330 lines
13 KiB
Markdown
330 lines
13 KiB
Markdown
|
|
# Dify App 改造与 AI 供给链路修复方案
|
|||
|
|
|
|||
|
|
> **版本**: v1.0
|
|||
|
|
> **日期**: 2026-07-13
|
|||
|
|
> **涵盖任务**: P1-4(App精简)、P1-5(Prompt部署)、P1-6(知识库优化)
|
|||
|
|
> **前置条件**: P0 代码改造已完成(`_call_dify_native()` + `DIFY_NATIVE_*` 环境变量)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、当前阻塞点(P0-3 验证结果)
|
|||
|
|
|
|||
|
|
### 1.1 Dify 应用状态
|
|||
|
|
|
|||
|
|
| 应用 | API Key | 状态 | 说明 |
|
|||
|
|
|------|---------|------|------|
|
|||
|
|
| 智能IT支持-员工咨询 | `app-7jkRkAzvX4QM9v9SM3P8mMEO` | ❌ 400 | "Workflow not published"(工作流未发布) |
|
|||
|
|
| 老线上应用 | `app-UaTWYdBSwN6VktKQlbh5YN5H` | ✅ 200 | 返回纯文本Markdown(非JSON),已标记禁用 |
|
|||
|
|
| 分诊应用 | `app-z3S9AEUUAVPbtR2rioxpiIvp` | ✅ 200 | 返回结构化JSON,正常工作 |
|
|||
|
|
| 自建应用 | `app-J3s8sHarZQ2SCaNF3xCppliL` | ❌ 400 | "Model credentials not initialized" |
|
|||
|
|
|
|||
|
|
### 1.2 根因分析
|
|||
|
|
|
|||
|
|
Dify 应用 `app-7jkRkAzvX4QM9v9SM3P8mMEO` 是一个 **advanced-chat(聊天流)** 类型的应用,包含 85 个节点。该应用的工作流 **尚未发布**,导致 API 调用返回 `"Workflow not published"` 错误。
|
|||
|
|
|
|||
|
|
**影响**:
|
|||
|
|
- 后端 `_call_dify_native()` 调用 Dify 原生 API → 返回 400 → 降级到代理路径
|
|||
|
|
- 代理路径(dify2openai)返回 `[object Object]` → JSON 解析失败 → 降级为纯文本
|
|||
|
|
- **最终结果**:所有 Phase 1-6 前端改造的结构化功能(卡片渲染、选项按钮、诊断阶段)均无法触发
|
|||
|
|
|
|||
|
|
### 1.3 修复路径
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户在 Dify 平台发布工作流
|
|||
|
|
↓
|
|||
|
|
Dify API 返回 200 + JSON answer
|
|||
|
|
↓
|
|||
|
|
后端 _call_dify_native() 解析 JSON
|
|||
|
|
↓
|
|||
|
|
双 WS 推送(ai_reply + dynamic_recommend)
|
|||
|
|
↓
|
|||
|
|
前端渲染结构化消息(文字气泡 + 卡片 + 选项按钮)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、P1-4:Dify App 精简方案(85 → ~35 节点)
|
|||
|
|
|
|||
|
|
### 2.1 精简原则
|
|||
|
|
|
|||
|
|
1. **后端已接管的功能**:审批意图分类、关键词预过滤、BYOD 拦截、图片增强 → Dify 中对应节点可删除
|
|||
|
|
2. **Prompt 已覆盖的功能**:JSON 输出格式、诊断阶段标注、审批卡片推送规则 → Dify 中的格式化/路由节点可删除
|
|||
|
|
3. **保留核心能力**:RAGFlow 知识检索、LLM 推理、多轮对话上下文 → 这三块是 Dify 的核心价值
|
|||
|
|
4. **Vision 节点**:后端 `VisionService` 已独立接入,但 Dify 内的图片理解节点暂保留(双路径冗余)
|
|||
|
|
|
|||
|
|
### 2.2 节点分类与精简计划
|
|||
|
|
|
|||
|
|
#### 可删除节点(50个)
|
|||
|
|
|
|||
|
|
| 类别 | 节点类型 | 数量 | 删除原因 |
|
|||
|
|
|------|---------|------|---------|
|
|||
|
|
| 审批意图路由 | if-else + answer | 12 | 后端 `_check_approval_intent()` 已接管,关键词收窄至~25个 |
|
|||
|
|
| BYOD 拦截 | if-else + code + assigner | 8 | 后端 `h5_ai_task.py` 已实现 BYOD 拦截逻辑 |
|
|||
|
|
| 格式化输出 | code + template-transform | 10 | Prompt v1.1 已要求 LLM 直接输出 JSON,无需后处理 |
|
|||
|
|
| 变量中转 | assigner | 12 | 精简后不再需要多步变量传递 |
|
|||
|
|
| 打招呼/人工判断 | if-else + answer | 4 | 后端 `h5_ai_task.py` 已实现打招呼和人工坐席判断 |
|
|||
|
|
| 保底机制 | code + if-else + assigner | 4 | 后端有 30s 超时降级 + 15s still_thinking 推送 |
|
|||
|
|
|
|||
|
|
#### 保留节点(~35个)
|
|||
|
|
|
|||
|
|
| 类别 | 节点类型 | 数量 | 保留原因 |
|
|||
|
|
|------|---------|------|---------|
|
|||
|
|
| 核心 | start + answer | 3 | 工作流入口和最终输出 |
|
|||
|
|
| 知识检索 | knowledge-retrieval | 3 | RAGFlow 检索(IT知识库 + 审批流程库 + FAQ库) |
|
|||
|
|
| LLM 推理 | llm | 4 | 主对话 LLM + 意图理解 + 上下文总结 + 图片描述 |
|
|||
|
|
| 条件路由 | if-else | 5 | 图片/文本分流 + 知识库命中/未命中分流 + 上下文长度判断 |
|
|||
|
|
| 变量管理 | assigner | 6 | 对话变量(servyou_query, memory_query, memory_ans, mmq) |
|
|||
|
|
| 代码处理 | code | 6 | 查询预处理 + 结果后处理 + 上下文拼接 + 图片URL提取 |
|
|||
|
|
| HTTP 请求 | http-request | 4 | RAGFlow API 调用 + 图片理解 API + 外部知识源 |
|
|||
|
|
| 模板转换 | template-transform | 2 | 上下文模板 + 答案模板 |
|
|||
|
|
| 列表操作 | list-operator | 1 | 历史消息列表处理 |
|
|||
|
|
| 其他 | 1 | 保底 answer 节点 |
|
|||
|
|
|
|||
|
|
### 2.3 精简后的工作流结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[Start]
|
|||
|
|
→ [Code: 预处理用户输入]
|
|||
|
|
→ [IF-ELSE: 图片消息?]
|
|||
|
|
├─ Yes → [HTTP: 调用图片理解API] → [LLM: 图片描述生成]
|
|||
|
|
└─ No → 直接继续
|
|||
|
|
→ [Code: 拼接上下文(memory_query + memory_ans + servyou_query)]
|
|||
|
|
→ [IF-ELSE: 上下文长度 > 阈值?]
|
|||
|
|
├─ Yes → [LLM: 上下文压缩总结]
|
|||
|
|
└─ No → 直接继续
|
|||
|
|
→ [Knowledge-Retrieval: RAGFlow 检索]
|
|||
|
|
→ [IF-ELSE: 检索结果命中?]
|
|||
|
|
├─ Yes → [LLM: 基于知识库回答(JSON格式)] → [Answer]
|
|||
|
|
└─ No → [LLM: 通用回答(JSON格式)] → [Answer]
|
|||
|
|
→ [Code: 更新对话变量]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.4 精简操作步骤
|
|||
|
|
|
|||
|
|
1. **导出当前 DSL**:在 Dify 后台导出 `app-7jkRkAzvX4QM9v9SM3P8mMEO` 的完整 YAML(已导出,见 `scripts/dify_export_clean.yaml`)
|
|||
|
|
2. **在 Dify 后台编辑工作流**:
|
|||
|
|
- 删除审批意图路由相关节点(12个 if-else + answer)
|
|||
|
|
- 删除 BYOD 拦截相关节点(8个)
|
|||
|
|
- 删除格式化输出节点(10个 code + template-transform)
|
|||
|
|
- 删除冗余变量中转节点(12个 assigner)
|
|||
|
|
- 删除打招呼/人工判断节点(4个)
|
|||
|
|
- 删除保底机制节点(4个)
|
|||
|
|
3. **更新 LLM 节点的 System Prompt**:将 `dify_main_chat_prompt_v1.md` 的完整 Prompt 粘贴到主 LLM 节点
|
|||
|
|
4. **重新连接节点**:确保工作流从 Start 到 Answer 的路径完整
|
|||
|
|
5. **测试工作流**:在 Dify 后台的调试面板中测试以下场景:
|
|||
|
|
- "密码忘记了怎么办" → 应返回 JSON with options
|
|||
|
|
- "我要申请VPN" → 应返回 JSON with action
|
|||
|
|
- "你好" → 应返回 JSON 纯文字
|
|||
|
|
6. **发布工作流**:点击「发布」按钮,使工作流生效
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、P1-5:Dify Prompt v1.1 部署内容
|
|||
|
|
|
|||
|
|
### 3.1 Prompt 文件位置
|
|||
|
|
|
|||
|
|
完整 Prompt 已准备好,位于:
|
|||
|
|
```
|
|||
|
|
docs/02-技术文档/实现配置/dify_main_chat_prompt_v1.1.md
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 部署步骤
|
|||
|
|
|
|||
|
|
1. **登录 Dify 平台**:http://yw-dify.dc.servyou-it.com
|
|||
|
|
2. **打开应用**:找到「智能IT支持-员工咨询」(API Key: `app-7jkRkAzvX4QM9v9SM3P8mMEO`)
|
|||
|
|
3. **进入编排页面**:点击「编排」→ 进入工作流编辑器
|
|||
|
|
4. **找到主 LLM 节点**:在精简后的工作流中,主 LLM 节点(用于生成最终回复的节点)
|
|||
|
|
5. **替换 System Prompt**:
|
|||
|
|
- 将 `dify_main_chat_prompt_v1.md` 中「## System Prompt 正文」以下的所有内容复制
|
|||
|
|
- 粘贴到 LLM 节点的「SYSTEM」输入框中
|
|||
|
|
- 确保 USER 输入框设置为 `{{#sys.query#}}`(用户原始输入)
|
|||
|
|
6. **配置模型参数**:
|
|||
|
|
- 模型:`gpt-3.5-turbo`(或可用的 OpenAI 兼容模型)
|
|||
|
|
- Temperature:0.3(低温度保证 JSON 格式稳定)
|
|||
|
|
- Max Tokens:500(JSON 输出不需要太长)
|
|||
|
|
7. **测试验证**:
|
|||
|
|
- 在调试面板输入 "密码忘了" → 验证返回 JSON 包含 `text` + `options` + `diagnosis_stage`
|
|||
|
|
- 在调试面板输入 "我要申请VPN" → 验证返回 JSON 包含 `action`
|
|||
|
|
- 在调试面板输入 "谢谢" → 验证返回 JSON 纯文字
|
|||
|
|
8. **发布**:确认无误后点击「发布」
|
|||
|
|
|
|||
|
|
### 3.3 Prompt 核心要点
|
|||
|
|
|
|||
|
|
Prompt v1.1 的关键设计:
|
|||
|
|
|
|||
|
|
| 要点 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| JSON 强制输出 | 4个字段:`text`、`action`、`options`、`diagnosis_stage` |
|
|||
|
|
| 文字简短 | `text` 字段 ≤50字,口语化 |
|
|||
|
|
| 诊断阶段 | 6种值:initial/gathering_info/diagnosing/recommending/resolved/escalating |
|
|||
|
|
| 审批卡片 | `action.type = "approval_card"`,8种审批类型 |
|
|||
|
|
| 交互选项 | `options` 最多4个,label ≤8字 |
|
|||
|
|
| 无 markdown | 直接输出 JSON 原文,不用代码块包裹 |
|
|||
|
|
|
|||
|
|
### 3.4 后端适配确认
|
|||
|
|
|
|||
|
|
后端 `_call_dify_native()` 和 `_parse_structured_response()` 已完成适配:
|
|||
|
|
- `_call_dify_native()`:直连 Dify `/v1/chat-messages`,blocking 模式,返回 `answer` 字段
|
|||
|
|
- `_parse_structured_response()`:解析 `answer` 字段为 JSON,提取 `text`/`action`/`options`/`diagnosis_stage`
|
|||
|
|
- 失败降级:JSON 解析失败 → 纯文本回复(不中断用户体验)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、P1-6:知识库内容优化计划
|
|||
|
|
|
|||
|
|
### 4.1 当前知识库状态
|
|||
|
|
|
|||
|
|
RAGFlow 生产环境:`http://10.80.0.85:8080/`(API: `:9380`)
|
|||
|
|
|
|||
|
|
Dify 中引用的知识库:
|
|||
|
|
1. **IT知识库**:日常IT问题解答(密码重置、VPN连接、打印机等)
|
|||
|
|
2. **审批流程库**:12种审批类型的操作流程
|
|||
|
|
3. **FAQ库**:高频问题快速回答
|
|||
|
|
|
|||
|
|
### 4.2 优化目标
|
|||
|
|
|
|||
|
|
| 指标 | 当前 | 目标 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 检索准确率 | ~60%(粗估) | ≥85% |
|
|||
|
|
| 知识库文档数 | ~200篇 | ~150篇(精简+补充) |
|
|||
|
|
| 平均检索时间 | ~3s | ≤2s |
|
|||
|
|
| 无效检索率 | ~25% | ≤10% |
|
|||
|
|
|
|||
|
|
### 4.3 优化策略
|
|||
|
|
|
|||
|
|
#### 策略1:知识库结构化重构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
IT知识库/
|
|||
|
|
├── 01-账号密码/ # 密码重置、账号解锁、二次验证
|
|||
|
|
│ ├── 企微密码重置.md
|
|||
|
|
│ ├── 邮箱密码重置.md
|
|||
|
|
│ ├── aTrust密码重置.md
|
|||
|
|
│ └── GitLab密码重置.md
|
|||
|
|
├── 02-网络VPN/ # VPN连接、网络故障、WiFi
|
|||
|
|
│ ├── 零信任aTrust连接.md
|
|||
|
|
│ ├── 传统VPN配置.md
|
|||
|
|
│ └── 网络不通排查.md
|
|||
|
|
├── 03-设备硬件/ # 电脑、显示器、打印机
|
|||
|
|
│ ├── 打印机连接.md
|
|||
|
|
│ ├── 蓝屏排查.md
|
|||
|
|
│ └── 设备报修流程.md
|
|||
|
|
├── 04-软件安装/ # 软件安装、授权、更新
|
|||
|
|
│ ├── 软件安装指南.md
|
|||
|
|
│ └── 软件授权申请.md
|
|||
|
|
├── 05-审批流程/ # 12种审批类型
|
|||
|
|
│ ├── 设备申请流程.md
|
|||
|
|
│ ├── VPN账号申请.md
|
|||
|
|
│ └── ...
|
|||
|
|
└── 06-常见FAQ/ # 高频问题
|
|||
|
|
├── 电脑卡顿.md
|
|||
|
|
└── 邮件配置.md
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 策略2:文档内容标准化
|
|||
|
|
|
|||
|
|
每篇知识库文档统一格式:
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
# [问题标题]
|
|||
|
|
|
|||
|
|
## 问题描述
|
|||
|
|
[1-2句话描述问题场景]
|
|||
|
|
|
|||
|
|
## 解决方案
|
|||
|
|
### 步骤1:[操作名称]
|
|||
|
|
[具体操作步骤]
|
|||
|
|
|
|||
|
|
### 步骤2:[操作名称]
|
|||
|
|
[具体操作步骤]
|
|||
|
|
|
|||
|
|
## 相关链接
|
|||
|
|
- [操作入口URL]
|
|||
|
|
- [相关文档]
|
|||
|
|
|
|||
|
|
## 关键词
|
|||
|
|
密码、重置、企微、登录
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 策略3:RAGFlow 检索优化
|
|||
|
|
|
|||
|
|
1. **Chunk 策略调整**:
|
|||
|
|
- 将大文档拆分为 ≤500 token 的 chunk
|
|||
|
|
- 每个 chunk 包含完整的「问题描述 + 解决方案」
|
|||
|
|
- 避免跨 chunk 的信息断裂
|
|||
|
|
|
|||
|
|
2. **Embedding 模型**:
|
|||
|
|
- 确认使用中文优化的 embedding 模型(如 `bge-large-zh`)
|
|||
|
|
- 如果当前用的是英文模型,切换后检索准确率可提升 15-20%
|
|||
|
|
|
|||
|
|
3. **检索参数调优**:
|
|||
|
|
- Top-K:5→3(减少噪音)
|
|||
|
|
- 相似度阈值:0.5→0.65(提高精度)
|
|||
|
|
- Rerank:启用 rerank 模型(如 `bge-reranker-base`)
|
|||
|
|
|
|||
|
|
#### 策略4:知识库内容补充
|
|||
|
|
|
|||
|
|
基于员工咨询高频场景,需补充以下内容:
|
|||
|
|
|
|||
|
|
| 场景 | 当前状态 | 补充内容 |
|
|||
|
|
|------|---------|---------|
|
|||
|
|
| 企微使用问题 | 缺失 | 企微登录/消息/审批/会议常见问题 |
|
|||
|
|
| 税友安全助手 | 缺失 | 安装/认证失败/网络断开排查 |
|
|||
|
|
| 域控账号 | 部分 | 域控密码同步机制 + 常见故障 |
|
|||
|
|
| 云桌面 | 缺失 | 云桌面连接/卡顿/文件传输 |
|
|||
|
|
| 视频会议 | 部分 | 腾讯会议/企微会议常见问题 |
|
|||
|
|
|
|||
|
|
### 4.4 实施时间线
|
|||
|
|
|
|||
|
|
| 阶段 | 内容 | 预计工作量 |
|
|||
|
|
|------|------|-----------|
|
|||
|
|
| 第1周 | 知识库结构化重构 + 文档标准化 | 2天 |
|
|||
|
|
| 第1周 | RAGFlow 检索参数调优 | 0.5天 |
|
|||
|
|
| 第2周 | 高频场景内容补充(20篇) | 2天 |
|
|||
|
|
| 第2周 | Embedding 模型评估 + 切换 | 1天 |
|
|||
|
|
| 第3周 | 端到端测试 + 效果评估 | 1天 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、完整执行清单
|
|||
|
|
|
|||
|
|
### 5.1 用户需在 Dify 平台操作(阻塞项)
|
|||
|
|
|
|||
|
|
- [ ] **D-1**:登录 http://yw-dify.dc.servyou-it.com
|
|||
|
|
- [ ] **D-2**:打开「智能IT支持-员工咨询」应用(`app-7jkRkAzvX4QM9v9SM3P8mMEO`)
|
|||
|
|
- [ ] **D-3**:精简工作流(按 P1-4 方案,85→~35节点)
|
|||
|
|
- [ ] **D-4**:更新主 LLM 节点的 System Prompt(按 P1-5 部署步骤)
|
|||
|
|
- [ ] **D-5**:在调试面板测试3个场景(密码/VPN/打招呼)
|
|||
|
|
- [ ] **D-6**:点击「发布」按钮
|
|||
|
|
- [ ] **D-7**:发布后通知我验证 API 连通性
|
|||
|
|
|
|||
|
|
### 5.2 我来完成(Dify 发布后)
|
|||
|
|
|
|||
|
|
- [ ] **M-1**:验证 Dify 原生 API 返回 JSON 格式(复用 `test_dify_native.py`)
|
|||
|
|
- [ ] **M-2**:请用户在企微内发消息测试端到端链路
|
|||
|
|
- [ ] **M-3**:检查后端日志确认 `调用 Dify 原生 API` + JSON 解析成功
|
|||
|
|
- [ ] **M-4**:验证前端结构化消息渲染(文字气泡 + 卡片 + 选项按钮)
|
|||
|
|
- [ ] **M-5**:开始知识库优化(P1-6)
|
|||
|
|
|
|||
|
|
### 5.3 临时方案(如需立即可用)
|
|||
|
|
|
|||
|
|
如果用户暂时无法在 Dify 平台操作,可临时切换到旧 Key(需用户授权):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
# 临时切换 .env 中的 DIFY_NATIVE_API_KEY
|
|||
|
|
DIFY_NATIVE_API_KEY=app-UaTWYdBSwN6VktKQlbh5YN5H
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**注意**:旧 Key 返回纯文本(非JSON),后端会降级为纯文字回复。结构化功能(卡片/选项)不可用,但至少 AI 对话能正常工作。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、风险评估
|
|||
|
|
|
|||
|
|
| 风险 | 等级 | 缓解措施 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| Dify 工作流精简后遗漏关键路径 | 中 | 精简前已导出完整 DSL YAML 备份 |
|
|||
|
|
| Prompt v1.1 在 Dify 中 JSON 输出不稳定 | 中 | Temperature=0.3 + 后端有 JSON 解析降级 |
|
|||
|
|
| RAGFlow 检索准确率不达标 | 低 | 可通过调整检索参数 + 补充内容逐步优化 |
|
|||
|
|
| 知识库内容过时 | 中 | 建立月度知识库审查机制 |
|