# 技术方案 - AI回复来源标识 > **版本**: v1.0 > **日期**: 2026-07-20 > **状态**: [待评审] > **作者**: 许清楚 > **REQ编号**: REQ-AI-004 > **关联PRD**: `01-产品文档/03-AI服务/PRD-REQ-AI-004-AI回复来源标识-v1.0.md` --- ## 一、方案概述 本技术方案实现 AI 回复来源标识功能,在 AI 回复消息上显示来源图标(图谱/Dify/本地路由等),提升来源透明度和可追溯性。 --- ## 二、数据库设计 ### 2.1 消息表新增字段 ```sql -- 消息表新增字段 ALTER TABLE messages ADD COLUMN reply_source VARCHAR(50) DEFAULT NULL; -- 存储格式:JSON数组,如 '["graph"]' 或 '["routing","assets"]' ``` ### 2.2 字段说明 | 字段 | 类型 | 说明 | |------|------|------| | reply_source | VARCHAR(50) | 来源标识,JSON数组格式 | --- ## 三、后端实现 ### 3.1 来源标识配置 ```python # 来源标识配置 REPLY_SOURCE_MARKERS = { "byod": "🔒", # BYOD拦截 "rule": "⚡️", # 本地快判(打招呼/呼叫人工) "vision": "🖼️", # 图片增强 "graph": "🕸️", # Neo4j图谱 "dify": "🤖", # Dify主推理 "routing": "📋", # 业务路由 "assets": "💻", # 资产推荐 "fallback": "⚠️", # 降级回复 } # 来源优先级 REPLY_SOURCE_PRIORITY = [ "rule", "byod", "vision", "graph", "dify", "routing", "assets", "fallback" ] ``` ### 3.2 来源标识追加函数 ```python from collections import OrderedDict from typing import List def append_source_marker(content: str, sources: List[str]) -> str: """在回复内容末尾追加来源标识""" # 获取对应图标 markers = [REPLY_SOURCE_MARKERS.get(s, "") for s in sources if s in REPLY_SOURCE_MARKERS] # 按优先级排序并去重 seen = set() unique_markers = [] for marker in markers: if marker and marker not in seen: seen.add(marker) unique_markers.append(marker) if unique_markers: return content + " " + "".join(unique_markers) return content ``` ### 3.3 各路由返回格式 ```python # 各路由返回时携带来源标识 def handle_local_rule(...) -> dict: return { "content": "回复内容", "reply_source": ["rule"] # 来源列表 } def handle_byod(...) -> dict: return { "content": "回复内容", "reply_source": ["byod"] } def handle_vision(...) -> dict: return { "content": "回复内容", "reply_source": ["vision"] } def handle_graph(...) -> dict: return { "content": "回复内容", "reply_source": ["graph"] } def handle_dify(...) -> dict: return { "content": "回复内容", "reply_source": ["dify"] } def handle_routing(...) -> dict: return { "content": "回复内容", "reply_source": ["routing"] } def handle_assets(...) -> dict: return { "content": "回复内容", "reply_source": ["assets"] } def handle_fallback(...) -> dict: return { "content": "回复内容", "reply_source": ["fallback"] } ``` ### 3.4 Persist层统一处理 ```python def persist_message(conversation_id: str, content: str, reply_source: List[str], ...): """持久化消息,统一处理来源标识""" # 追加来源标识到显示内容 display_content = append_source_marker(content, reply_source) # 保存到数据库(原始content + reply_source字段) message = Message( conversation_id=conversation_id, content=content, # 原始内容 reply_source=json.dumps(reply_source), # 来源列表 created_at=datetime.now() ) db.save(message) # WebSocket推送(带标识的内容) ws_push(conversation_id, { "type": "ai_reply", "content": display_content, # 带标识 "reply_source": reply_source }) ``` --- ## 四、配置文件 ```yaml # config/ai_reply.yaml reply_source: markers: byod: "🔒" rule: "⚡️" vision: "🖼️" graph: "🕸️" dify: "🤖" routing: "📋" assets: "💻" fallback: "⚠️" priority: - rule - byod - vision - graph - dify - routing - assets - fallback max_display: 3 # 最多显示3个标识 ``` --- ## 五、前端实现 ### 5.1 常量定义 ```javascript // 来源标识映射 const SOURCE_MARKERS = { byod: "🔒", rule: "⚡️", vision: "🖼️", graph: "🕸️", dify: "🤖", routing: "📋", assets: "💻", fallback: "⚠️" }; // 来源标签(坐席端详细展示) const SOURCE_LABELS = { byod: "BYOD拦截", rule: "本地快判", vision: "图片增强", graph: "Neo4j图谱", dify: "Dify推理", routing: "业务路由", assets: "资产推荐", fallback: "降级回复" }; ``` ### 5.2 H5员工端 - 消息气泡组件 ```javascript // src/components/MessageBubble.vue ``` ### 5.3 坐席工作台 - 来源详情展示 ```javascript // src/components/SourceDetail.vue ``` --- ## 六、接口设计 ### 6.1 消息查询接口(扩展) ```json // GET /api/messages/{conversation_id} { "messages": [ { "id": "msg_001", "content": "重置密码有以下方式...", "reply_source": ["graph"], "sender_type": "ai", "created_at": "2026-07-20T10:00:00Z" } ] } ``` ### 6.2 WebSocket推送(扩展) ```json { "type": "ai_reply", "content": "重置密码有以下方式... 🕸️", "reply_source": ["graph"], "message_id": "msg_001" } ``` --- ## 七、测试用例 | 用例 | 输入 | 预期输出 | |------|------|----------| | TC1 | reply_source=["graph"] | 显示 "🕸️" | | TC2 | reply_source=["routing","assets"] | 显示 "📋💻" | | TC3 | reply_source=[] | 不显示标识 | | TC4 | reply_source长度>3 | 按优先级取前3个 | --- ## 八、部署与配置 ### 8.1 配置热更新 标识配置支持热更新,无需重启服务: ```python # 配置热加载 def reload_config(): global REPLY_SOURCE_MARKERS, REPLY_SOURCE_PRIORITY config = load_yaml("config/ai_reply.yaml") REPLY_SOURCE_MARKERS = config['reply_source']['markers'] REPLY_SOURCE_PRIORITY = config['reply_source']['priority'] ``` ### 8.2 数据库迁移 ```bash # 执行迁移 alembic upgrade head # 或手动执行 ALTER TABLE messages ADD COLUMN reply_source VARCHAR(50) DEFAULT NULL; ``` --- ## 九、关联文档 | 文档 | 说明 | |------|------| | `PRD-REQ-AI-004-AI回复来源标识-v1.0.md` | 产品需求文档 | | `原型-REQ-AI-004-AI回复来源标识-v1.0.html` | 交互原型 |