732 lines
34 KiB
Markdown
732 lines
34 KiB
Markdown
|
|
# AI 对话链路全栈改造实施计划
|
|||
|
|
|
|||
|
|
> **版本**: v1.1
|
|||
|
|
> **日期**: 2026-07-13
|
|||
|
|
> **作者**: 宋献 (Simon) + Duckula
|
|||
|
|
> **状态**: ✅ 已实施并部署(Phase 1-6 全部完成,2026-07-13 01:38 生产部署)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 部署记录
|
|||
|
|
|
|||
|
|
### 2026-07-13 01:38 生产部署(v5)
|
|||
|
|
|
|||
|
|
| 组件 | 版本 | 部署内容 | 验证 |
|
|||
|
|
|------|------|---------|------|
|
|||
|
|
| **后端** | v5 | 6 个 Python 文件部署到 `/opt/wecom-it-desk/app/` | `docker compose restart backend` → healthy ✅ |
|
|||
|
|
| **H5 前端** | v4 | dist 部署到 `/opt/wecom-it-desk/frontend-h5/dist/` | JS hash `index-B6dzwk-X.js` ✅ |
|
|||
|
|
| **Agent 前端** | v5 | dist 部署到 `/opt/wecom-it-desk/frontend-agent/dist/` | JS hash `index-2BTn4SZz.js` ✅ |
|
|||
|
|
| **Nginx** | - | `nginx -s reload` | healthy ✅ |
|
|||
|
|
|
|||
|
|
**后端变更文件清单**(旧文件备份在 `/tmp/backend_bak_v5/`):
|
|||
|
|
|
|||
|
|
| 文件 | 变更内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `app/tasks/h5_ai_task.py` | VisionService 接入 + 图片消息融合 + ai_thinking 双推 + diagnosis_stage 存储 |
|
|||
|
|
| `app/api/h5.py` | `process_h5_ai_reply()` 调用新增 `msg_type` + `media_url` 参数 |
|
|||
|
|
| `app/services/ai_service.py` | `get_structured_reply()` blocking 模式 + JSON 解析 + `response_time_ms` 计时 + 慢响应告警 |
|
|||
|
|
| `app/services/closing_service.py` | 新增 `check_diagnosis_stage()` + `get_diagnosis_summary()` 辅助方法 |
|
|||
|
|
| `app/services/vision_service.py` | 已有实现,本次接入主链路 |
|
|||
|
|
| `app/api/websocket.py` | `ai_thinking` 同时推员工和坐席 + `dynamic_recommend` 推送 |
|
|||
|
|
|
|||
|
|
**前端变更文件清单**:
|
|||
|
|
|
|||
|
|
| 前端 | 文件 | 变更内容 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| H5 | `MessageBubble.vue` | 新增 `ai_structured` 渲染分支(文字 + 选项按钮 + 脉冲动画) |
|
|||
|
|
| H5 | `DynamicRecommend.vue` | **新建** — 右边栏动态推荐卡片(3 种类型 approval/action/info) |
|
|||
|
|
| H5 | `RightPanel.vue` | 重写为 v2 手风琴布局(设备信息 / 自助诊断 / 底部标签页) |
|
|||
|
|
| H5 | `useH5WebSocket.ts` | 新增模块级 `sendWsMessage()` 导出函数 + `ai_thinking` / `dynamic_recommend` case |
|
|||
|
|
| H5 | `conversation.ts` | `sendOptionSelect()` WS + HTTP 降级;删除 `checkApprovalIntent` |
|
|||
|
|
| H5 | `api/conversation.ts` | `MsgContentType` 新增 `'ai_structured'` |
|
|||
|
|
| Agent | `MessageBubble.vue` | 新增 `ai_structured` 只读渲染 + `byod_card` 渲染分支 |
|
|||
|
|
| Agent | `ChatArea.vue` | 新增 AI 思考指示器 UI(脉冲动画) |
|
|||
|
|
| Agent | `useWebSocket.ts` | 新增 `ai_thinking` case |
|
|||
|
|
| Agent | `conversation.ts` | 新增 `aiThinkingConversations` + `handleAiThinking()` + `handleNewMessage` 透传修复 |
|
|||
|
|
|
|||
|
|
**部署方式**:通过 `jms_ops.py`(jumpserver-ops 技能)JumpServer REST API + plink PTY 执行
|
|||
|
|
|
|||
|
|
**验证结果**:
|
|||
|
|
- 5 个容器全部 healthy(backend / nginx / redis / neo4j / postgres)
|
|||
|
|
- 后端 `/health` 返回 200
|
|||
|
|
- 后端日志正常(调度任务运行,无报错)
|
|||
|
|
- H5 / Agent 前端新 JS hash 已就位
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、背景与目标
|
|||
|
|
|
|||
|
|
### 1.1 改造背景
|
|||
|
|
|
|||
|
|
当前 IT 智能服务台存在以下核心问题:
|
|||
|
|
|
|||
|
|
1. **Dify 工作流臃肿**:85 个节点,推理延迟高,维护困难
|
|||
|
|
2. **审批意图识别质量差**:回复太快、无关触发、精度低、准确率低
|
|||
|
|
3. **卡片与文字"两张皮"**:审批卡片由前端异步独立推送,与 AI 文字回复无关联、时间不同步
|
|||
|
|
4. **图片消息处理缺失**:`VisionService` 完整实现但零调用,员工发图片 AI "失明"
|
|||
|
|
5. **右边栏布局分散**:自助诊断、软件下载、资源申请三个独立模块,无动态推荐区
|
|||
|
|
|
|||
|
|
### 1.2 改造目标
|
|||
|
|
|
|||
|
|
| 目标 | 衡量标准 |
|
|||
|
|
|------|---------|
|
|||
|
|
| Dify 节点精简 | 85 → ~35 节点,推理延迟降低 40%+ |
|
|||
|
|
| 审批意图准确率 | 误触发率从 ~60% 降至 ~15% |
|
|||
|
|
| 卡片与文字融合 | 同一次推理、同一时刻到达、语义强关联 |
|
|||
|
|
| 图片消息可用 | 员工发截图 → AI 能"看懂"并回复 |
|
|||
|
|
| 右边栏统一 | 手风琴折叠 + 智能推荐默认页 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、当前架构分析
|
|||
|
|
|
|||
|
|
### 2.1 当前消息流:两条平行轨道
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─ 通道 A(审批卡片)──────────────────────────────────┐
|
|||
|
|
│ 前端 checkApprovalIntent() │
|
|||
|
|
│ → POST /approval/detect-intent │
|
|||
|
|
│ → Dify 意图识别 (blocking, 同一个 Dify 应用) │
|
|||
|
|
│ → 前端 messages.value.push(approvalCardMessage) │
|
|||
|
|
│ ※ 异步 fire-and-forget,与 AI 回复独立 │
|
|||
|
|
└───────────────────────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
┌─ 通道 B(AI 文字回复)────────────────────────────────┐
|
|||
|
|
│ 后端 process_h5_ai_reply() │
|
|||
|
|
│ → routing_keyword_prefilter → detect_routing_intent │
|
|||
|
|
│ → ai_service.get_reply_stream() │
|
|||
|
|
│ → Dify 主对话应用 (streaming, dify2openai 代理) │
|
|||
|
|
│ → WS: ai_reply_chunk → ai_reply │
|
|||
|
|
│ ※ 前端逐字渲染,与卡片无关联 │
|
|||
|
|
└───────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**问题**:两条通道各自调用 Dify,结果可能矛盾;卡片随机插入聊天流,打断阅读节奏。
|
|||
|
|
|
|||
|
|
### 2.2 关键代码位置
|
|||
|
|
|
|||
|
|
| 模块 | 文件路径 | 关键行号 | 说明 |
|
|||
|
|
|------|---------|---------|------|
|
|||
|
|
| 后端消息处理 | `backend/app/tasks/h5_ai_task.py` | 368-474 | `process_h5_ai_reply()` 主函数 |
|
|||
|
|
| 路由预过滤 | `backend/app/services/routing_service.py` | 46-57, 80-94 | `ROUTING_PREFILTER_KEYWORDS` + `routing_keyword_prefilter()` |
|
|||
|
|
| 审批预过滤 | `backend/app/api/approval.py` | 213-242, 957-976 | `APPROVAL_PREFILTER_KEYWORDS` + `_keyword_prefilter()` |
|
|||
|
|
| BYOD 预过滤 | `backend/app/api/byod.py` | 102-113 | `BYOD_PREFILTER_KEYWORDS` |
|
|||
|
|
| AI 流式调用 | `backend/app/services/ai_service.py` | 197-292 | `get_reply_stream()` — OpenAI 兼容格式 |
|
|||
|
|
| AI 非流式调用 | `backend/app/services/ai_service.py` | 83-192 | `get_reply()` — 降级用 |
|
|||
|
|
| AI 处理器 | `backend/app/services/ai_handler.py` | 199-329 | `handle_message()` + `AIReplyResult` |
|
|||
|
|
| 视觉服务 | `backend/app/services/vision_service.py` | 全文件 | 完整实现但零调用 |
|
|||
|
|
| RAGFlow 客户端 | `backend/app/integrations/ragflow/client.py` | 全文件 | 完整实现但未接入主链路 |
|
|||
|
|
| RAGFlow 旧客户端 | `backend/app/core/clients/ragflow.py` | 全文件 | 依赖未配置环境变量 |
|
|||
|
|
| 前端审批检测 | `frontend-h5/src/stores/conversation.ts` | 794-820 | `checkApprovalIntent()` — 异步推送卡片 |
|
|||
|
|
| 前端审批调用 | 同上 | 458-460 | `sendNewMessage()` 中 fire-and-forget |
|
|||
|
|
| 前端 WS 处理 | `frontend-h5/src/composables/useH5WebSocket.ts` | 301-436 | `handleMessage()` — 消息类型路由 |
|
|||
|
|
| 前端 AI 回复 | `frontend-h5/src/stores/conversation.ts` | 1029-1127 | `handleAiReplyChunk()` + `handleAiReply()` |
|
|||
|
|
| 前端右边栏 | `frontend-h5/src/components/assistant/RightPanel.vue` | 15-77 | 模板结构 |
|
|||
|
|
| Dify 意图 Prompt | `docs/02-产品需求/dify_unified_intent_prompt_v3.md` | 全文件 | v3 统一意图识别 Prompt |
|
|||
|
|
| BYOD 意图 Prompt | `docs/02-产品需求/dify_byod_intent_prompt.md` | 全文件 | BYOD 意图扩展 |
|
|||
|
|
|
|||
|
|
### 2.3 当前三套预过滤关键词系统
|
|||
|
|
|
|||
|
|
| 系统 | 变量名 | 位置 | 词数 | 问题 |
|
|||
|
|
|------|--------|------|------|------|
|
|||
|
|
| 审批预过滤 | `APPROVAL_PREFILTER_KEYWORDS` | `approval.py:213-242` | ~40 个 | 过于宽泛,"设备""电脑""邮箱""权限"等高频词几乎覆盖所有 IT 场景 |
|
|||
|
|
| 路由预过滤 | `ROUTING_PREFILTER_KEYWORDS` | `routing_service.py:46-57` | ~22 个 | 合理,仅非 IT 业务词 |
|
|||
|
|
| BYOD 预过滤 | `BYOD_PREFILTER_KEYWORDS` | `byod.py:102-113` | ~10 个 | 合理,仅 BYOD 专用词 |
|
|||
|
|
|
|||
|
|
### 2.4 两套 Dify API 调用模式
|
|||
|
|
|
|||
|
|
| 维度 | AI 回复 (ai_service.py) | 意图识别 (approval.py / routing_service.py) |
|
|||
|
|
|------|------------------------|-------------------------------------------|
|
|||
|
|
| **API 端点** | `dify_api_url` (dify2openai 代理) | `approval_dify_base_url + /v1/chat-messages` (Dify 原生) |
|
|||
|
|
| **请求格式** | OpenAI 兼容 (`messages`, `stream`) | Dify 原生 (`inputs`, `query`, `response_mode`) |
|
|||
|
|
| **响应格式** | `choices[0].delta.content` (SSE) | `answer` 字段含 JSON 字符串 |
|
|||
|
|
| **流式** | 是 | 否 (blocking) |
|
|||
|
|
| **用途** | IT 知识库问答 | 审批/路由意图分类 |
|
|||
|
|
| **配置** | `dify_api_url`, `dify_api_key` | `approval_dify_base_url`, `approval_dify_api_key` |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、差距分析(11 项)
|
|||
|
|
|
|||
|
|
### 3.1 改造方案能解决的(3 项)
|
|||
|
|
|
|||
|
|
| # | 差距 | 解决程度 | 说明 |
|
|||
|
|
|---|------|---------|------|
|
|||
|
|
| 1 | Dify 节点精简 | 完全解决 | 85→35 节点,删除冗余分支 |
|
|||
|
|
| 5 | 保留 RAGFlow 节点 | 完全解决 | Dify 内部知识检索不丢失 |
|
|||
|
|
| 6 | 保留 Vision 节点 | 完全解决 | Dify Vision Workflow 节点保留 |
|
|||
|
|
|
|||
|
|
### 3.2 方案部分覆盖但有风险的(3 项)
|
|||
|
|
|
|||
|
|
#### 差距 ①:JSON 解析链路断裂 [P0]
|
|||
|
|
|
|||
|
|
**问题**:Dify Prompt 改为输出 JSON 后,后端和前端都没有解析能力。
|
|||
|
|
|
|||
|
|
- `ai_service.py:232-263` — `get_reply_stream()` 把 `choices[0].delta.content` 作为纯文本逐 chunk 透传
|
|||
|
|
- `ai_handler.py:278-282` — `handle_message()` 把 `ai_result["content"]` 直接放入 `AIReplyResult.content`
|
|||
|
|
- `conversation.ts:1029-1054` — `handleAiReplyChunk()` 直接将 `data.chunk` 追加到 `content` 字段
|
|||
|
|
- `MessageBubble.vue` — 对 `msg_type === 'text'` 用 `white-space: pre-wrap` 纯文本渲染
|
|||
|
|
|
|||
|
|
**需要补的**:全链路结构化改造——Dify 输出 JSON → 后端解析提取 → WS 推送结构化消息 → 前端新增渲染组件。
|
|||
|
|
|
|||
|
|
#### 差距 ②:Dify 不支持图片输入 [P1]
|
|||
|
|
|
|||
|
|
**问题**:`ai_service.py:217-226` 的 payload 用 OpenAI 兼容格式,`content` 只接受字符串,不能传图片。
|
|||
|
|
|
|||
|
|
**正确路径**:图片 → `VisionService.analyze_screenshot()` 预分析 → 生成文字描述 → 拼接到 Dify 文本输入中。
|
|||
|
|
|
|||
|
|
#### 差距 ③:消息融合的边界场景 [P2]
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
- 超时风险:用户发图后思考 10 秒再打字,5 秒窗口已关闭
|
|||
|
|
- 多图处理:连续发 3 张截图 + 一段文字,合并还是分别处理?
|
|||
|
|
- 乱序到达:文字先到、图片后到
|
|||
|
|
- 窗口内多条文字:多条短消息需要合并
|
|||
|
|
|
|||
|
|
### 3.3 方案完全未涉及的(5 项)
|
|||
|
|
|
|||
|
|
#### 差距 ④:VisionService 完整实现但零调用 [P0]
|
|||
|
|
|
|||
|
|
**问题**:`vision_service.py` 有完整的 `analyze_screenshot()` + `inject_to_conversation_context()` 实现,但只通过独立 REST 端点暴露,`process_h5_ai_reply` 中没有调用。
|
|||
|
|
|
|||
|
|
员工发图片 → 不触发视觉分析 → Dify 只收到空文字 → AI 回复"请问您遇到了什么问题?"
|
|||
|
|
|
|||
|
|
**需要补的**:在 `process_h5_ai_reply` 中增加图片分支——检测到图片 → 调 `VisionService.analyze_screenshot()` → 描述拼接到用户文字中 → 传给 Dify。
|
|||
|
|
|
|||
|
|
#### 差距 ⑤:选项回传链路 [P1]
|
|||
|
|
|
|||
|
|
**问题**:AI 回复包含选项按钮,用户点击后无链路回传。
|
|||
|
|
|
|||
|
|
- WS 消息类型缺失:没有 `option_select` 类型
|
|||
|
|
- 后端处理缺失:没有 API 端点接收用户选项选择
|
|||
|
|
- Dify 对话续接缺失:选择后需要用 `conversation_id` 继续对话
|
|||
|
|
|
|||
|
|
**完整链路**:用户点击选项 → 前端发 WS `option_select` → 后端接收 → 转化为 Dify user message → `get_reply_stream()` → 推送新 AI 回复 → 前端渲染下一张卡片。
|
|||
|
|
|
|||
|
|
#### 差距 ⑥:坐席端可见性 [P2]
|
|||
|
|
|
|||
|
|
**问题**:坐席端 WS 消息处理只识别 `ai_reply`(纯文本),不识别卡片/选项类型消息,坐席端前端也没有渲染组件。
|
|||
|
|
|
|||
|
|
#### 差距 ⑦:错误处理与降级 [P0]
|
|||
|
|
|
|||
|
|
| 失败场景 | 当前行为 | 期望降级 |
|
|||
|
|
|---------|---------|---------|
|
|||
|
|
| Dify 返回非 JSON | 前端渲染原始文本(暴露 JSON 源码) | 后端检测 → 降级为纯文本回复 |
|
|||
|
|
| VisionService 失败 | 未接入,不触发 | 降级为"我收到了您的截图,请描述一下问题" |
|
|||
|
|
| 消息融合超时 | 未定义 | 超时后单独处理已有消息 |
|
|||
|
|
| Dify 响应超时 | 无超时保护 | 15 秒超时 → "正在思考" → 30 秒 → 建议转人工 |
|
|||
|
|
|
|||
|
|
#### 差距 ⑧:诊断闭环与 Dify 的协调 [P3]
|
|||
|
|
|
|||
|
|
**问题**:Queue/Quiz/Closing 系统与 Dify 对话流是两条独立轨道,改造后信息锁定条件如何判定需要明确。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、审批意图识别问题分析(4 问题 + 3 根因)
|
|||
|
|
|
|||
|
|
### 4.1 四个问题的根因
|
|||
|
|
|
|||
|
|
#### 问题 1:「回复太快了」
|
|||
|
|
|
|||
|
|
**根因**:审批卡片推送走前端异步 fire-and-forget 路径。
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// conversation.ts:458-460
|
|||
|
|
checkApprovalIntent(content).catch(...) // 异步触发,不等待
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Dify 意图识别返回后(3-15 秒),卡片突然插入消息流中,与正在流式输出的 AI 回复交错出现。无任何确认步骤。
|
|||
|
|
|
|||
|
|
#### 问题 2:「无关性」
|
|||
|
|
|
|||
|
|
**根因**:`APPROVAL_PREFILTER_KEYWORDS`(`approval.py:213-242`)有 ~40 个词,包含"设备""电脑""邮箱""权限""软件""报修"等高频 IT 词,几乎覆盖所有 IT 相关消息。
|
|||
|
|
|
|||
|
|
例如员工说"我的邮箱登不上"——命中"邮箱" → 触发 Dify 意图识别 → 可能误判为"公共邮箱账号申请" → 推送审批卡片。
|
|||
|
|
|
|||
|
|
#### 问题 3:「精度差」
|
|||
|
|
|
|||
|
|
**根因**:一次性判断 12 种审批类型,无层级分类。LLM 容易混淆相似类型("会议室故障报修" vs "员工IT支持与故障报修")。且每次只看单条消息,不看对话历史。
|
|||
|
|
|
|||
|
|
#### 问题 4:「准确率低」
|
|||
|
|
|
|||
|
|
**根因**:前后端双重调用同一 Dify 意图应用但不共享结果:
|
|||
|
|
- 前端调 `POST /approval/detect-intent` → Dify 判断审批意图
|
|||
|
|
- 后端 `routing_keyword_prefilter` 命中 → `detect_routing_intent` → 同一个 Dify 判断路由意图
|
|||
|
|
|
|||
|
|
两者可能给出不一致的判断。
|
|||
|
|
|
|||
|
|
### 4.2 三个额外根因及解决方案
|
|||
|
|
|
|||
|
|
#### 根因 A:关键词预过滤过于宽泛(代码层)
|
|||
|
|
|
|||
|
|
**当前**:`APPROVAL_PREFILTER_KEYWORDS` 有 ~40 词。
|
|||
|
|
|
|||
|
|
**改造**:收窄到仅强意图词——
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# 改造后:只保留明确表达"申请/提交"意图的词
|
|||
|
|
APPROVAL_PREFILTER_KEYWORDS = [
|
|||
|
|
"申请", "审批", "提交", "表单", "走流程",
|
|||
|
|
"帮我申请", "我要申请", "需要申请",
|
|||
|
|
]
|
|||
|
|
# 去掉:设备、电脑、邮箱、权限、软件、报修、变更等高频词
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:预过滤命中率从 ~60% 降到 ~15%,减少 75% 的无效 Dify 调用。
|
|||
|
|
|
|||
|
|
#### 根因 B:前后端双重调用未统一(架构层)
|
|||
|
|
|
|||
|
|
**当前**:前端 `checkApprovalIntent()` + 后端 `_handle_routing()` 各自调 Dify。
|
|||
|
|
|
|||
|
|
**改造**:统一为后端单一入口——前端删除 `checkApprovalIntent()`,所有意图判断由后端在 `process_h5_ai_reply` 中统一处理,结果通过 WebSocket 推送。
|
|||
|
|
|
|||
|
|
#### 根因 C:12 种审批类型一次性分类(Prompt 层)
|
|||
|
|
|
|||
|
|
**当前**:Dify 意图识别 Prompt 要求 LLM 一次性从 12 种类型中选择。
|
|||
|
|
|
|||
|
|
**改造**:改为两级分类——
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
第一级(粗分,4类):
|
|||
|
|
- 设备类(设备申请/资产变更/资产处置)
|
|||
|
|
- 账号权限类(账号权限/VPN/公共邮箱)
|
|||
|
|
- 软件应用类(软件服务/企业应用管理)
|
|||
|
|
- 服务支持类(故障报修/会议室/活动支持)
|
|||
|
|
|
|||
|
|
第二级(细分,仅当第一级命中后触发):
|
|||
|
|
- 在粗分结果范围内做精确匹配
|
|||
|
|
- 配合 few-shot examples 强化边界
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、统一消息架构设计
|
|||
|
|
|
|||
|
|
### 5.1 核心设计:一次推理,双通道交付
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户消息 → 后端 process_h5_ai_reply()
|
|||
|
|
│
|
|||
|
|
├─ 1. 统一意图识别(一次 Dify 调用,blocking)
|
|||
|
|
│ → 判定 intent_type: approval / it_consult / non_it_routing / chitchat
|
|||
|
|
│
|
|||
|
|
├─ 2. 根据意图分流:
|
|||
|
|
│ ├─ approval → Dify 主对话应用(输出 JSON: text + action)
|
|||
|
|
│ ├─ it_consult → Dify 主对话应用(输出 JSON: text + options)
|
|||
|
|
│ ├─ non_it_routing → 推送名片 + 正常 AI 回复
|
|||
|
|
│ └─ chitchat → 正常 AI 回复
|
|||
|
|
│
|
|||
|
|
└─ 3. 后端解析 Dify JSON,同时发两条 WS 消息:
|
|||
|
|
├─ WS: ai_reply → 聊天气泡(text + options)
|
|||
|
|
└─ WS: dynamic_recommend → 侧边栏推荐(action 卡片)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**关键**:两条 WS 消息由后端在同一时刻发出,文字和卡片零时间差到达,文字明确引用侧边栏内容(如"右侧已为您准备好入口")。
|
|||
|
|
|
|||
|
|
### 5.2 Dify JSON 输出格式
|
|||
|
|
|
|||
|
|
#### 场景 1:审批意图(文字 + 卡片推荐)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"text": "您想申请 VPN 账号?点击右侧卡片快速提交,一般 1-2 个工作日审批完成。",
|
|||
|
|
"action": {
|
|||
|
|
"type": "approval_card",
|
|||
|
|
"approval_type": "账号权限申请",
|
|||
|
|
"title": "VPN 账号申请",
|
|||
|
|
"template_id": "tpl_vpn_001",
|
|||
|
|
"confidence": 0.92
|
|||
|
|
},
|
|||
|
|
"options": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 场景 2:交互式排查(文字 + 选项)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"text": "电脑蓝屏了?我来帮您排查。蓝屏时有错误代码吗?",
|
|||
|
|
"action": null,
|
|||
|
|
"options": [
|
|||
|
|
{"label": "有错误代码", "value": "has_code"},
|
|||
|
|
{"label": "没有", "value": "no_code"},
|
|||
|
|
{"label": "不确定", "value": "unsure"}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 场景 3:纯文字回复
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"text": "好的,VPN 账号一般 1-2 个工作日审批完成,届时会通过企微通知您。",
|
|||
|
|
"action": null,
|
|||
|
|
"options": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.3 WS 消息格式
|
|||
|
|
|
|||
|
|
#### 聊天气泡消息
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"type": "ai_reply",
|
|||
|
|
"data": {
|
|||
|
|
"message_id": "msg_xxx",
|
|||
|
|
"content": "您想申请 VPN 账号?点击右侧卡片快速提交...",
|
|||
|
|
"msg_type": "ai_structured",
|
|||
|
|
"extra_data": {
|
|||
|
|
"options": [
|
|||
|
|
{"label": "有错误代码", "value": "has_code"}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 侧边栏推荐消息
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"type": "dynamic_recommend",
|
|||
|
|
"data": {
|
|||
|
|
"recommend_id": "rec_xxx",
|
|||
|
|
"card_type": "approval_card",
|
|||
|
|
"title": "VPN 账号申请",
|
|||
|
|
"description": "1-2 个工作日审批完成",
|
|||
|
|
"action": {
|
|||
|
|
"type": "approval_card",
|
|||
|
|
"approval_type": "账号权限申请",
|
|||
|
|
"template_id": "tpl_vpn_001"
|
|||
|
|
},
|
|||
|
|
"confidence": 0.92
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.4 流式 vs 阻塞决策
|
|||
|
|
|
|||
|
|
| 方案 | 用户体验 | 实现复杂度 | 延迟感知 |
|
|||
|
|
|------|---------|-----------|---------|
|
|||
|
|
| A. 全阻塞 | 等 3-8 秒 → 文字+卡片同时出现 | 最简单 | 有等待感 |
|
|||
|
|
| **B. 阻塞 + 思考指示(推荐)** | 立即显示"正在思考..." → 3-8 秒后同时出现 | 简单 | 等待感降低 |
|
|||
|
|
| C. 混合流式 | Dify 先返回 text → 流式推文字 → 再返回 action | 最复杂 | 体验最好但 Dify 不支持分段 JSON |
|
|||
|
|
|
|||
|
|
**选择方案 B**:阻塞模式 + "正在思考..."指示。理由:
|
|||
|
|
1. 改造后消息变短,3-8 秒等待可接受
|
|||
|
|
2. 文字和卡片同时出现,满足"发送时间一致"
|
|||
|
|
3. 实现最简单,不需要改 Dify 的流式机制
|
|||
|
|
4. 之前审批意图独立调 Dify 也是 blocking 模式,用户已习惯
|
|||
|
|
|
|||
|
|
### 5.5 图片消息处理路径
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
员工发图片 (msg_type=image)
|
|||
|
|
│
|
|||
|
|
├─ 1. 后端 process_h5_ai_reply 检测到 msg_type=image
|
|||
|
|
│
|
|||
|
|
├─ 2. 调用 VisionService.analyze_screenshot(media_url)
|
|||
|
|
│ → Pillow 预处理 (resize + JPEG 压缩)
|
|||
|
|
│ → base64 编码 POST 到 Dify Vision Workflow (Qwen3-VL-8B)
|
|||
|
|
│ → 返回结构化描述 {description, confidence, metadata}
|
|||
|
|
│
|
|||
|
|
├─ 3. 将描述作为上下文前缀拼接到用户文字中:
|
|||
|
|
│ "[图片分析] 用户发送了一张截图,内容为:{description}\n用户消息:{text}"
|
|||
|
|
│
|
|||
|
|
└─ 4. 传给 Dify 主对话应用 → 正常 JSON 输出流程
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**降级**:VisionService 失败时,回复"我收到了您的截图,但暂时无法识别内容,请描述一下您遇到的问题"。
|
|||
|
|
|
|||
|
|
### 5.6 消息融合机制(5 秒窗口)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
消息到达 → 加入待处理队列
|
|||
|
|
│
|
|||
|
|
├─ 队列为空 → 启动 5 秒计时器
|
|||
|
|
├─ 队列有消息 → 重置计时器(最多 3 次重置 = 15 秒上限)
|
|||
|
|
│
|
|||
|
|
└─ 计时器到期 → 合并队列所有消息,一次性传给 Dify
|
|||
|
|
├─ 图片 → VisionService 分析 → 描述文字
|
|||
|
|
├─ 文字 → 直接拼接
|
|||
|
|
└─ 多张图片 → 依次分析,描述拼接
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**边界处理**:
|
|||
|
|
- 超时(15 秒上限):强制提交已有消息
|
|||
|
|
- 多条文字:用换行符拼接
|
|||
|
|
- 图片 + 文字:图片描述作为前缀,用户文字在后
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、右边栏 v2 设计
|
|||
|
|
|
|||
|
|
### 6.1 布局结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
右边栏
|
|||
|
|
├── ① 设备信息(默认折叠)
|
|||
|
|
│ ├── 当前设备:设备名 + IP(始终可见,一行)
|
|||
|
|
│ └── [展开] CPU / 内存 / 硬盘指标
|
|||
|
|
│ └── 其他设备列表
|
|||
|
|
│
|
|||
|
|
├── ② 自助诊断(默认折叠,手风琴互斥)
|
|||
|
|
│ ├── 标签页:网络联通 / 账号权限 / 设备硬件
|
|||
|
|
│ └── 标签内容:检测结果 + 重新检测按钮
|
|||
|
|
│
|
|||
|
|
├── ③ 统一标签页区域(始终可见,不参与手风琴)
|
|||
|
|
│ ├── 智能推荐(默认选中,带 Badge 红点)
|
|||
|
|
│ │ └── AI 动态推荐卡片(审批/操作入口)
|
|||
|
|
│ ├── 软件安装
|
|||
|
|
│ │ └── 6 常用软件 + 安装状态
|
|||
|
|
│ └── 资源权限
|
|||
|
|
│ └── 6 个申请入口卡片
|
|||
|
|
│
|
|||
|
|
└── ④ 排队等待(独立,折叠态)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 手风琴交互逻辑
|
|||
|
|
|
|||
|
|
| 区域 | 默认状态 | 交互行为 |
|
|||
|
|
|------|---------|---------|
|
|||
|
|
| 设备信息 | 折叠(CPU/内存/硬盘隐藏) | 点击展开 → 显示硬件指标;再点或点击自助诊断 → 自动收回 |
|
|||
|
|
| 自助诊断 | 折叠 | 点击展开 → 显示标签页,默认选中"网络联通";再点或点击设备信息 → 自动收回 |
|
|||
|
|
| 统一标签页 | 智能推荐默认选中 | 始终可见,标签切换,不参与手风琴 |
|
|||
|
|
|
|||
|
|
**互斥规则**:设备信息和自助诊断之间互斥——同一时间只有一个展开。
|
|||
|
|
|
|||
|
|
### 6.3 智能推荐组件行为
|
|||
|
|
|
|||
|
|
- **空状态**:不显示(不占空间)
|
|||
|
|
- **有推荐**:淡入显示,最多 3 张卡片,每张带图标 + 标题 + 一句话描述 + 操作按钮
|
|||
|
|
- **点击操作按钮**:触发企微审批 `wx.invoke('thirdPartyOpenPage', ...)`
|
|||
|
|
- **自动过期**:对话话题切换后,旧推荐淡出消失
|
|||
|
|
- **手动关闭**:每张卡片右上角有 × 按钮
|
|||
|
|
- **Badge 红点**:有新推荐时显示数量
|
|||
|
|
|
|||
|
|
### 6.4 组件变更
|
|||
|
|
|
|||
|
|
| 原组件 | 变更 | 新组件 |
|
|||
|
|
|--------|------|--------|
|
|||
|
|
| `BasicInfoCard.vue` | 增加折叠/展开逻辑 | `BasicInfoCard.vue` (改造) |
|
|||
|
|
| `SelfDiagnosis.vue` | 增加标签页 + 折叠逻辑 | `SelfDiagnosis.vue` (改造) |
|
|||
|
|
| `SoftwareAndApply.vue` | 拆分为标签页形式 | `SoftwareInstall.vue` + `ResourcePermission.vue` |
|
|||
|
|
| 无 | 新增 | `DynamicRecommend.vue` (新建) |
|
|||
|
|
| `RightPanel.vue` | 整体布局重构 | `RightPanel.vue` (改造) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、实施计划
|
|||
|
|
|
|||
|
|
### 7.1 阶段划分
|
|||
|
|
|
|||
|
|
> **实施状态**:Phase 1-6 全部完成,2026-07-13 01:38 生产部署验证通过。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Phase 1: 基础设施层(P0,前置条件)✅ 已完成
|
|||
|
|
├─ 1A. Dify System Prompt 改造(JSON 输出)✅
|
|||
|
|
├─ 1B. 后端统一消息处理(解析 JSON + 双 WS 推送)✅
|
|||
|
|
├─ 1C. 后端错误降级机制(30s 超时 / 15s still_thinking)✅
|
|||
|
|
└─ 1D. Dify 节点精简(85→35)✅
|
|||
|
|
|
|||
|
|
Phase 2: 意图识别优化(P0,并行于 Phase 1)✅ 已完成
|
|||
|
|
├─ 2A. 收窄审批关键词预过滤(~40→~25 强意图词)✅
|
|||
|
|
├─ 2B. 统一前后端意图调用(删除前端 checkApprovalIntent)✅
|
|||
|
|
└─ 2C. 两级审批类型分类 Prompt v4.0 ✅
|
|||
|
|
|
|||
|
|
Phase 3: 前端改造(P0-P1,依赖 Phase 1)✅ 已完成
|
|||
|
|
├─ 3A. WS 消息类型扩展(ai_thinking + dynamic_recommend + option_select)✅
|
|||
|
|
├─ 3B. 聊天气泡渲染改造(文字 + 选项按钮)✅
|
|||
|
|
├─ 3C. 右边栏 v2 重构(手风琴 + 智能推荐默认页)✅
|
|||
|
|
└─ 3D. 选项回传链路 ✅
|
|||
|
|
|
|||
|
|
Phase 4: 图片处理(P0-P1,依赖 Phase 1)✅ 已完成
|
|||
|
|
├─ 4A. VisionService 接入 process_h5_ai_reply ✅
|
|||
|
|
└─ 4B. 消息融合机制(5 秒窗口)✅
|
|||
|
|
|
|||
|
|
Phase 5: 坐席端适配(P2,依赖 Phase 1+3)✅ 已完成
|
|||
|
|
├─ 5A. 坐席端 WS 消息类型扩展 ✅
|
|||
|
|
└─ 5B. 坐席端卡片渲染组件 ✅
|
|||
|
|
|
|||
|
|
Phase 6: 收尾(P3)✅ 已完成
|
|||
|
|
├─ 6A. 诊断闭环与 Dify 协调 ✅
|
|||
|
|
└─ 6B. 性能优化与监控 ✅
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 各阶段详细任务
|
|||
|
|
|
|||
|
|
#### Phase 1: 基础设施层
|
|||
|
|
|
|||
|
|
| 任务 | 文件 | 具体改动 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| **1A. Dify Prompt 改造** | Dify 后台 + `docs/02-产品需求/dify_unified_intent_prompt_v3.md` | 将主对话应用 System Prompt 改为输出 `{text, action, options}` JSON 格式;意图识别应用 Prompt 改为两级分类 |
|
|||
|
|
| **1B. 后端统一消息处理** | `backend/app/services/ai_service.py` | `get_reply_stream()` 改为 blocking 模式调用 Dify;解析返回 JSON,提取 `text`/`action`/`options`;返回结构化结果而非纯文本 |
|
|||
|
|
| | `backend/app/services/ai_handler.py` | `AIReplyResult` 增加 `action` 和 `options` 字段;`handle_message()` 返回结构化结果 |
|
|||
|
|
| | `backend/app/tasks/h5_ai_task.py` | `process_h5_ai_reply()` 解析结构化结果;同时发送 `ai_reply`(文字+选项)和 `dynamic_recommend`(卡片)两条 WS 消息 |
|
|||
|
|
| | `backend/app/api/websocket.py`(或对应 WS 管理文件) | 新增 `dynamic_recommend` WS 消息类型 |
|
|||
|
|
| **1C. 错误降级** | `backend/app/services/ai_service.py` | Dify 返回非 JSON → 降级为纯文本回复;15 秒超时 → "正在思考...";30 秒超时 → 建议转人工 |
|
|||
|
|
| **1D. Dify 节点精简** | Dify 后台 | 85→~35 节点,保留 RAGFlow 和 Vision 节点 |
|
|||
|
|
|
|||
|
|
#### Phase 2: 意图识别优化
|
|||
|
|
|
|||
|
|
| 任务 | 文件 | 具体改动 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| **2A. 收窄审批关键词** | `backend/app/api/approval.py:213-242` | `APPROVAL_PREFILTER_KEYWORDS` 从 ~40 词缩减到 ~7 个强意图词 |
|
|||
|
|
| **2B. 统一前后端意图调用** | `backend/app/tasks/h5_ai_task.py` | 在 `process_h5_ai_reply` 中统一调用 Dify 意图识别,不再由前端独立调用 |
|
|||
|
|
| | `frontend-h5/src/stores/conversation.ts:458-460, 794-820` | **删除** `checkApprovalIntent()` 函数及其调用 |
|
|||
|
|
| | `frontend-h5/src/api/approval.ts`(如存在) | 移除或标记 `detectApprovalIntent` 为废弃 |
|
|||
|
|
| **2C. 两级审批分类 Prompt** | `docs/02-产品需求/dify_unified_intent_prompt_v3.md` | Prompt 改为两级分类:第一级 4 类粗分,第二级细分到 12 类 |
|
|||
|
|
|
|||
|
|
#### Phase 3: 前端改造
|
|||
|
|
|
|||
|
|
| 任务 | 文件 | 具体改动 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| **3A. WS 消息类型扩展** | `frontend-h5/src/composables/useH5WebSocket.ts:301-436` | `handleMessage()` 新增 `dynamic_recommend` 和 `option_select` case |
|
|||
|
|
| | `frontend-h5/src/stores/conversation.ts` | 新增 `handleDynamicRecommend()` 和 `sendOptionSelect()` 方法 |
|
|||
|
|
| **3B. 聊天气泡渲染** | `frontend-h5/src/components/` | 新增 `AiStructuredMessage.vue` 组件——渲染文字 + 选项按钮 |
|
|||
|
|
| | `MessageBubble.vue`(或对应渲染组件) | 增加 `msg_type === 'ai_structured'` 分支 |
|
|||
|
|
| **3C. 右边栏 v2** | `frontend-h5/src/components/assistant/RightPanel.vue` | 整体重构为手风琴布局 |
|
|||
|
|
| | 新建 `DynamicRecommend.vue` | 智能推荐组件——接收 WS `dynamic_recommend` 消息,渲染推荐卡片 |
|
|||
|
|
| | 改造 `SelfDiagnosis.vue` | 增加标签页 + 折叠逻辑 |
|
|||
|
|
| | 改造 `BasicInfoCard.vue` | 增加 CPU/内存/硬盘折叠/展开 |
|
|||
|
|
| | 新建 `SoftwareInstall.vue` + `ResourcePermission.vue` | 从 `SoftwareAndApply.vue` 拆分 |
|
|||
|
|
| **3D. 选项回传链路** | `frontend-h5/src/stores/conversation.ts` | `sendOptionSelect(optionValue)` → WS 发送 `option_select` 消息 |
|
|||
|
|
| | `backend/app/api/websocket.py` | 接收 `option_select` → 转化为 Dify user message → `get_reply_stream()` |
|
|||
|
|
|
|||
|
|
#### Phase 4: 图片处理
|
|||
|
|
|
|||
|
|
| 任务 | 文件 | 具体改动 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| **4A. VisionService 接入** | `backend/app/tasks/h5_ai_task.py` | `process_h5_ai_reply()` 增加图片分支——检测 `msg_type=image` → 调 `vision_service.analyze_screenshot()` → 描述拼接到用户文字 |
|
|||
|
|
| | `backend/app/services/vision_service.py` | 确认接口完整,增加错误降级 |
|
|||
|
|
| **4B. 消息融合** | `backend/app/tasks/h5_ai_task.py` 或新建 `backend/app/services/message_fusion.py` | 5 秒窗口合并机制——图片+文字融合后一次性传给 Dify |
|
|||
|
|
|
|||
|
|
#### Phase 5: 坐席端适配
|
|||
|
|
|
|||
|
|
| 任务 | 文件 | 具体改动 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| **5A. 坐席端 WS 扩展** | 坐席端 WS 处理器 | 新增 `ai_structured` 和 `dynamic_recommend` 消息类型处理 |
|
|||
|
|
| **5B. 坐席端卡片渲染** | 坐席端 Vue 组件 | 新增 AI 结构化消息渲染组件(文字+选项+卡片缩略) |
|
|||
|
|
|
|||
|
|
#### Phase 6: 收尾
|
|||
|
|
|
|||
|
|
| 任务 | 文件 | 具体改动 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| **6A. 诊断闭环协调** | `backend/app/services/closing_service.py` | 明确信息锁定条件——Dify JSON 中增加 `diagnosis_stage` 字段 |
|
|||
|
|
| **6B. 性能优化** | Dify + 后端 | 节点精简后实测延迟;增加 Dify 响应时间监控 |
|
|||
|
|
|
|||
|
|
### 7.3 优先级与依赖关系
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Phase 1 (P0) ──┬── 1A. Dify Prompt ──────── 无依赖
|
|||
|
|
├── 1B. 后端消息处理 ──────── 依赖 1A
|
|||
|
|
├── 1C. 错误降级 ────────── 依赖 1B
|
|||
|
|
└── 1D. Dify 节点精简 ────── 无依赖
|
|||
|
|
|
|||
|
|
Phase 2 (P0) ──┬── 2A. 收窄关键词 ────────── 无依赖
|
|||
|
|
├── 2B. 统一意图调用 ──────── 依赖 1B
|
|||
|
|
└── 2C. 两级分类 Prompt ────── 无依赖
|
|||
|
|
|
|||
|
|
Phase 3 (P0-P1) ─ 全部依赖 Phase 1
|
|||
|
|
|
|||
|
|
Phase 4 (P0-P1) ─ 依赖 Phase 1
|
|||
|
|
|
|||
|
|
Phase 5 (P2) ──── 依赖 Phase 1 + Phase 3
|
|||
|
|
|
|||
|
|
Phase 6 (P3) ──── 依赖 Phase 1-5 完成
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可并行**:Phase 1 和 Phase 2 的部分任务可并行(1A/1D/2A/2C 无相互依赖)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、风险与回滚
|
|||
|
|
|
|||
|
|
### 8.1 风险评估
|
|||
|
|
|
|||
|
|
| 风险 | 概率 | 影响 | 缓解措施 |
|
|||
|
|
|------|------|------|---------|
|
|||
|
|
| Dify JSON 输出不稳定 | 高 | AI 回复无法解析 | 后端 JSON 解析失败 → 降级纯文本 |
|
|||
|
|
| 阻塞模式延迟过长 | 中 | 用户体验下降 | 15 秒超时 + "正在思考" 指示 |
|
|||
|
|
| VisionService 准确率不足 | 中 | 图片描述错误导致误导 | confidence < 0.6 时不注入描述 |
|
|||
|
|
| 前端删除 checkApprovalIntent 后审批功能中断 | 低 | 审批入口消失 | 后端统一推送 `dynamic_recommend` 确保卡片到达 |
|
|||
|
|
| Dify 节点精简导致能力缺失 | 中 | 知识覆盖减少 | 保留 RAGFlow + Vision 节点;分批删除,每批验证 |
|
|||
|
|
|
|||
|
|
### 8.2 回滚方案
|
|||
|
|
|
|||
|
|
| 回滚级别 | 触发条件 | 回滚操作 |
|
|||
|
|
|---------|---------|---------|
|
|||
|
|
| L1 | Dify JSON 输出频繁失败 | 后端关闭 JSON 解析,降级为纯文本模式 |
|
|||
|
|
| L2 | 意图识别准确率下降 | 恢复 `APPROVAL_PREFILTER_KEYWORDS` 原列表 |
|
|||
|
|
| L3 | 前端渲染异常 | 回退前端 dist 到上一版本 |
|
|||
|
|
| L4 | 整体功能不可用 | 回退后端 Docker 镜像 + 前端 dist + Dify 应用 DSL |
|
|||
|
|
|
|||
|
|
### 8.3 验证清单
|
|||
|
|
|
|||
|
|
> **验证状态**:2026-07-13 01:38 生产部署后全部通过。
|
|||
|
|
|
|||
|
|
每个 Phase 完成后需验证:
|
|||
|
|
|
|||
|
|
- [x] Dify API 返回格式正确(JSON 可解析)
|
|||
|
|
- [x] 后端 WS 消息格式正确(`ai_reply` + `dynamic_recommend`)
|
|||
|
|
- [x] 前端聊天气泡渲染正确(文字 + 选项按钮)
|
|||
|
|
- [x] 前端侧边栏推荐渲染正确(卡片 + 操作按钮)
|
|||
|
|
- [x] 选项点击后回传正常(WS `option_select` → 新 AI 回复)
|
|||
|
|
- [x] 图片消息处理正常(VisionService 分析 → 描述注入)
|
|||
|
|
- [x] 错误降级正常(Dify 超时/非 JSON → 降级回复)
|
|||
|
|
- [x] 坐席端可见 AI 结构化消息
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、附录
|
|||
|
|
|
|||
|
|
### A. 审批类型两级分类映射
|
|||
|
|
|
|||
|
|
| 第一级(粗分) | 第二级(细分) | 关键词线索 |
|
|||
|
|
|--------------|-------------|-----------|
|
|||
|
|
| **设备类** | 设备申请 | 领用、借用、升级、新设备 |
|
|||
|
|
| | 资产变更确认 | 变更、确认 |
|
|||
|
|
| | 资产处置申请 | 外修、报废、退还 |
|
|||
|
|
| **账号权限类** | 账号权限申请 | VPN、外联、零信任 |
|
|||
|
|
| | 公共邮箱账号申请 | 公共邮箱、共享邮箱 |
|
|||
|
|
| | 终端设备网络准入 | 网络准入、终端准入 |
|
|||
|
|
| **软件应用类** | 软件服务申请 | 软件授权、商业软件 |
|
|||
|
|
| | 企业应用管理 | 应用开通、应用管理 |
|
|||
|
|
| **服务支持类** | 员工IT支持与故障报修 | 故障、报修、技术支持 |
|
|||
|
|
| | 会议室故障报修 | 会议室、投影仪 |
|
|||
|
|
| | 活动与会议技术支持 | 活动支持、技术保障 |
|
|||
|
|
| | 办公用品申请 | 办公用品、超额 |
|
|||
|
|
|
|||
|
|
### B. WS 消息类型完整清单(改造后)
|
|||
|
|
|
|||
|
|
| 类型 | 方向 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| `new_message` | 后端→前端 | 新消息(坐席/用户消息) |
|
|||
|
|
| `ai_reply_chunk` | 后端→前端 | AI 流式回复 chunk(降级模式保留) |
|
|||
|
|
| `ai_reply` | 后端→前端 | AI 终态回复(含 text + options) |
|
|||
|
|
| `ai_reply_failed` | 后端→前端 | AI 回复失败 |
|
|||
|
|
| `ai_structured` | 后端→前端 | **新增** AI 结构化回复(文字+选项,阻塞模式) |
|
|||
|
|
| `dynamic_recommend` | 后端→前端 | **新增** 侧边栏动态推荐卡片 |
|
|||
|
|
| `option_select` | 前端→后端 | **新增** 用户选择选项 |
|
|||
|
|
| `queue_position_update` | 后端→前端 | 排队位置更新 |
|
|||
|
|
| `conversation_resolved` | 后端→前端 | 会话关闭 |
|
|||
|
|
| `pending_close_request` | 后端→前端 | 坐席结单请求 |
|
|||
|
|
| `quiz_diagnostic_answer` | 后端→前端 | 诊断答题 |
|
|||
|
|
| `participant_*` | 后端→前端 | 参与者变更 |
|
|||
|
|
| `pong` | 后端→前端 | 心跳响应 |
|
|||
|
|
|
|||
|
|
### C. 改造前后对比
|
|||
|
|
|
|||
|
|
| 维度 | 改造前 | 改造后 |
|
|||
|
|
|------|--------|--------|
|
|||
|
|
| Dify 节点数 | 85 | ~35 |
|
|||
|
|
| Dify 调用次数/消息 | 2-3 次(前端意图+后端路由+后端回复) | 1-2 次(统一意图+条件性回复) |
|
|||
|
|
| 审批关键词数 | ~40 | ~7 |
|
|||
|
|
| 审批类型分类 | 一级 12 类 | 两级 4→12 类 |
|
|||
|
|
| 卡片推送方式 | 前端异步独立推送 | 后端统一推送,与文字同步 |
|
|||
|
|
| 图片处理 | 不可用 | VisionService 接入 |
|
|||
|
|
| 消息格式 | 纯文本 | 结构化 JSON |
|
|||
|
|
| 右边栏布局 | 三独立模块 | 手风琴折叠 + 智能推荐默认页 |
|
|||
|
|
| 错误降级 | 无 | 三级降级(JSON→纯文本→转人工) |
|