901 lines
40 KiB
Markdown
901 lines
40 KiB
Markdown
# 重构方案 - 复杂场景技术实现方案
|
||
|
||
> 文档版本:v1.1
|
||
> 日期:2026-07-03
|
||
> **设计理念**:借鉴 TeliChat "让代码负责业务逻辑,让模型负责语言理解"
|
||
|
||
---
|
||
|
||
## 零、设计理念:TeliChat 三重约束
|
||
|
||
> **核心理念**:借鉴 TeliChat 白盒架构,确保复杂对话场景的可靠性
|
||
|
||
### 0.1 三重约束机制
|
||
|
||
| 约束 | 作用 | 实现方式 |
|
||
|------|------|---------|
|
||
| **拓扑结构限制** | 限制对话可以走到哪里 | Neo4j DAG 边定义 |
|
||
| **信息状态约束** | 决定当前已经知道什么 | 信息项组合状态 |
|
||
| **Python 代码约束** | 负责真正的业务判断 | FastAPI 业务逻辑 |
|
||
|
||
### 0.2 信息项修饰机制
|
||
|
||
| 修饰 | 含义 | 在复杂场景中的应用 |
|
||
|------|------|------------------|
|
||
| `固定` | 用户回答后不再重复询问 | 已通过系统获取的信息(操作系统、用户名) |
|
||
| `增量` | 允许用户补充新信息 | 故障描述、错误信息 — **非线性跳转核心** |
|
||
| `明确` | 必须明确回答 | 紧急程度确认 — **信息更正核心** |
|
||
| `隐含` | 可以从上下文推断 | AI 推断的问题类型 |
|
||
| `复述` | 要求用户确认信息正确性 | 重要操作确认 — **信息更正核心** |
|
||
| `必需` | 必须填写才能进入下一节点 | 必填字段 — **任务中断恢复核心** |
|
||
|
||
### 0.3 全局意图类型
|
||
|
||
| 意图 | 用户表达示例 | 处理策略 | 对应场景 |
|
||
|------|-------------|---------|---------|
|
||
| `SKIP` | "这个问题先不管了" | 跳过当前节点,记录未完成 | 非线性跳转 |
|
||
| `INSERT` | "对了,我的打印机也有问题" | 插入新任务到队列 | 多意图并行 |
|
||
| `RESUME` | "还是说回刚才那个网络问题" | 恢复之前话题 | 任务中断恢复 |
|
||
| `SWITCH` | "先帮我看看VPN吧" | 切换到指定话题 | 非线性跳转 |
|
||
| `CORRECT` | "刚才说错了,是win10" | 更新信息项值 | 信息更正 |
|
||
| `SUPPLEMENT` | "再补充一下,是财务部的电脑" | 增量补充信息 | 信息更正 |
|
||
| `PAUSE` | "我先去开会,等会继续" | 保存状态,等待恢复 | 任务中断恢复 |
|
||
| `RESUME_TASK` | "好了,继续吧" | 恢复中断的任务 | 任务中断恢复 |
|
||
| `ESCALATE` | "叫个人工来" | 转接坐席 | 所有场景 |
|
||
|
||
### 0.4 状态驱动流程
|
||
|
||
```python
|
||
def determine_next_node(topology, information_items, user_intent):
|
||
"""
|
||
根据三重因素确定下一个节点
|
||
"""
|
||
|
||
# 1. 拓扑约束:检查意图是否在允许的路径上
|
||
allowed_paths = topology.get_allowed_paths(current_node)
|
||
if user_intent not in allowed_paths:
|
||
return handle_off_path_intent(user_intent)
|
||
|
||
# 2. 信息项检查:是否满足必填信息要求
|
||
required_items = topology.get_required_items(next_node)
|
||
for item in required_items:
|
||
if not information_items[item].is_filled:
|
||
return PromptForItem(item)
|
||
|
||
# 3. 业务逻辑:Python 代码执行判断
|
||
if should_escalate(information_items):
|
||
return TransferToAgent()
|
||
|
||
return ExecuteNode(next_node)
|
||
```
|
||
|
||
---
|
||
|
||
## 一、非线性跳转
|
||
|
||
### 1.1 场景描述
|
||
|
||
用户在对话过程中不按线性路径跳转,而是随时切换话题或返回上一步。
|
||
|
||
**示例**:
|
||
```
|
||
用户:我想开VPN
|
||
AI:请问是个人用途还是团队用途?
|
||
用户:先说说团队 VPN 是什么(跳转到知识了解)
|
||
AI:(介绍团队VPN)
|
||
用户:算了,我还是开个人的吧(返回原话题)
|
||
AI:好的,个人VPN开通需要...
|
||
```
|
||
|
||
### 1.2 技术架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 用户对话 │
|
||
└─────────────────────────────┬───────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Dify LLM 推理层 │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌───────────────┐ │
|
||
│ │ 意图理解 │ │ 上下文追踪 │ │ 路径规划 │ │
|
||
│ │ Intent Parser │ │ Context Track │ │ Path Planner │ │
|
||
│ └─────────────────┘ └─────────────────┘ └───────────────┘ │
|
||
└─────────────────────────────┬───────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Neo4j 知识图谱 │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ IT_SUPPORT_GRAPH │ │
|
||
│ │ │ │
|
||
│ │ [VPN问题] ──[可选]──> [个人VPN] │ │
|
||
│ │ │ │ │
|
||
│ │ [可选] │ │
|
||
│ │ │ │ │
|
||
│ │ └───[可选]──> [团队VPN] ──[子节点]──> [使用场景] │ │
|
||
│ │ │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 1.3 知识图谱设计
|
||
|
||
```cypher
|
||
// 节点设计
|
||
CREATE (vpn:Issue {name: "VPN开通", category: "网络"})
|
||
CREATE (personal:Action {name: "个人VPN开通"})
|
||
CREATE (team:Action {name: "团队VPN开通"})
|
||
CREATE (usage:Info {name: "使用场景说明"})
|
||
|
||
// 关系设计 - 支持非线性跳转
|
||
CREATE (vpn)-[:LEADS_TO {type: "可选", order: 1}]->(personal)
|
||
CREATE (vpn)-[:LEADS_TO {type: "可选", order: 2}]->(team)
|
||
CREATE (team)-[:LINKS_TO {type: "子节点"}]->(usage)
|
||
|
||
// 跳转关系 - 支持任意跳转
|
||
CREATE (personal)-[:CAN_JUMP_TO {type: "跳转"}]->(team)
|
||
CREATE (team)-[:CAN_JUMP_TO {type: "返回"}]->(vpn)
|
||
CREATE (usage)-[:CAN_JUMP_TO {type: "返回"}]->(team)
|
||
```
|
||
|
||
### 1.4 信息项修饰机制(借鉴 TeliChat)
|
||
|
||
**核心设计**:使用信息项的 `增量` 修饰符支持非线性跳转
|
||
|
||
```python
|
||
# 信息项定义
|
||
class InformationItem:
|
||
name: str # 信息项名称,如 "{故障描述}"
|
||
value: Any # 当前值
|
||
modifiers: List[str] # 修饰符: ["增量"]
|
||
|
||
# 状态追踪
|
||
is_filled: bool # 是否已填写
|
||
is_incremental: bool # 是否允许增量(补充)
|
||
|
||
# 非线性跳转示例
|
||
用户:我想开VPN
|
||
AI:请问是个人用途还是团队用途?
|
||
用户:先说说团队 VPN 是什么(用户切换到"了解"意图)
|
||
|
||
# 信息项状态变化
|
||
information_items = {
|
||
"VPN类型": {"value": None, "modifiers": ["增量"], "is_filled": False},
|
||
}
|
||
# 用户切换话题时,信息项"VPN类型"保留(因为是增量修饰)
|
||
# 用户返回时,可以继续之前的流程
|
||
```
|
||
|
||
### 1.5 全局意图识别支持
|
||
|
||
```python
|
||
# 非线性跳转意图识别
|
||
def detect_jump_intent(user_input: str) -> JumpIntent:
|
||
"""检测跳转意图"""
|
||
|
||
# RESUME - 返回之前话题
|
||
if any(kw in user_input for kw in ["还是说回", "继续刚才", "回到"]):
|
||
return JumpIntent.RESUME
|
||
|
||
# SWITCH - 切换到新话题
|
||
if any(kw in user_input for kw in ["先看", "先帮我看看", "算了"]):
|
||
return JumpIntent.SWITCH
|
||
|
||
# SKIP - 跳过当前问题
|
||
if any(kw in user_input for kw in ["先不管", "跳过", "算了"]):
|
||
return JumpIntent.SKIP
|
||
|
||
return JumpIntent.NONE
|
||
```
|
||
|
||
### 1.6 关键设计点
|
||
|
||
| 设计点 | 方案 | 说明 |
|
||
|--------|------|------|
|
||
| 上下文栈 | 使用栈结构维护对话路径 | 支持"返回上一步" |
|
||
| 节点状态 | 每个节点记录 visited/focused 状态 | 区分已访问和当前节点 |
|
||
| 跳转权限 | 边设计 CAN_JUMP_TO 关系 | 控制哪些节点可以互相跳转 |
|
||
| **信息项修饰** | 使用"增量"修饰符 | **借鉴 TeliChat,支持乱序输入** |
|
||
| **全局意图** | 识别 RESUME/SWITCH/SKIP | **借鉴 TeliChat,控制跳转** |
|
||
|
||
---
|
||
|
||
## 二、多意图并行
|
||
|
||
### 2.1 场景描述
|
||
|
||
用户一次输入包含多个意图,系统需要并行处理后再合并结果。
|
||
|
||
**示例**:
|
||
```
|
||
用户:我电脑开不了机,VPN也连不上
|
||
→ 同时处理2个问题:
|
||
1. 电脑开机问题 → 引导检查电源/硬件
|
||
2. VPN连接问题 → 引导检查网络/账号
|
||
→ 合并输出:两个问题的处理指引
|
||
```
|
||
|
||
### 2.2 技术架构
|
||
|
||
```
|
||
用户输入: "我电脑开不了机,VPN也连不上"
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Dify 多意图识别节点 │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ Input: "我电脑开不了机,VPN也连不上" │ │
|
||
│ │ Output: │ │
|
||
│ │ [ │ │
|
||
│ │ {intent: "电脑开机故障", entities: []}, │ │
|
||
│ │ {intent: "VPN连接失败", entities: []} │ │
|
||
│ │ ] │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────┬───────────────────────────────────┘
|
||
│
|
||
┌───────────────────┼───────────────────┐
|
||
▼ ▼ ▼
|
||
┌───────────┐ ┌───────────┐ ┌───────────┐
|
||
│ 意图1分支 │ │ 意图2分支 │ │ 意图N分支 │
|
||
│ 电脑开机 │ │ VPN连接 │ │ ... │
|
||
│ 路径推理 │ │ 路径推理 │ │ │
|
||
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
|
||
│ │ │
|
||
└───────────────────┼───────────────────┘
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 结果合并节点 │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 将多个分支的结果合并为统一回复 │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 2.3 Dify 工作流设计
|
||
|
||
```yaml
|
||
# Dify 工作流配置(简化版)
|
||
workflow:
|
||
nodes:
|
||
- id: multi_intent_parser
|
||
type: LLM
|
||
prompt: |
|
||
用户输入: {{input}}
|
||
识别所有意图,以JSON数组返回:
|
||
[{"intent": "意图1", "entities": [...]}, {"intent": "意图2", "entities": [...]}]
|
||
|
||
- id: parallel_branches
|
||
type: parallel
|
||
branches:
|
||
- target: intent_1_handler
|
||
- target: intent_2_handler
|
||
|
||
- id: result_merger
|
||
type: LLM
|
||
prompt: |
|
||
合并以下处理结果为统一回复:
|
||
{{intent_1_result}}
|
||
{{intent_2_result}}
|
||
```
|
||
|
||
### 2.4 知识图谱辅助
|
||
|
||
```cypher
|
||
// 为多意图场景设计聚合节点
|
||
CREATE (multi:IntentGroup {name: "多问题聚合", type: "parallel"})
|
||
|
||
// 并行意图关系
|
||
CREATE (multi)-[:CONTAINS {parallel: true}]->(vpn_issue)
|
||
CREATE (multi)-[:CONTAINS {parallel: true}]->(hardware_issue)
|
||
|
||
// 并行度标记
|
||
MATCH (n)-[r:LEADS_TO]->(m)
|
||
SET r.is_parallel = false // 默认串行
|
||
```
|
||
|
||
### 2.5 信息项聚合管理(借鉴 TeliChat)
|
||
|
||
**核心设计**:多意图对应多个独立的信息项集合
|
||
|
||
```python
|
||
# 多意图场景的信息项设计
|
||
class MultiIntentSession:
|
||
"""多意图会话管理"""
|
||
|
||
# 每个意图对应独立的信息项集合
|
||
intent_items: Dict[str, List[InformationItem]] = {
|
||
"电脑开机": [
|
||
{"name": "故障现象", "modifiers": ["增量", "必需"]},
|
||
{"name": "错误信息", "modifiers": ["增量"]},
|
||
],
|
||
"VPN连接": [
|
||
{"name": "错误代码", "modifiers": ["明确"]},
|
||
{"name": "网络环境", "modifiers": ["隐含"]},
|
||
]
|
||
}
|
||
|
||
def add_intent(self, intent: str):
|
||
"""添加新意图,创建独立信息项集合"""
|
||
if intent not in self.intent_items:
|
||
self.intent_items[intent] = []
|
||
|
||
def get_all_items(self) -> List[InformationItem]:
|
||
"""获取所有意图的信息项"""
|
||
items = []
|
||
for intent_items in self.intent_items.values():
|
||
items.extend(intent_items)
|
||
return items
|
||
```
|
||
|
||
### 2.6 全局意图 INSERT 支持
|
||
|
||
```python
|
||
# INSERT 意图处理
|
||
def handle_insert_intent(user_input: str, session: MultiIntentSession):
|
||
"""处理插入新意图"""
|
||
|
||
# 检测 INSERT 意图
|
||
insert_keywords = ["对了", "还有", "另外", "顺便"]
|
||
if any(kw in user_input for kw in insert_keywords):
|
||
# 识别新意图
|
||
new_intent = llm_recognize_intent(user_input)
|
||
session.add_intent(new_intent)
|
||
|
||
# 并行处理新旧意图
|
||
return process_parallel_intents(session)
|
||
|
||
return None
|
||
```
|
||
|
||
### 2.7 关键设计点
|
||
|
||
| 设计点 | 方案 | 说明 |
|
||
|--------|------|------|
|
||
| 意图识别 | Dify LLM 并行识别 | 使用 Few-shot 提示词模板 |
|
||
| 分支并行 | Dify Parallel Branch | 同时触发多个处理分支 |
|
||
| 结果合并 | Dify LLM 合并 | 智能合并多分支输出 |
|
||
| 冲突检测 | 边设计 CONFLICTS_WITH | 检测意图间冲突 |
|
||
| **信息项聚合** | 每个意图独立信息项集合 | **借鉴 TeliChat,管理多意图状态** |
|
||
| **INSERT 意图** | 检测"对了/还有"等插入语 | **借鉴 TeliChat 全局意图** |
|
||
|
||
---
|
||
|
||
## 三、信息更正
|
||
|
||
### 3.1 场景描述
|
||
|
||
用户在对话过程中更正之前提供的信息,系统需要理解更正并更新上下文。
|
||
|
||
**示例**:
|
||
```
|
||
用户:帮我重置密码,用户名是 zhangsan
|
||
AI:好的,正在为 zhangsan 重置密码...
|
||
用户:不好意思,用户名是 lisi,不是 zhangsan
|
||
AI:好的,已更正,为 lisi 重置密码
|
||
```
|
||
|
||
### 3.2 技术架构
|
||
|
||
```
|
||
用户输入: "不好意思,用户名是 lisi,不是 zhangsan"
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Dify 意图理解层 │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 识别更正意图: │ │
|
||
│ │ { │ │
|
||
│ │ "type": "correction", │ │
|
||
│ │ "field": "username", │ │
|
||
│ │ "old_value": "zhangsan", │ │
|
||
│ │ "new_value": "lisi" │ │
|
||
│ │ } │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────┬───────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Neo4j 会话状态图谱 │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ Session(id: xxx) │ │
|
||
│ │ │ │ │
|
||
│ │ ├── [:PROVIDED]─> Field(name: "username", value: "zhangsan") │ │
|
||
│ │ │ │ │
|
||
│ │ └── [:CORRECTED]─> (标记旧值为已更正) │ │
|
||
│ │ │ │ │
|
||
│ │ └──> Field(name: "username", value: "lisi") │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.3 知识图谱设计
|
||
|
||
```cypher
|
||
// 会话状态节点
|
||
CREATE (session:Session {
|
||
id: "session_123",
|
||
user_id: "user_001",
|
||
created_at: datetime(),
|
||
current_node: "password_reset"
|
||
})
|
||
|
||
// 用户提供的字段(可更正)
|
||
CREATE (session)-[:PROVIDED]->(field1:Field {
|
||
name: "username",
|
||
value: "zhangsan",
|
||
timestamp: datetime(),
|
||
status: "corrected" // 标记为已更正
|
||
})
|
||
|
||
// 更正后的字段
|
||
CREATE (session)-[:PROVIDED]->(field2:Field {
|
||
name: "username",
|
||
value: "lisi",
|
||
timestamp: datetime(),
|
||
status: "active" // 当前有效值
|
||
})
|
||
|
||
// 更正历史关系
|
||
CREATE (field1)-[:CORRECTED_TO {new_value: "lisi", timestamp: datetime()}]->(field2)
|
||
```
|
||
|
||
### 3.4 Dify 工作流设计
|
||
|
||
```yaml
|
||
# 更正处理节点
|
||
nodes:
|
||
- id: correction_detector
|
||
type: LLM
|
||
prompt: |
|
||
检测用户输入是否为信息更正:
|
||
用户输入: {{input}}
|
||
当前已知信息: {{known_fields}}
|
||
|
||
输出JSON:
|
||
{
|
||
"is_correction": true/false,
|
||
"corrected_field": "字段名",
|
||
"old_value": "旧值",
|
||
"new_value": "新值",
|
||
"confidence": 0.0-1.0
|
||
}
|
||
|
||
- id: field_updater
|
||
type: code
|
||
action: |
|
||
# 更新 Neo4j 中的字段状态
|
||
# 1. 标记旧值为 corrected
|
||
# 2. 创建新值节点
|
||
# 3. 建立更正关系
|
||
```
|
||
|
||
### 3.5 信息项修饰机制(借鉴 TeliChat)
|
||
|
||
**核心设计**:使用"增量"+"复述"双修饰实现智能信息更正
|
||
|
||
```python
|
||
# 信息项修饰与更正策略
|
||
class InformationItem:
|
||
modifiers: List[str] # 修饰符组合
|
||
|
||
def handle_update(self, new_value: str, is_correction: bool = False):
|
||
"""处理信息更新"""
|
||
|
||
if "增量" in self.modifiers and not is_correction:
|
||
# 增量模式:追加新值,不覆盖旧值
|
||
self.value = f"{self.value}; {new_value}"
|
||
elif "复述" in self.modifiers:
|
||
# 复述模式:要求用户确认
|
||
self.pending_confirmation = new_value
|
||
return ConfirmationRequest(new_value)
|
||
else:
|
||
# 默认模式:直接覆盖
|
||
self.value = new_value
|
||
|
||
self.is_filled = True
|
||
self.last_updated = datetime.now()
|
||
return None
|
||
|
||
|
||
# 更正示例
|
||
# 用户:不好意思,用户名是 lisi,不是 zhangsan
|
||
# 系统识别 CORRECT 意图,更新信息项
|
||
information_items["用户名"] = {
|
||
"value": "lisi",
|
||
"modifiers": ["明确"], # 原来是"明确"修饰
|
||
"is_filled": True,
|
||
"update_history": ["zhangsan"] # 保留更正历史
|
||
}
|
||
```
|
||
|
||
### 3.6 全局意图 CORRECT/SUPPLEMENT 支持
|
||
|
||
```python
|
||
# 更正意图识别
|
||
def detect_correction_intent(user_input: str) -> CorrectionInfo:
|
||
"""检测更正意图"""
|
||
|
||
correction_patterns = [
|
||
(r"不是(.+),是(.+)", "swap"), # 不是A,是B
|
||
(r"应该是(.+)", "replace"), # 应该是A
|
||
(r"更正.*?为(.+)", "replace"), # 更正为A
|
||
(r"说错了.*?是(.+)", "replace"), # 说错了是A
|
||
]
|
||
|
||
for pattern, correction_type in correction_patterns:
|
||
match = re.search(pattern, user_input)
|
||
if match:
|
||
return CorrectionInfo(
|
||
type=correction_type,
|
||
old_value=match.group(1) if match.lastindex >= 1 else None,
|
||
new_value=match.group(2) if match.lastindex >= 2 else match.group(1),
|
||
is_correction=True
|
||
)
|
||
|
||
return None
|
||
```
|
||
|
||
### 3.7 关键设计点
|
||
|
||
| 设计点 | 方案 | 说明 |
|
||
|--------|------|------|
|
||
| 更正识别 | Dify LLM | 检测"不是/应该是/更正为"等模式 |
|
||
| 字段版本 | Neo4j 节点版本 | 维护字段历史,支持回溯 |
|
||
| 状态同步 | WS 实时推送 | 更正后立即更新前端状态 |
|
||
| **增量修饰** | 追加而非覆盖 | **借鉴 TeliChat,支持补充** |
|
||
| **复述修饰** | 要求用户确认 | **借鉴 TeliChat,关键信息确认** |
|
||
| **CORRECT 意图** | 识别更正表达 | **借鉴 TeliChat 全局意图** |
|
||
|
||
---
|
||
|
||
## 四、任务中断与恢复
|
||
|
||
### 4.1 场景描述
|
||
|
||
用户在任务进行过程中中断(离开/超时),后续可以恢复继续。
|
||
|
||
**示例**:
|
||
```
|
||
用户:我要开VPN
|
||
AI:请问是个人还是团队用途?
|
||
用户:(离开/超时/未回复)
|
||
|
||
--- 2小时后 ---
|
||
用户:继续刚才的VPN申请
|
||
AI:好的,您刚才选择的是VPN开通,请问是个人还是团队用途?
|
||
(恢复上下文,继续流程)
|
||
```
|
||
|
||
### 4.2 技术架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 任务状态机设计 │
|
||
│ │
|
||
│ ┌─────────┐ 用户输入 ┌─────────┐ 选择个人 ┌─────┐ │
|
||
│ │ START │ ───────────> │ ASK_TYPE│ ──────────> │INPUT│ │
|
||
│ └─────────┘ └─────────┘ └──┬──┘ │
|
||
│ ^ │ │ │
|
||
│ │ │ 恢复 │ │
|
||
│ │ ▼ ▼ │
|
||
│ │ ┌─────────┐ ┌────────┐ │
|
||
│ └─────────────── │ PAUSED │ <──────────── │ RESUME │ │
|
||
│ 恢复 └─────────┘ 用户恢复 └────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.3 知识图谱设计
|
||
|
||
```cypher
|
||
// 任务节点
|
||
CREATE (task:Task {
|
||
id: "task_vpn_001",
|
||
type: "VPN开通",
|
||
status: "paused", // paused / active / completed / cancelled
|
||
created_at: datetime(),
|
||
updated_at: datetime(),
|
||
current_node: "ASK_TYPE",
|
||
user_id: "user_001"
|
||
})
|
||
|
||
// 任务路径历史
|
||
CREATE (task)-[:HAS_HISTORY]->(step1:TaskStep {
|
||
node: "START",
|
||
status: "completed",
|
||
timestamp: datetime()
|
||
})
|
||
CREATE (task)-[:HAS_HISTORY]->(step2:TaskStep {
|
||
node: "ASK_TYPE",
|
||
status: "active",
|
||
timestamp: datetime()
|
||
})
|
||
|
||
// 恢复点
|
||
CREATE (task)-[:CAN_RESUME_FROM {node: "ASK_TYPE"}]->(resume_point:ResumePoint {
|
||
prompt: "请问是个人还是团队用途?",
|
||
options: ["个人", "团队"],
|
||
timestamp: datetime()
|
||
})
|
||
```
|
||
|
||
### 4.4 状态管理
|
||
|
||
```python
|
||
# 任务状态机
|
||
class TaskState:
|
||
STATES = {
|
||
"created": ["active", "cancelled"],
|
||
"active": ["paused", "completed", "cancelled"],
|
||
"paused": ["active", "cancelled", "expired"],
|
||
"completed": [],
|
||
"cancelled": [],
|
||
"expired": ["active"]
|
||
}
|
||
|
||
def pause(self):
|
||
"""任务中断"""
|
||
self.status = "paused"
|
||
self.paused_at = datetime.now()
|
||
self._save_to_neo4j()
|
||
|
||
def resume(self):
|
||
"""任务恢复"""
|
||
if self.status != "paused":
|
||
raise InvalidStateError("只有暂停的任务可以恢复")
|
||
self.status = "active"
|
||
self.resumed_at = datetime.now()
|
||
self._save_to_neo4j()
|
||
```
|
||
|
||
### 4.5 恢复触发
|
||
|
||
| 触发方式 | 说明 |
|
||
|----------|------|
|
||
| 关键字恢复 | 用户输入"继续/恢复/接着刚才" |
|
||
| 菜单恢复 | 提供"我的任务"入口 |
|
||
| 超时恢复 | 定时任务检测暂停任务,恢复后通知用户 |
|
||
| 坐席恢复 | 坐席手动恢复用户任务 |
|
||
|
||
```cypher
|
||
// 恢复点查询
|
||
MATCH (task:Task {user_id: $user_id, status: "paused"})
|
||
MATCH (task)-[:CAN_RESUME_FROM]->(rp)
|
||
RETURN task, rp.prompt as resume_prompt
|
||
ORDER BY rp.timestamp DESC
|
||
LIMIT 1
|
||
```
|
||
|
||
### 4.6 信息项与任务状态(借鉴 TeliChat)
|
||
|
||
**核心设计**:任务状态 = 信息项组合,使用结构化状态空间
|
||
|
||
```python
|
||
# 任务状态 - 结构化信息项组合
|
||
class TaskState:
|
||
"""借鉴 TeliChat 的结构化状态空间"""
|
||
|
||
# 任务元信息
|
||
task_id: str
|
||
status: str # created/active/paused/completed/cancelled/expired
|
||
|
||
# 信息项组合 - 决定任务能否继续
|
||
information_items: Dict[str, InformationItem] = {}
|
||
|
||
# 当前节点
|
||
current_node: str
|
||
visited_nodes: List[str] = []
|
||
|
||
def can_proceed_to(self, next_node: str) -> bool:
|
||
"""检查是否可以进入下一节点"""
|
||
|
||
# 检查必需信息项是否已填写
|
||
required_items = get_required_items(next_node)
|
||
for item_name in required_items:
|
||
if item_name not in self.information_items:
|
||
return False
|
||
if not self.information_items[item_name].is_filled:
|
||
return False
|
||
|
||
return True
|
||
|
||
def get_pending_items(self) -> List[str]:
|
||
"""获取未完成的必需信息项"""
|
||
pending = []
|
||
# 检查所有节点的必需信息项
|
||
all_required = get_all_required_items(self.current_node)
|
||
for item_name in all_required:
|
||
if item_name not in self.information_items:
|
||
pending.append(item_name)
|
||
elif not self.information_items[item_name].is_filled:
|
||
pending.append(item_name)
|
||
return pending
|
||
```
|
||
|
||
### 4.7 全局意图 PAUSE/RESUME 支持
|
||
|
||
```python
|
||
# 任务中断与恢复意图
|
||
class TaskIntent(Enum):
|
||
PAUSE = "暂停" # 用户主动暂停
|
||
RESUME_TASK = "继续" # 用户恢复任务
|
||
EXPIRED = "过期" # 任务超时过期
|
||
|
||
def handle_task_intent(user_input: str, task_state: TaskState) -> Action:
|
||
"""处理任务控制意图"""
|
||
|
||
# PAUSE - 用户离开
|
||
pause_keywords = ["先去开会", "等会继续", "先处理别的"]
|
||
if any(kw in user_input for kw in pause_keywords):
|
||
task_state.status = "paused"
|
||
task_state.paused_at = datetime.now()
|
||
save_to_redis(task_state) # 持久化
|
||
return Action(message="好的,您先忙,需要时 say一声继续")
|
||
|
||
# RESUME_TASK - 用户返回
|
||
resume_keywords = ["继续", "好了", "继续刚才", "接着来"]
|
||
if any(kw in user_input for kw in resume_keywords):
|
||
task_state = load_from_redis(task_state.task_id)
|
||
task_state.status = "active"
|
||
pending = task_state.get_pending_items()
|
||
|
||
if pending:
|
||
return Action(message=f"好的,您刚才说到{pending[0]},请继续")
|
||
else:
|
||
return Action(message="继续刚才的流程...")
|
||
|
||
return None
|
||
```
|
||
|
||
### 4.8 关键设计点
|
||
|
||
| 设计点 | 方案 | 说明 |
|
||
|--------|------|------|
|
||
| 状态持久化 | Neo4j 节点 | 保存任务完整上下文 |
|
||
| 恢复点 | ResumePoint 节点 | 保存每个步骤的恢复信息 |
|
||
| 超时处理 | 定时任务 | 24小时未恢复则标记 expired |
|
||
| 坐席可见 | 状态同步 | 坐席工作台可查看用户任务状态 |
|
||
| **结构化状态** | 信息项组合决定状态 | **借鉴 TeliChat,可靠的状态管理** |
|
||
| **必需修饰** | 缺失必填项则阻塞 | **借鉴 TeliChat,保证任务完整性** |
|
||
| **PAUSE/RESUME 意图** | 任务控制意图 | **借鉴 TeliChat 全局意图** |
|
||
|
||
---
|
||
|
||
## 五、综合架构
|
||
|
||
### 5.1 完整技术栈
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 用户层 (H5端) │
|
||
│ 用户发起对话,接收AI/坐席回复 │
|
||
└─────────────────────────────┬───────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Dify AI 推理层 │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
|
||
│ │ 意图理解 │ │ 多意图并行 │ │ 信息更正检测 │ │
|
||
│ │ Intent │ │ Parallel │ │ Correction Detector │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
|
||
│ │ 结果合并 │ │ 路径规划 │ │ 任务状态机 │ │
|
||
│ │ Merger │ │ Path Plan │ │ Task FSM │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
|
||
└─────────────────────────────┬───────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Neo4j 知识图谱层 │
|
||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||
│ │ │ │
|
||
│ │ [Issue] ──[LEADS_TO]──> [Action] │ │
|
||
│ │ │ │ │
|
||
│ │ [:CAN_JUMP_TO] ←──→ [:CAN_JUMP_TO] │ │
|
||
│ │ │ │ │
|
||
│ │ [Session] ──[PROVIDED]──> [Field] │ │
|
||
│ │ │ │ │
|
||
│ │ [Task] ──[HAS_HISTORY]──> [TaskStep] │ │
|
||
│ │ │ │ │
|
||
│ │ [:CAN_RESUME_FROM] ──> [ResumePoint] │ │
|
||
│ │ │ │
|
||
│ └───────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 TeliChat 风格架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ TeliChat 风格架构 │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 信息项状态管理层 │ │
|
||
│ │ (InformationItem: name/value/modifiers/is_filled) │ │
|
||
│ └─────────────────────────────┬───────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌─────────────────────────────▼───────────────────────────┐ │
|
||
│ │ 全局意图识别层 │ │
|
||
│ │ (SKIP/INSERT/RESUME/SWITCH/CORRECT/SUPPLEMENT/ │ │
|
||
│ │ PAUSE/RESUME_TASK/CANCEL/ESCALATE) │ │
|
||
│ └─────────────────────────────┬───────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌─────────────────────────────▼───────────────────────────┐ │
|
||
│ │ 状态驱动引擎 │ │
|
||
│ │ f(拓扑结构, 信息项组合, 用户意图) = 下一节点 │ │
|
||
│ └─────────────────────────────┬───────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌─────────────────────────────▼───────────────────────────┐ │
|
||
│ │ Dify AI 执行层 │ │
|
||
│ │ (意图理解 + 路径推理 + 结果生成) │ │
|
||
│ └─────────────────────────────┬───────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌─────────────────────────────▼───────────────────────────┐ │
|
||
│ │ Neo4j 图数据库层 │ │
|
||
│ │ (知识图谱 + 会话状态 + 任务状态) │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.3 核心能力矩阵
|
||
|
||
| 场景 | TeliChat 设计 | Dify 能力 | Neo4j 能力 | 综合支持 |
|
||
|------|--------------|-----------|-------------|---------|
|
||
| 非线性跳转 | 增量修饰 + SWITCH/SKIP/RESUME 意图 | 路径规划 | 图谱遍历 + 跳转关系 | ✅ 完全支持 |
|
||
| 多意图并行 | INSERT 意图 + 信息项聚合 | 并行分支 + 结果合并 | 聚合节点 | ✅ 完全支持 |
|
||
| 信息更正 | 增量+复述修饰 + CORRECT/SUPPLEMENT 意图 | 更正检测 | 字段版本管理 | ✅ 完全支持 |
|
||
| 中断恢复 | 必需修饰 + PAUSE/RESUME_TASK 意图 | 状态触发 | 任务状态机 + 恢复点 | ✅ 完全支持 |
|
||
|
||
---
|
||
|
||
## 六、实施建议
|
||
|
||
### 6.1 TeliChat 架构落地计划
|
||
|
||
#### 短期(1-2周)
|
||
|
||
1. **信息项数据模型设计**
|
||
- 设计 InformationItem 数据结构
|
||
- 定义 6 种修饰符的交互策略
|
||
- 开发 CRUD 接口
|
||
|
||
2. **全局意图识别 Agent**
|
||
- 在 Dify 中创建意图识别工作流
|
||
- 支持 10 种全局意图类型
|
||
|
||
#### 中期(1个月)
|
||
|
||
3. **状态驱动引擎**
|
||
- 开发对话状态管理服务
|
||
- 实现"拓扑+信息项+意图"三因素路由
|
||
|
||
4. **Neo4j 融合**
|
||
- 图谱节点携带信息项定义
|
||
- 支持信息项状态查询
|
||
|
||
### 6.2 实施优先级
|
||
|
||
| 优先级 | 场景 | TeliChat 核心 | 工作量 | 建议 |
|
||
|--------|------|--------------|--------|------|
|
||
| P0 | 任务中断恢复 | 必需修饰 + PAUSE/RESUME | 中 | 核心场景,优先实现 |
|
||
| P1 | 信息更正 | 增量+复述 + CORRECT | 小 | 用户体验关键 |
|
||
| P1 | 非线性跳转 | 增量修饰 + SWITCH/SKIP | 大 | 知识图谱扩展 |
|
||
| P2 | 多意图并行 | INSERT + 信息项聚合 | 中 | 高级场景,后续迭代 |
|
||
|
||
### 6.3 技术债务
|
||
|
||
| 项 | 说明 | 规避方案 |
|
||
|----|------|----------|
|
||
| 图谱复杂度 | 跳转关系过多导致图谱复杂 | 设计跳转权限控制 |
|
||
| 状态一致性 | 中断恢复可能产生状态不一致 | 使用事务保证 |
|
||
| 性能 | 多意图并行增加响应时间 | 添加缓存层 |
|
||
| **LLM 幻觉** | **TeliChat 解决的核心问题** | **代码约束 + 拓扑限制** |
|
||
|
||
---
|
||
|
||
*本文档为技术实现方案详细设计 v1.1*
|
||
*新增 TeliChat 风格设计理念*
|