Skip to content

空间智能体:大屏端 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 产品化方案
平台CozeDify
意图分类问数 / 运维月报 / 其他(三分类,科技馆特有)
❌ 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: 项目级变量(由实施人员配置)

项目级变量表

yaml
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 核心逻辑

markdown
# 任务
判断用户问题的意图类别,仅输出以下两类之一。

# 意图定义
## DATA - 数据查询
用户查询动态实时数据:统计、趋势、对比、排名等。
示例:"上个月电费多少"、"今天人流量"、"哪个楼层能耗最高"

## QA - 知识问答(兜底)
所有不属于 DATA 的输入均归入 QA,包括:
- 静态知识:项目概况、公司信息、设备说明、流程指引
- 闲聊:问候、寒暄
- 模糊输入:无法清晰归类的表达

# 输出格式
{"intent": "DATA|QA", "confidence": 0.0-1.0}

路由规则

意图路由目标备注
DATAData_Query Agent 子流程直接路由
QAQA 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

markdown
# 任务
将用户的问题改写为适合数据查询的简洁表述。如果用户问题缺少上下文
(如"那上个月呢""和之前比呢"),需要根据对话历史补全。

# 规则
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_id1ChatBI 内部使用的 Agent 类型标识,可与 ChatBI 团队确认具体含义
chat_id"-1"-1 表示新建会话。如需多轮上下文管理可与 ChatBI 团队协商策略
client_type"BS"大屏端标识

响应格式(预期):

json
{
  "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 节点

python
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 result

3.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 已支持动态图表——返回 datasetchart_type,前端 Chat Box 内渲染图表。

用户问"对比过去六个月各楼层的用电量"
用户问"对比过去六个月各楼层的用电量"
  → 问题改写(提取时间范围、指标、分组维度)
  → ChatBI 查询数据源 → 返回数据集
  → ChatBI 根据数据特征选择图表类型(柱状图/折线图等)
  → 返回 summary + dataset + chart_type
  → Dify 透传给 Unity
  → Chat Box 渲染图表组件
  → (不切换大屏页面)

特点

  • 响应慢:10s+
  • 实现复杂:需要 ChatBI 具备动态图表类型选择能力
  • 渲染在 Chat Box 内,不涉及大屏切换

4. 输出协议(answerDone)

4.1 协议格式

json
{
  "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 字段说明

字段类型必填说明
summarystring文字摘要,始终显示在 Chat Box + 语音播报
display_typeenum渲染模式:text(纯文字)、chatbi(数据图表)、qa(问答引用)
action.typeenumUnity 大屏联动:none(不操作)、switch_dashboard(Unity 切换大屏页面)、render_chart(Chat Box 内渲染图表)
action.dashboard_idstring目标仪表盘 ID,仅 switch_dashboard 时使用
datasetarray图表数据,仅 render_chart / chatbi 时使用
chart_typestring图表类型:bar/line/pie/table

4.3 各场景输出示例

QA 纯文字回答

json
{
  "summary": "苏州科技馆总建筑面积约 6.3 万平方米",
  "display_type": "qa",
  "action": {"type": "none", "dashboard_id": ""}
}

ChatBI 仪表盘模式

json
{
  "summary": "已为您切换到能耗总览看板",
  "display_type": "chatbi",
  "action": {"type": "switch_dashboard", "dashboard_id": "energy_overview"},
  "dataset": [],
  "chart_type": ""
}

ChatBI 动态图表模式

json
{
  "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 工作流模板

实施人员部署流程:

  1. 导入 Dify 工作流模板(DSL 文件)
  2. 配置项目级变量(project_context)
  3. 配置知识库(绑定项目知识库空间)
  4. 配置 ChatBI 仪表盘映射表(可选)
  5. 配置输出协议中的 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)。这意味着:

  1. Data_Query 子流程的 ChatBI API 调用需要调整为:传入用户问题 → 返回 dashboard_id(而非返回 dataset + chart_type)
  2. 输出协议中 action.type=switch_dashboard 是唯一路径render_chart 当前不适用于大屏端
  3. datasetchart_type 字段在大屏端暂时不需要,待后续 ChatBI 能力升级后再扩展
  4. 映射表需要实施人员配置:一组唤醒词/问题提示词 → dashboard_id(数字孪生团队配 dashboard,实施团队配映射)

短期策略:以模式一集成,项目交付优先。长期优化方向待后续探讨。

Released under the Private License.