facc04aa65
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交 (5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。 一、docs 结构整改(整改 #14) 根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入, 随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录 树并存于 docs/,共 791 文件、双分类体系冲突。 修复动作: - b2 同名异主题文件改名迁移保全 9 个 - C 类 39 个孤立文件按主题正确归类 - A/B1 类 222 个重复文件删除(新结构已有内容副本) - 9 个旧独有空目录删除 - 270 处内部引用按 verified 映射改写 - 整改记录 #14 登记于 04-运维文档/部署运维 结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。 残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。 二、compose 双目录对齐(消除踩坑 A) - docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist 改为 src/frontend-*/dist(h5 / agent / admin / terminal) - docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/ - 效果:本地 docker compose up 不再把根目录 stale dist 挂回, 与线上一致,分叉隐患消除(已 docker compose config 校验通过) 防复发铁律: - 重构须提交;仓库修复须 git stash -u 或先 commit - 新结构须 git add 并提交,避免再次 untracked 复活 - H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
12 KiB
12 KiB
技术方案 - REQ-AI-001 复杂场景与统一路由
版本: v1.1 日期: 2026-07-27 REQ编号: REQ-AI-001 关联PRD:
PRD-REQ-AI-001-复杂场景与统一路由-v1.1.md状态: 架构设计 架构师: 高见远(Bob)
目录
一、设计理念
1.1 TeliChat 三重约束机制
借鉴 TeliChat 白盒架构,确保复杂对话场景的可靠性:
| 约束 | 作用 | 实现方式 |
|---|---|---|
| 拓扑结构限制 | 限制对话可以走到哪里 | ScenarioConfig.actions 有序列表 + Python 代码路由 |
| 信息状态约束 | 决定当前已经知道什么 | auto_information_items PostgreSQL 表 |
| Python 代码约束 | 负责真正的业务判断 | FastAPI 业务逻辑 |
1.2 信息项修饰机制
| 修饰 | 含义 | 在复杂场景中的应用 |
|---|---|---|
固定 |
用户回答后不再重复询问 | 已通过系统获取的信息(操作系统、用户名) |
增量 |
允许用户补充新信息 | 故障描述、错误信息 — 非线性跳转核心 |
明确 |
必须明确回答 | 紧急程度确认 — 信息更正核心 |
隐含 |
可以从上下文推断 | AI 推断的问题类型 |
复述 |
要求用户确认信息正确性 | 重要操作确认 — 信息更正核心 |
必需 |
必须填写才能进入下一节点 | 必填字段 — 任务中断恢复核心 |
1.3 全局意图类型
| 意图 | 用户表达示例 | 处理策略 | 对应场景 |
|---|---|---|---|
SKIP |
"这个问题先不管了" | 跳过当前节点,记录未完成 | 非线性跳转 |
INSERT |
"对了,我的打印机也有问题" | 插入新任务到队列 | 多意图并行 |
RESUME |
"还是说回刚才那个网络问题" | 恢复之前话题 | 任务中断恢复 |
SWITCH |
"先帮我看看VPN吧" | 切换到指定话题 | 非线性跳转 |
CORRECT |
"刚才说错了,是win10" | 更新信息项值 | 信息更正 |
SUPPLEMENT |
"再补充一下,是财务部的电脑" | 增量补充信息 | 信息更正 |
PAUSE |
"我先去开会,等会继续" | 保存状态,等待恢复 | 任务中断恢复 |
RESUME_TASK |
"好了,继续吧" | 恢复中断的任务 | 任务中断恢复 |
ESCALATE |
"叫个人工来" | 转接坐席 | 所有场景 |
二、统一路由层
2.1 业务路由推荐
当员工提问涉及非IT问题(如行政、HR、财务等)时,自动推荐对应部门的联系人。
注:打印机、复印机、扫描仪属于IT服务范畴,不在此列。
2.1.1 核心技术挑战与对策
| 挑战 | 对策 |
|---|---|
| 向后兼容:扩展 Dify Prompt 后不能破坏现有审批识别 | 原审批判断规则原文保留不动,仅新增非IT判断段落;原3字段语义和取值不变,新增3字段 |
| 路由检测时机:在消息处理流程中何时调用 Dify | 在 process_h5_ai_reply 后台任务中新增路由检测步骤,位于 BYOD 检测之后,打招呼/呼叫人工检测之前 |
| 误路由防护:IT问题被误识别为非IT | routing_confidence < 0.7 不触发名片推荐,走正常 AI 回复流程 |
2.1.2 多层级路由模型
部门(department) → 业务(business) → 应用(application) → 角色(role) → 职责(responsibility)
↓
联系方式(contact_point)
联系方式可配置在任意层级,匹配时采用「就近原则」:
- 优先查找职责级别
- 其次角色级别
- 再次应用级别
- 以此类推
2.1.3 Dify 统一意图识别
扩展 Dify Prompt 输出格式:
{
"is_approval_request": true/false,
"confidence": 0.0-1.0,
"approval_type": "设备申请",
"intent_type": "approval" / "it_consult" / "non_it_routing" / "chitchat",
"business_category": "行政" / "人力资源" / "财务" / null,
"routing_confidence": 0.0-1.0
}
判断优先级链:
- IT审批意图 → intent_type: "approval"
- IT范围内咨询/报修 → intent_type: "it_consult"
- 非IT业务路由 → intent_type: "non_it_routing"
- 闲聊/无关 → intent_type: "chitchat"
三、复杂场景重构第一阶段
3.1 核心技术挑战
| 挑战 | 说明 | 对策 |
|---|---|---|
| 不引入 Neo4j 实现 TeliChat 三重约束 | 本阶段约束不引入 Neo4j | 三重约束映射:拓扑 → ScenarioConfig.actions 有序列表 + Python 代码路由;信息状态 → auto_information_items PostgreSQL 表 |
| 全局意图识别与现有场景识别的兼容 | 新增 PAUSE/RESUME_TASK/CORRECT/SUPPLEMENT 4 种全局意图 | 在 IntentRouter.detect() 前置一层全局意图检测,命中全局意图时跳过场景识别 |
| 暂停状态持久化与恢复点一致性 | 暂停时需保存完整上下文 | PostgreSQL 持久化会话状态 + Redis 存储恢复点快照(含 TTL 25h 自动过期) |
| 信息项版本管理与更正锁定 | 更正需保留变更历史 | auto_information_items 表记录 version + update_history,is_locked 字段控制更正锁定 |
| 24 小时超时自动关闭 | 暂停超过 24 小时需自动关闭会话 | 后台定时任务扫描 paused 状态会话,超时则标记 closed |
3.2 总体架构
员工 H5 / 坐席工作台
│ HTTP / WebSocket
▼
FastAPI 路由层 (api/automation.py)
新增: /pause /resume /correct /supplement /info-items /paused
│
▼
自动化服务层 (services/automation/)
├── IntentRouter (+全局意图检测)
├── SessionManager (+pause/resume/correct/supplement)
├── InformationItemService (新增)
├── TimeoutCleaner (新增, 24h扫描)
└── ProgressPublisher (+5种新WS事件)
│
┌────┴────┐
▼ ▼ ▼
PostgreSQL Redis Dify
+新表 +恢复点 AI
3.3 数据模型
3.3.1 auto_information_items 表
CREATE TABLE auto_information_items (
id VARCHAR(36) PRIMARY KEY,
session_id VARCHAR(36) NOT NULL,
name VARCHAR(128) NOT NULL,
value TEXT NOT NULL DEFAULT '',
modifiers JSON NOT NULL DEFAULT '[]',
is_filled BOOLEAN NOT NULL DEFAULT FALSE,
is_locked BOOLEAN NOT NULL DEFAULT FALSE,
version INTEGER NOT NULL DEFAULT 1,
update_history JSON NOT NULL DEFAULT '[]',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
3.3.2 auto_sessions 表新增字段
ALTER TABLE auto_sessions ADD COLUMN paused_at TIMESTAMPTZ;
3.4 核心功能
| 功能 | 说明 |
|---|---|
| 暂停/恢复 | 员工可暂停会话并指定时间恢复,坐席可代恢复/关闭 |
| 信息更正 | 支持 CORRECT 意图更新信息项值,保留版本历史 |
| 信息补充 | 支持 SUPPLEMENT 意图增量补充信息 |
| 超时关闭 | 暂停超过24小时自动关闭会话 |
| 坐席感知 | 坐席工作台实时看到暂停/恢复/更正事件 |
四、复杂场景重构第二阶段
4.1 上下文压缩
4.1.1 Tokenizer 选择
| 方案 | 说明 | 优先级 |
|---|---|---|
tiktoken(cl100k_base) |
OpenAI 官方编码器,与 Dify/GPT 系列模型一致 | 首选 |
| 字符估算兜底 | 1 token ≈ 1.5 个中文字符估算 | 兜底 |
4.1.2 压缩引擎设计
class ContextCompressor:
def count_tokens(messages: list) -> int
def should_compress(session_id) -> bool
def compress(session_id, messages, info_items, actions, task_node) -> CompressedContext
def _extract_key_info(info_items, actions, task_node) -> str
def _summarize_history(messages_to_compress) -> str
def _progressive_compress(context, level=1) -> str
4.1.3 渐进式压缩策略
| 级别 | 策略 | 压缩效果 |
|---|---|---|
| Level 1 | LLM 摘要 + 保留最近4轮对话 | token 降低约 60% |
| Level 2 | LLM 摘要 + 保留最近2轮对话 | token 降低约 80% |
| Level 3 | 纯关键信息 + 保留最近1轮对话 | token 降低约 90% |
| 超出 | 截断最旧消息 | 降级保护 |
4.2 多轮纠错
4.2.1 快照机制
每次更正前创建快照,支持撤销最近5次更正:
class SnapshotService:
def create_snapshot(session_id, trigger_item_key, correction_ids) -> InformationSnapshot
def undo_correction(session_id) -> dict # 限制最近5次
def get_snapshot_history(session_id) -> list
def get_version_diff(session_id, v1, v2) -> dict
4.2.2 批量更正
class CorrectionService:
def batch_correct(session_id, corrections: list) -> BatchCorrectResult # 原子性事务
def check_dependencies(session_id, item_key) -> list # 依赖联动警告
4.3 数据模型
-- 上下文压缩记录表
CREATE TABLE auto_context_compressions (
id SERIAL PRIMARY KEY,
session_id VARCHAR(36) NOT NULL,
tokens_before INTEGER NOT NULL,
tokens_after INTEGER NOT NULL,
compression_ratio NUMERIC(5,2) NOT NULL,
compression_level SMALLINT NOT NULL DEFAULT 1,
summary TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 信息项快照表
CREATE TABLE auto_information_snapshots (
id SERIAL PRIMARY KEY,
session_id VARCHAR(36) NOT NULL,
trigger_item_key VARCHAR(64) NOT NULL,
snapshot_data JSON NOT NULL,
correction_ids JSON NOT NULL DEFAULT '[]',
is_undone BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
五、技术架构总结
5.1 核心技术栈
| 层 | 技术栈 |
|---|---|
| 后端 | FastAPI + SQLAlchemy + PostgreSQL + Redis |
| H5前端 | Vue3 + Vant4 + TypeScript |
| 坐席前端 | Vue3 + Element Plus |
| AI意图识别 | Dify 原生 API(扩展现有 Prompt) |
5.2 技术债务规避
| 项 | 规避方案 |
|---|---|
| LLM 幻觉 | 代码约束 + 拓扑限制(TeliChat 核心解决) |
| 图谱复杂度 | 设计跳转权限控制 |
| 状态一致性 | 使用事务保证 |
| 性能 | 添加缓存层 |
六、验收标准
6.1 统一路由层
| 场景 | 验收条件 |
|---|---|
| 非IT路由触发 | 员工发送"名片印刷找谁" → Dify识别为 non_it_routing → 发送名片卡片 |
| 路由置信度阈值 | routing_confidence < 0.7 → 不触发名片推荐,走正常AI流程 |
| 审批识别兼容性 | 审批问题仍正常识别,不受路由Prompt影响 |
6.2 复杂场景第一阶段
| 场景 | 验收条件 |
|---|---|
| 暂停功能 | 员工输入"先去开会" → 会话暂停 → 恢复点保存到Redis |
| 恢复功能 | 员工输入"继续" → 恢复暂停会话 → 从断点继续执行 |
| 信息更正 | 员工说"刚才说错了,是win10" → 信息项更新 → 版本历史记录 |
| 超时关闭 | 暂停超过24小时 → 会话自动标记closed → 员工收到通知 |
6.3 复杂场景第二阶段
| 场景 | 验收条件 |
|---|---|
| 上下文压缩 | 消息token超过6000 → 自动压缩 → token降低60%以上 |
| 批量更正 | 一次提交多个更正 → 原子性事务 → 全部成功或全部回滚 |
| 更正撤销 | 可撤销最近5次更正 → 信息项回滚到历史版本 |
变更记录
| 变更日期 | 变更内容 | 变更类型 | 关联PRD |
|---|---|---|---|
| 2026-07-27 | 新增智能打招呼检测:解决"您好+具体问题"被误判为纯打招呼的问题,新增 _SUBSTANTIVE_KEYWORDS 实质问题关键词列表 |
缺陷修复 | PRD-REQ-AI-001-v1.2 |
附录:源文档归档记录
本技术方案合并自以下文档:
| 源文档 | 合并章节 |
|---|---|
| 复杂场景技术方案-v1.1.md | 一、设计理念 |
| 复杂场景重构第一阶段-v1.0.md | 三、复杂场景重构第一阶段 |
| 复杂场景重构第二阶段-v1.0.md | 四、复杂场景重构第二阶段 |
| 业务路由推荐-v2.1.1.md | 二、统一路由层 |
本文档为 REQ-AI-001 复杂场景与统一路由的完整技术方案