空间智能体:大屏端 Dify Agent 设计
文档版本:v1.0 更新日期:2026-07-30 定位:大屏端 Dify Agent 的设计方案。
⚠️ 说明:本文档基于奇瑞项目交付期的 ChatBI 能力现状(模式一:意图 ↔ dashboard_id)编写。当前 ChatBI 方案是轻量集成方案,与标准ChatBI存在较大差距,详见附录 B。
1. 背景
AI 团队前期为苏州科技馆项目基于 Coze 平台定制了大屏智能体,实现了意图分类、ChatBI 数据查询、FAQ 问答、天气查询等能力,与数字孪生团队的大屏端深度集成。
当前正在进行产品化转型——基于 Dify 平台构建通用大屏 Agent,可适配所有数字孪生项目(科技馆、智慧园区、智慧城市等)。
1.1 与科技馆 Coze 方案的对比
科技馆 Coze 工作流结构(供参考):
| 维度 | 科技馆 Coze 方案 | 本次 Dify 产品化方案 |
|---|---|---|
| 平台 | Coze | Dify |
| 意图分类 | 问数 / 运维月报 / 其他(三分类,科技馆特有) ❌ Agent 理解「运维月报」等具体业务概念 | QA / DATA(二分类,其余全部归入 QA) ✅ Agent 只做通用分类,不碰业务语义 |
| ChatBI | 子流程调用(无问题改写) | 增加问题改写节点 + 扩展输出协议 |
| 月报能力 / 业务语义 | ❌ Coze 独立「运维月报」意图 + 硬编码业务逻辑,Agent 理解具体业务概念 | ✅ 不独立成意图,归入 DATA(ChatBI),Agent 只做通用分类,不碰业务语义 |
| 天气查询 | 独立 Coze 定时任务每天拉取天气写入 DB,Agent 查询时读表 | 待定(见附录) |
| QA 问答 | 内嵌在 Agent prompt 中的 FAQ | 独立 QA_Chat Agent,复用移动端设计 |
| 多意图 | 意图澄清节点处理 | 沿用相同策略,Master/Dify 层澄清 |
| 输出协议 | text + display_type | 扩展为 text + display_type + action(支持大屏指令) |
| 前端渲染 | Chat Box 内渲染图表 | 新增 Unity 大屏联动模式(dashboard 切换) |
1.2 与数字人讲解的关系
大屏 Dify Agent 是数字人讲解场景中的可选增值层:
Unity 本地指令识别(14B 模型)
├── 命中菜单/讲解控制 → Unity 直接执行(脚本不中断)
└── 未命中 → Dify Agent(本设计范围)
├── DATA → Data_Query 子流程(ChatBI)
└── QA(兜底,含知识库问答 / 闲聊 / 模糊输入)2. 整体架构
2.1 系统分层
┌─────────────────────────────────────────────────┐
│ Unity / 前端 │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ 唤醒词 │ │ 语音 ASR │ │ Chat Box + │ │
│ │ (本地) │ │ (本地) │ │ 数字人播报 │ │
│ └──────────┘ └────┬─────┘ └───────────────┘ │
│ │ ASR 文本 │
│ ▼ │
│ ┌──────────────────┐ │
│ │ 本地指令识别 (14B)│ │
│ └────┬─────────────┘ │
│ 命中 │ 未命中 │
│ (执行) │ 转发 │
└─────────────────┼─────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ Dify Agent(本设计范围) │
│ │
│ ┌──────────────────────────────┐ │
│ │ 入口网关 │ │
│ │ · 输入清洗 │ │
│ │ · 注入项目上下文(project_id, │ │
│ │ api_base, access_token 等) │ │
│ └──────────┬───────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ 意图分类 │ │
│ │ QA / DATA(其余归入 QA) │ │
│ └──┬───────────┬───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────┐ ┌──────────────────┐ │
│ │ QA │ │ Data_Query │ │
│ │ 子流程 │ │ 子流程 │ │
│ │ │ │ ① 问题改写 │ │
│ │ (复用 │ │ ② 调用 ChatBI │ │
│ │ 移动端 │ │ ③ 输出格式化 │ │
│ │ 设计) │ │ │ │
│ └────┬───┘ └───────┬──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────┐ │
│ │ 输出处理 │ │
│ │ · 格式化 answerDone 协议 │ │
│ │ · 含 text / display_type / │ │
│ │ action 字段 │ │
│ └──────────┬───────────────────┘ │
│ ▼ │
│ answerDone → Unity │
└──────────────────────────────────────────────────┘2.2 核心设计决策
| 决策 | 结论 | 理由 |
|---|---|---|
| 是否传多轮对话给 ChatBI | 不传,传单句 + 项目上下文 | ChatBI 查询独立,多轮对话由 Dify 层改写补全 |
| QA 是否独立设计 | 不独立设计 | 复用移动端 QA_Chat Agent 设计,仅调整输出协议适配大屏 |
3. Dify 工作流设计
3.1 入口网关
职责:输入清洗与项目上下文注入。
输入:
user_input: 用户原始文本(Unity 未命中的 ASR 结果)project_context: 项目级变量(由实施人员配置)
项目级变量表:
project_context:
project_id: "xxx" # 当前项目 ID
project_name: "苏州科技馆" # 项目名称(供 LLM 参考)
api_base: "https://api.example.com" # 业务系统 API 基地址
access_token: "Bearer xxx" # API 访问令牌
kb_space_id: "xxx" # 知识库空间 ID输出:清洗后的文本 + 注入的 project_context(传递给下游所有节点)。
3.2 意图分类节点
System Prompt 核心逻辑:
# 任务
判断用户问题的意图类别,仅输出以下两类之一。
# 意图定义
## DATA - 数据查询
用户查询动态实时数据:统计、趋势、对比、排名等。
示例:"上个月电费多少"、"今天人流量"、"哪个楼层能耗最高"
## QA - 知识问答(兜底)
所有不属于 DATA 的输入均归入 QA,包括:
- 静态知识:项目概况、公司信息、设备说明、流程指引
- 闲聊:问候、寒暄
- 模糊输入:无法清晰归类的表达
# 输出格式
{"intent": "DATA|QA", "confidence": 0.0-1.0}路由规则:
| 意图 | 路由目标 | 备注 |
|---|---|---|
| DATA | Data_Query Agent 子流程 | 直接路由 |
| QA | QA Agent 子流程 | 所有非 DATA 的输入均归入 QA |
3.3 QA Agent 子流程
设计原则:复用移动端 QA_Chat Agent 设计,不重复设计。
处理流程:
用户问题
↓
场景分类(LLM):寒暄对话 / 知识问答 / 模糊输入
↓
[知识问答] → 知识库向量检索 → LLM 增强生成
[寒暄对话] → LLM 直接生成回复
[模糊输入] → 澄清反问
↓
输出格式化 → answerDone与大屏端的适配点:
| 适配项 | 说明 |
|---|---|
| 输出格式 | 遵循 answerDone 协议(见 §4) |
| 回复长度 | 适配语音播报场景,建议控制在 100 字以内 |
| 知识库 | 每个项目独立知识库空间,实施时配置 |
3.4 Data_Query Agent 子流程(ChatBI 对接)
这是本设计的核心部分,包含三个节点。
3.4.1 节点一:问题改写
时机:在将用户问题发送给 ChatBI 之前,由 Dify Agent 做一轮问题改写。
目的:
- 补全上下文:用户说"那上个月呢?" → 改写为"上个月的用电量是多少"
- 去除口语废话:将语音 ASR 结果中的重复、口误、语气词清理干净
- 提取关键参数:时间范围、指标、空间等
实现方式:Dify LLM 节点 + 改写 Prompt
# 任务
将用户的问题改写为适合数据查询的简洁表述。如果用户问题缺少上下文
(如"那上个月呢""和之前比呢"),需要根据对话历史补全。
# 规则
1. 保留核心查询意图(指标、时间、空间、对比对象)
2. 去除语气词、重复、口误
3. 补全指代不明的上下文
4. 改写后的问题要包含完整的查询条件
# 输入
用户问题:{{user_input}}
最近对话摘要:{{chat_history_summary}}
# 输出
仅输出改写后的问题文本,不要解释。3.4.2 节点二:调用 ChatBI API
工具类型:Dify HTTP Request 节点
请求参数:
POST {{project_context.api_base}}/chatbi/query
Headers:
Authorization: {{project_context.access_token}}
Content-Type: application/json
Body:
{
"query": "{{rewritten_question}}",
"project_id": "{{project_context.project_id}}",
"agent_id": 1,
"chat_id": "-1",
"client_type": "BS"
}| 参数 | 值 | 说明 |
|---|---|---|
query | 改写后的问题 | 由问题改写节点输出 |
project_id | 项目 ID | 项目级变量注入 |
agent_id | 1 | ChatBI 内部使用的 Agent 类型标识,可与 ChatBI 团队确认具体含义 |
chat_id | "-1" | -1 表示新建会话。如需多轮上下文管理可与 ChatBI 团队协商策略 |
client_type | "BS" | 大屏端标识 |
响应格式(预期):
{
"summary": "本月用电量 12,500 kWh,较上月下降 5.2%",
"dataset": [
{"month": "2026-06", "value": 13180},
{"month": "2026-07", "value": 12500}
],
"chart_type": "bar",
"action": {
"type": "dashboard" | "chart",
"dashboard_id": "energy_overview"
}
}超时与错误处理:
| 场景 | 处理 |
|---|---|
| ChatBI 超时(>10s) | 返回"数据查询服务暂时繁忙,请稍后再试" |
| ChatBI 返回空数据 | 返回"未查询到相关数据,请换个问题试试" |
| ChatBI 返回错误 | 记录错误日志,返回友好提示 |
3.4.3 节点三:输出格式化
职责:将 ChatBI 原始响应转换为统一的 answerDone 协议格式。
实现:Dify Code 节点
def main(chatbi_response: dict) -> dict:
action_type = chatbi_response.get("action", {}).get("type", "chart")
result = {
"summary": chatbi_response.get("summary", ""),
"display_type": "chatbi",
"dataset": chatbi_response.get("dataset", []),
"chart_type": chatbi_response.get("chart_type", ""),
"action": {
"type": action_type,
# 如果是仪表盘模式,带 dashboard_id
"dashboard_id": chatbi_response.get("action", {}).get("dashboard_id", "")
}
}
# 仪表盘模式:chat_box 只显示 summary,大屏页交由 Unity 切换
# 动态图表模式:summary + dataset 在 chat_box 中渲染
return result3.5 ChatBI 两种模式的详细说明
模式一:仪表盘召回(推荐优先实现)
用户问"能耗数据怎么样"
→ 问题改写(保留原意)
→ ChatBI 判断意图 → 匹配到预置仪表盘 "energy_dashboard"
→ 返回 action.type = "dashboard", dashboard_id = "energy_dashboard"
→ Dify 包装为 answerDone
→ Unity 解析 action → 调用大屏切换接口 → 切换到能耗仪表盘页面
→ Chat Box 同时显示 summary 文字特点:
- 响应快:2-3s 即可完成
- 实现简单:ChatBI 只需做意图→仪表盘 ID 的映射
- 体验好:切换整张大屏,视觉冲击强
前提:需要实施人员提前配置好"意图→仪表盘 ID"的映射表。
模式二:动态图表生成
Coze 方案中 ChatBI 已支持动态图表——返回 dataset 和 chart_type,前端 Chat Box 内渲染图表。
用户问"对比过去六个月各楼层的用电量"
用户问"对比过去六个月各楼层的用电量"
→ 问题改写(提取时间范围、指标、分组维度)
→ ChatBI 查询数据源 → 返回数据集
→ ChatBI 根据数据特征选择图表类型(柱状图/折线图等)
→ 返回 summary + dataset + chart_type
→ Dify 透传给 Unity
→ Chat Box 渲染图表组件
→ (不切换大屏页面)特点:
- 响应慢:10s+
- 实现复杂:需要 ChatBI 具备动态图表类型选择能力
- 渲染在 Chat Box 内,不涉及大屏切换
4. 输出协议(answerDone)
4.1 协议格式
{
"summary": "文字回复摘要(必填)",
"display_type": "text | chatbi | qa",
"action": {
"type": "none | switch_dashboard | render_chart",
"dashboard_id": "" // 仅 type=switch_dashboard 时有效
},
"dataset": [], // 仅 display_type=chatbi 时有效
"chart_type": "" // 仅 display_type=chatbi 时有效
}4.2 字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
summary | string | 是 | 文字摘要,始终显示在 Chat Box + 语音播报 |
display_type | enum | 是 | 渲染模式:text(纯文字)、chatbi(数据图表)、qa(问答引用) |
action.type | enum | 否 | Unity 大屏联动:none(不操作)、switch_dashboard(Unity 切换大屏页面)、render_chart(Chat Box 内渲染图表) |
action.dashboard_id | string | 否 | 目标仪表盘 ID,仅 switch_dashboard 时使用 |
dataset | array | 否 | 图表数据,仅 render_chart / chatbi 时使用 |
chart_type | string | 否 | 图表类型:bar/line/pie/table |
4.3 各场景输出示例
QA 纯文字回答:
{
"summary": "苏州科技馆总建筑面积约 6.3 万平方米",
"display_type": "qa",
"action": {"type": "none", "dashboard_id": ""}
}ChatBI 仪表盘模式:
{
"summary": "已为您切换到能耗总览看板",
"display_type": "chatbi",
"action": {"type": "switch_dashboard", "dashboard_id": "energy_overview"},
"dataset": [],
"chart_type": ""
}ChatBI 动态图表模式:
{
"summary": "近六个月用电量呈下降趋势,7月较2月下降18%",
"display_type": "chatbi",
"action": {"type": "render_chart", "dashboard_id": ""},
"dataset": [
{"month": "2026-02", "value": 15200},
{"month": "2026-03", "value": 14800},
{"month": "2026-04", "value": 14100},
{"month": "2026-05", "value": 13500},
{"month": "2026-06", "value": 13180},
{"month": "2026-07", "value": 12500}
],
"chart_type": "bar"
}5. 前端交互设计
5.1 交互形态
大屏端交互复刻科技馆已验证的模式,不做重新设计:
| 能力 | 说明 | 来源 |
|---|---|---|
| 唤醒词 | 本地语音唤醒 → 数字人出现 + Chat Box 弹出 | 科技馆复刻 |
| 语音输入 | ASR 识别用户语音 | 科技馆复刻 |
| Chat Box | 展示文字对话内容 | 科技馆复刻 |
| 语音播报 | TTS 数字人发声 | 科技馆复刻 |
| 数字人动作 | 说话时匹配基础动作 | 科技馆复刻 |
5.2 ChatBI 图表渲染
仪表盘模式(快速):
- Chat Box 显示 summary 文字
- Unity 大屏切换到目标仪表盘页面
- 数字人说"已为您切换到能耗看板"
动态图表模式(慢速):
- Chat Box 显示加载状态 + "正在查询数据..."
- 数据返回后 Chat Box 内渲染图表组件(柱状图/折线图等)
- 数字人配合 summary 做语音播报
- 大屏页面不切换
5.3 加载状态与超时处理
复用科技馆现有实现,不做重新设计。关键原则:
- ChatBI 查询期间前端显示加载态(科技馆已有方案)
- 超时/错误由前端统一拦截并展示友好的提示文案
6. 部署与配置
6.1 Dify 工作流模板
实施人员部署流程:
- 导入 Dify 工作流模板(DSL 文件)
- 配置项目级变量(project_context)
- 配置知识库(绑定项目知识库空间)
- 配置 ChatBI 仪表盘映射表(可选)
- 配置输出协议中的 Unity 回调地址
6.2 环境要求
| 依赖 | 说明 |
|---|---|
| Dify 平台 | 必须部署并运行 Dify 服务 |
| ChatBI 服务 | 可选,无 ChatBI 时 DATA 意图走兜底 |
| 知识库 | 每个项目至少一个知识库空间 |
7. 待确认事项
| 事项 | 说明 | 状态 |
|---|---|---|
| ChatBI agentId 含义 | 1 是否固定,还是可配 | 需与 ChatBI 团队确认 |
| ChatBI 多轮会话 | chatId=-1 是否始终新建会话,还是需要维护 | 需与 ChatBI 团队确认 |
| ChatBI API 精确路径 | /chatbi/query 是否准确 | 需确认接口文档 |
| 仪表盘 ID 映射 | 意图到 dashboard_id 的配置方式 | 需实施团队确认 |
| 动态图表组件 | Chat Box 内是否已有图表渲染组件 | 需前端团队确认 |
附录 A:天气查询问题(待决策)
背景
科技馆 Coze 方案中通过独立定时任务每天拉取天气写入 DB 表,Agent 在查询时走 select_record 节点读表。产品化后需要重新选择天气查询方案。
三个候选方案
方案一:RAG 覆盖写入(推荐方向)
做法:维护一个固定的「今日天气」文档在 Dify 知识库中。定时任务每天调天气 API → 覆盖写入该文档(非追加)。用户问天气时,QA Agent 正常走 RAG 检索,自然命中该文档。
优点:
- 零额外性能损耗——不查天气时 RAG 检不出该文档(不相关),不需要任何分支判断
- 不增加流程复杂度——QA Agent 不需要加天气判断节点
- 可扩展——今日活动、今日公告等动态信息同机制接入
- 只有一条记录,不存在新旧混淆问题
缺点:
- 依赖 RAG 对"今天"语义的匹配准确度(大概率够用,但需验证)
- 需实现定时写入知识库 API 的机制
方案二:QA 分支内调 Tool 节点
做法:QA Agent 流程中增加一个子判断节点。当模型判断用户在问天气时,调用 HTTP Tool 节点(复用智能整备已有的百度天气 URL 或独立配置)查询实时天气;非天气问题正常走知识库 RAG。
优点:
- 实时准确,不依赖定时任务
- 实现简单,Workflow 内加一个节点即可
缺点:
- 每次 QA 都多一次子判断(~0.5-1s),即使不问天气
- 可扩展性差——今天加天气分支,明天加活动分支,后天加公告分支,QA Agent 流程会膨胀
- 需维护 API Key
→ 个人倾向此方案
方案三:定时任务 + DB 表(科技馆方案)
做法:独立定时任务每天拉取天气写入结构化 DB 表。QA Agent 分支内判断是天气时走 select_record 节点读取。
优点:
- 查询快(读表而非 API 调用)
- 科技馆已验证可行
缺点:
- 定时任务无差别写入——不管用户问不问天气都跑
- 多维护一个定时任务 + DB 表
- 扩展新能力仍需在 QA 内加新分支,同方案二的可扩展性问题
建议
推荐优先评估方案一(RAG 覆盖写入),其零额外损耗 + 可扩展性优势最明显。如果 RAG 对时间语义的匹配准确度经过验证不达标,回退到方案二。
附录 B:ChatBI 能力调研与现状定位
背景
与 ChatBI 团队沟通后,了解到他们目前有三种能力模式。需要说明的是,当前大屏端采用的**模式一(意图 ↔ dashboard_id)**本质上是一种轻量集成方案——ChatBI 不取数、不渲染、不生成,只做意图到 ID 的映射。这与理想中的产品化 ChatBI(理解语义→动态取数→智能渲染)有较大差距。
从演进脉络看:
| 阶段 | 项目 | ChatBI 角色 | 评价 |
|---|---|---|---|
| 定制化 | 科技馆(Coze) | 取数 + 返回 dataset,前端渲染图表 | ChatBI 承担了真正的数据查询职能 |
| 交付期 | 奇瑞(当前) | 意图 → dashboard_id,内容全由数字孪生负责 | 务实集成方案,快速交付但能力有限 |
| 产品化 | 理想态 | 语义理解 → 动态 SQL → 取数 → 智能选图表渲染 | 全链路动态,灵活通用 |
当前文档设计以奇瑞交付期方案为准——模式一接入,快速上线。产品化演进方向后续讨论。以下为三种模式的详细调研记录。
三种模式
模式一:意图 ↔ Dashboard ID 绑定(大屏端用)
做法:ChatBI 只做意图识别,输出一个 dashboard_id。具体 dashboard 的配置(样式、数据源、布局)完全由数字孪生团队在数字孪生平台中自行配置(该平台本身支持配置 dashboard)。
流程:
用户说"看能耗数据"
→ ChatBI 识别意图 → 匹配到预置映射 "能耗总览" ↔ "dashboard_energy_001"
→ 返回 dashboard_id
→ Unity 接收后切换到对应 dashboard 页面特点:
- ChatBI 不关心 dashboard 内部有什么 — 不取数、不渲染、不关心样式
- 数字孪生团队自行配置 dashboard 内容和布局
- 数字孪生平台本身已支持多 dashboard 管理
- ChatBI 只需维护一张映射表:
{唤醒词/问题提示词 → dashboard_id}
优点:响应快(意图匹配即可),集成成本最低 缺点:静态映射,不支持动态查询
配置说明:
- dashboard 的内容(表、样式、数据源)由数字孪生实施人员在数字孪生平台中配置,平台本身已支持
- 配置 dashboard 自然产出 dashboard_id
- Dify/ChatBI 侧只需维护一张轻量映射表:
{唤醒词 → dashboard_id},例如 5 个主题对应 5 个 dashboard_id
模式二:问题 ↔ 内置 SQL(移动端 / Web 端用)
做法:ChatBI 管理一个问题库,每个问题绑定一条固定 SQL。用户提问 → 匹配问题 → 执行 SQL → 根据返回数据自动选图表样式 → 渲染。
流程:
用户说"上月用电量"
→ ChatBI 匹配到问题 "上月用电量" → 取出绑定的 SQL
→ 执行 SQL → 拿到数据 → 自动选图表类型 → 渲染问题:SQL 不支持变量。例如无法在 SQL 中动态传入日期参数,无法实现"查哪个月就传哪个月"。这意味着每查一个月就得配一条独立的问题+SQL。
特点:
- 问题与 SQL 严格绑定
- 渲染由 ChatBI 自己完成(自动选图表类型)
- 数据由 ChatBI 自己取
优点:对固定报表查询体验好,渲染效果可控 缺点:不支持变量,灵活性差,问题/SQL 数量随需求线性膨胀
模式三:全动态生成(通用能力)
做法:用户提问 → 匹配数据集的元数据定义 → 动态生成 SQL → 动态取数 → 动态选图表渲染。这是业界对 ChatBI 的常规理解。
特点:
- 不依赖预置问题或 SQL
- 通过语义理解匹配数据集元数据
- 全链路动态
优点:灵活性最高,任意查询 缺点:速度慢(全链路动态),实现复杂度高
对本次大屏端设计的直接影响
大屏端当前集成 模式一(意图 ↔ dashboard_id)。这意味着:
- Data_Query 子流程的 ChatBI API 调用需要调整为:传入用户问题 → 返回 dashboard_id(而非返回 dataset + chart_type)
- 输出协议中
action.type=switch_dashboard是唯一路径,render_chart当前不适用于大屏端 dataset和chart_type字段在大屏端暂时不需要,待后续 ChatBI 能力升级后再扩展- 映射表需要实施人员配置:一组唤醒词/问题提示词 → dashboard_id(数字孪生团队配 dashboard,实施团队配映射)
短期策略:以模式一集成,项目交付优先。长期优化方向待后续探讨。
