魔珐星云为城市展厅 Agent 加个身体:让任务执行拥有具身交互智能表达界面

摘要

做过一版“城市数字人”,效果一般:数字人站在那儿,嘴里念着写好的稿子,旁边的 BI 大屏各播各的,两者没什么关系。复盘时我意识到:这不是某个功能没做好,是架构没想清楚。

这篇我用“重做一遍”的视角,把城市数据讲解 Agent 的架构逐层推演一遍:Agent 可以负责理解问题、调度数据、组织讲解,但纯文本 Agent 缺少具身落地载体。魔珐星云依托 AI 端渲和解算 + 自研参数流,为这类 Agent 补齐可看、可听、可打断的具身交互智能表达层,让城市数据讲解真正进入展厅终端。

魔珐星云具身智能数字人开放平台:魔珐星云具身智能3D数字人开放平台 - 全球领先的3D具身智能体基础设施

一、推演的起点:先定“什么叫讲数据”

旧版的问题在于没回答一个根本问题:数字人"讲数据"和 BI 大屏"显示数据",到底是不是一回事?

显然不是这样,大屏侧重数据直观可视化,而具身交互智能体依托完整多模态交互能力,结合用户提问、实时图表动态组织讲解逻辑。它绝非大屏配套录音旁白,而是具备倾听、思考、实时讲解能力的可视化数据解说智能体。

**前者重精度重信息密度,后者重节奏重理解路径。**一个城市数字人,如果只是把大屏上的数字念一遍,那要数字人干嘛,TTS 不就行了?

所以重做的第一性原则:数字人不是大屏的旁白,是 Agent 面向用户的具身交互智能表达界面。它要根据用户的问题、结合大屏正在显示的图表,组织一条“听得懂”的讲解路径。

这条原则决定了后面的架构:感知、认知、表达三层,每一层都要为“讲数据”服务。Agent 负责理解、生成和任务执行,魔珐星云通过 AI 端渲、端侧解算与参数流,把这些能力落到可看、可听、可交互的终端表达里。

二、数据从哪来——大屏与内容库同源

2.1 痛点:数字人和大屏的数据对不上

第一个要解决的问题:数字人讲的数据,和大屏显示的数据,必须同源,否则会打架。如果数字人嘴里念的是 2.1 万亿、大屏上写的是 2.186 万亿,用户一眼就看出来"这俩对不上",可信度瞬间崩。

2.2 架构决策:大屏与内容库同源

参考实现里,中间面板是基于 ECharts 5.6 的暗色科技风数据大屏,6 类图表:杭州人口发展折线图、GDP 增长柱状图、"5+5+5"现代产业体系饼图、各区县 GDP 散点分布图、数字经济占比仪表盘、科技创新雷达图。这些图表的数据,和内容库(contentLibrary.ts,8 大分类:历史/文化/规划/地标/经济/科技/生态/民生)里的真实 2024 年城市数据(GDP 2.186万亿、数字经济占比 28.8%、常住人口 1262.4 万等)是同一份。

**一处维护,两处消费——大屏画图,数字人讲解。**这样数字人讲的内容和大屏显示的永远对得上。

内容库 contentLibrary.ts
        (杭州真实城市数据:GDP 2.186万亿、数字经济占比 28.8%…)
           ↙            ↘
   ECharts 大屏画图      数字人讲解词
   (6 类图表)          (同源数据,不会打架)

在这里插入图片描述

三、用户提问,怎么找到对应内容——国产向量模型Qwen3-Embedding 语义检索

3.1 痛点:关键词匹配太脆

用户问"杭州数字经济怎么样",系统怎么从内容库里找到对应的那几条?关键词匹配太脆——用户会说"数字经济"“数字产业”“杭州的互联网经济”,措辞千变万化,靠关键词命中漏得离谱。

3.2 架构决策:Qwen3-Embedding 语义检索

国产向量模型 Qwen3-Embedding-8B(4096 维)做语义检索:

async getEmbedding(text: string): Promise<number[]> {
  const response = await fetch(`${this.baseURL}/embeddings`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` },
    body: JSON.stringify({
      model: 'Qwen/Qwen3-Embedding-8B',
      input: text,
      encoding_format: 'float'
    })
  })
  // 先判状态:鉴权失败 / 限流 / 服务异常都不会有 data.data[0],否则下面取值会抛错且前端拿不到清晰提示
  if (!response.ok) {
    const errMsg = await response.text().catch(() => response.statusText)
    throw new Error(`向量服务请求失败(${response.status}):${errMsg}`)
  }
  const data: EmbeddingResponse = await response.json()
  return data.data[0].embedding
}

流程是:内容库预计算向量存 embeddings.json → 用户提问实时算向量 → 余弦相似度匹配(阈值 0.6)→ 返回 Top-K 相关内容卡片。

在这里插入图片描述

四、找到了内容,怎么"讲"出来——Qwen3-VL 流式生成 + 文本净化

4.1 架构决策:Qwen3-VL 流式生成

检索回来的是结构化数据片段,怎么变成"人听得懂的话"?这里要一个会组织的对话模型。用国产多模态大模型 Qwen3-VL-235B-A22B-Instruct,把检索到的内容作为上下文,流式生成讲解词:

async multimodalChat(messages: Array<{ role: string; content: any }>, onChunk?: (text: string) => void): Promise<string> {
  const response = await fetch(`${this.baseURL}/chat/completions`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` },
    body: JSON.stringify({
      model: 'Qwen/Qwen3-VL-235B-A22B-Instruct',
      messages,
      stream: true
    })
  })
  // 流式接口同样要先判状态,否则 handleStreamResponse 会拿到非 SSE 的错误体(鉴权失败 / 限流 / 服务异常)
  if (!response.ok) {
    const errMsg = await response.text().catch(() => response.statusText)
    throw new Error(`对话服务请求失败(${response.status}):${errMsg}`)
  }
  return this.handleStreamResponse(response, onChunk)   // SSE 流式解析
}

为什么选多模态 VL 而不是纯文本模型?因为城市数据讲解经常要"看着图讲"——后续可以让模型直接读大屏截图,结合图表内容生成讲解词,这是纯文本模型做不到的。

4.2 架构决策:文本净化层(最容易被忽略的中间层)

有个容易被忽略的细节:模型流式吐出来的文本带 markdown、emoji、各种符号,直接喂给数字人会念出"井号星号",很难听。所以中间加了一道 optimizeTextForAvatar 净化——去 markdown、去 emoji、中文标点化——再喂给数字人。

在这里插入图片描述

生成层和表达层之间,必须有这道净化层。这一步不做,数字人念出来全是符号,瞬间出戏。

在这里插入图片描述

五、数字人怎么"动"起来——魔珐星云端侧渲染 + 参数流 + 状态机

魔珐星云具身智能数字人开放平台:魔珐星云具身智能3D数字人开放平台 - 全球领先的3D具身智能体基础设施

5.1 架构决策:魔珐星云端侧渲染

文本有了,数字人怎么讲?

本层是整套具身交互智能核心承载层,依托魔珐星云自研参数流 + AI 端侧渲染这套标志性底层能力;3D 形象、表情、肢体全部在终端本地解算渲染,云端仅下发轻量化驱动参数,无需传输完整视频,实现≤500ms 首字流畅交互,是真人式实时沟通的基础保障。

SDK 实例化和流式 speak(实现 client/src/services/AvatarService.ts):

// 1. 创建 SDK 实例(端侧渲染 / 端侧解算,通过 gatewayServer 建立 TTSA 会话)
this.sdk = new window.XmovAvatar({
  containerId: `#${this.containerId}`,
  appId: this.config.xingyunAppId,
  appSecret: this.config.xingyunAppSecret,
  gatewayServer: 'https://nebula-agent.xingyun3d.com/user/v1/ttsa/session',
  onVoiceStateChange: (status: string) => {
    // status 枚举以魔珐星云 SDK 实际回调为准,这里按 'end' 判定朗读完成(落地时按 SDK 文档做状态映射)
    if (status === 'end' && this.speakCompleteCallback) {
      this.speakCompleteCallback()    // 朗读完成,可触发下一步交互
      this.speakCompleteCallback = null
    }
  },
  enableLogger: false
})

// 2. 异步初始化(下载数字人资源)
await this.sdk.init({
  onDownloadProgress: (progress: number) => callbacks?.onDownloadProgress?.(progress)
})

5.2 架构决策:流式 speak 缓冲区 + 三段式标记

// 3. 流式语音播报(适配 AI 流式输出:每次只传新增片段,不累加全文)
speak(text: string, isStart = true, isEnd = true, interrupt = true): void {
  if (interrupt && isStart) this.stopSpeaking()    // 打断上一轮
  // 关键:每次只把"新增片段 text"喂给 SDK,绝不累计全文——
  // 否则多段流式会让数字人把前面内容反复念一遍(重复播报)
  this.sdk.speak(text, isStart, isEnd)             // 驱动数字人语音+口型
  if (isEnd) { this.currentState = AvatarState.SPEAK }
}

三段式 speak 接口是具身交互智能关键流式驱动能力,speak(text, isStart, isEnd) 控制流的起承转合,配合 speakBuffer 累积分片,适配 AI 流式输出的到达节奏,避免数字人语音断续。

5.3 架构决策:状态机让数字人有"讲数据"的节奏

倾听、思考、讲解、待机四态状态机,是区分单向视频录播与原生具身交互智能的核心设计,复刻真人讲解员沟通节奏,实现双向实时交互。

// 4. 状态机切换(具身交互)
setState(state: AvatarState): void {
  switch (state) {
    case AvatarState.LISTEN:           this.sdk.listen(); break          // 倾听
    case AvatarState.THINK:            this.sdk.think(); break           // 思考
    case AvatarState.INTERACTIVE_IDLE: this.sdk.interactiveidle(); break // 互动待机
    case AvatarState.OFFLINE:          this.sdk.offlineMode(); break     // 离线省积分
  }
}

**整体流程:**用户问→数字人想→数字人讲→讲完待机。

在这里插入图片描述

六、大屏和数字人怎么真正联动——switchChart 同步

6.1 痛点:旧版大屏和数字人割裂

这是旧版翻车的点。用户点了一个数据卡片,大屏切到了对应图表,但数字人还在念上一段稿子——视觉和听觉各干各的,用户一脸问号。

6.2 架构决策:一次点击,两条并行链路

重做时必须解决:用户点了数据卡片,大屏要切到对应图表,数字人要同步开始讲这个图表

参考实现里,用户点击左侧内容卡片时,前端同时做两件事:① 调 switchChart 把中间大屏切到对应图表;② 把这个内容作为上下文调 Qwen3-VL 流式生成讲解词,净化后喂给数字人 speak

大屏切换和数字人讲解是同一个用户动作触发的两条并行链路,共享同一个内容上下文。不是"先切大屏再调数字人",而是"一次点击,大屏切图 + 数字人开讲"并行启动。这样视觉和听觉同步,用户点哪个讲哪个,真正的"数据看板数字人"。

这是整条架构最关键的一跳——它把"数字人"和"大屏"从两个独立组件,形成大屏可视化与具身交互智能体一体化联动系统。

在这里插入图片描述

七、双国产模型怎么分工 + DeepSeek 的替换点

7.1 双国产模型分工

回到"国产大模型"这个切入点。这套架构里两个国产模型分工明确:

模型 角色 干什么
Qwen3-Embedding-8B 检索层 用户提问向量化,和内容库做语义匹配
Qwen3-VL-235B-A22B-Instruct
生成层 把检索结果组织成讲解词,流式输出,支持看图

两者都走统一 API,一个 key 通吃。这是"双国产模型协同"——检索和生成各司其职,不是一个大模型干所有事。

7.2 架构决策:模型职责分离,替换点单一

生成层就是一个 fetch 调用,模型名是参数。如果后续城市数据解读需要更深推理(比如多步数据对比、趋势预测),可以把生成层换成 DeepSeek-V3——只需改 model 字段和 base_url,架构不动。这就是模型无关架构的好处:国产大模型生态迭代很快,今天用 Qwen3-VL,明天换 DeepSeek,后天换更新的,落地架构不该绑死在某一个模型上。

八、总结

魔珐星云具身智能数字人开放平台:魔珐星云具身智能3D数字人开放平台 - 全球领先的3D具身智能体基础设施

推演完六层架构,重做后的城市数据数字人长这样:

用户提问 / 点击数据卡片
  → [检索层] Qwen3-Embedding-8B 语义匹配内容库(同源于大屏数据)
  → [生成层] Qwen3-VL 流式生成讲解词
  → [净化层] optimizeTextForAvatar 去 markdown/emoji
  → [表达层] 魔珐星云的端侧渲染 + 流式 speak(isStart/isEnd) + 状态机
  → [联动层] 大屏 switchChart ∥ 数字人 speak,同一动作并行

city-exhibition-guide/
├── client/ # Vue 3 前端应用
│ ├── src/
│ │ ├── api/ # API接口层
│ │ ├── components/ # Vue组件
│ │ │ ├── avatar/ # 数字人组件
│ │ │ ├── chat/ # 对话组件
│ │ │ ├── content/ # 内容组件
│ │ │ └── visualization/ # 可视化组件
│ │ ├── data/ # 数据文件
│ │ ├── router/ # 路由配置
│ │ ├── services/ # 业务服务
│ │ ├── stores/ # Pinia状态管理
│ │ ├── types/ # TypeScript类型
│ │ ├── views/ # 页面视图
│ │ ├── App.vue # 根组件
│ │ └── main.ts # 应用入口
│ ├── .env.example # 环境变量示例
│ ├── package.json # 前端依赖
│ ├── vite.config.ts # Vite配置
│ └── tsconfig.json # TypeScript配置

├── server/ # Node.js 后端服务
│ ├── src/
│ │ ├── config/ # 配置文件
│ │ ├── middleware/ # Express中间件
│ │ ├── routes/ # API路由
│ │ ├── services/ # 业务服务
│ │ ├── utils/ # 工具函数
│ │ └── index.ts # 服务器入口
│ ├── .env.example # 环境变量示例
│ └── package.json # 后端依赖

├── shared/ # 前后端共享代码
│ └── types/ # 共享类型定义

├── package.json # 根项目配置
├── README.md # 项目说明
└── .gitignore # Git忽略配置


六层架构的每一条决策,都对应一个旧版翻车的点:

旧版问题 重做决策
数字人念稿、和大屏无关 数据同源 + switchChart 联动
检索靠关键词,召回不准 Qwen3-Embedding 语义检索
讲解生硬、念符号 Qwen3-VL 流式 + 文本净化层
开口慢、像播录像 端侧渲染 + 参数流 + 流式 speak ≤500ms
模型绑死、难迭代 模型职责分离,替换点单一

技术栈上,国产大模型提供语义检索、数据推理的认知大脑;ECharts 大屏实现数据可视化感知;魔珐星云补齐全套具身交互智能,赋予 AI 具象躯体、同步神态、实时双向交互能力;三层体系协同,打造完整城市数据具身交互智能体。

魔珐星云具身智能数字人开放平台:魔珐星云具身智能3D数字人开放平台 - 全球领先的3D具身智能体基础设施

原文出自:鸽芷咕

原文链接:https://blog.csdn.net/qq_57761637/article/details/162969149

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐