历史对话多轮对话解析

多轮对话解析

完整流程图 (以发车多轮对话为例) ═══════════════════════════════════════════════════════════════════ 第1轮: 用户说 "发车到神经" ═══════════════════════════════════════════════════════════════════

┌─────────────────────────────────────────────────────────────────┐ │ router_node │ │ 1. 读取 Redis draft → 空的 (第一次请求) │ │ 2. awaiting_selection = false, awaiting_confirm = false │ │ 3. 调用大模型判断意图 → "send_car_node" │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ send_car_node │ │ 1. 读取 Redis draft → 空的 │ │ 2. 提取目标站点 "神经" → 模糊匹配 → 找到2个站点 │ │ 3. ★★★ 写入 Redis draft ★★★ │ │ save_draft(session_id, { │ │ "pending_stations": [神经内科, 神经外科], │ │ "awaiting_selection": true ← 标记为等待选择 │ │ }) │ │ 4. 返回: "找到多个站点: 1.神经内科 2.神经外科" │ └─────────────────────────────────────────────────────────────────┘

Redis 状态: tk:draft:session123 = { "pending_stations": [...], "awaiting_selection": true ← 已写入! }

═══════════════════════════════════════════════════════════════════ 第2轮: 用户说 "1" ═══════════════════════════════════════════════════════════════════

┌─────────────────────────────────────────────────────────────────┐ │ router_node │ │ 1. ★★★ 读取 Redis draft ★★★ │ │ draft = get_draft(session_id) │ │ → {"pending_stations": [...], "awaiting_selection": true} │ │ 2. awaiting_selection = true → 直接去 send_car_node │ │ (不调用大模型!因为已经知道用户在选择站点) │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ send_car_node │ │ 1. 读取 Redis draft → 拿到 pending_stations │ │ 2. 用户说 "1" → 选择第一个站点 (神经内科) │ │ 3. ★★★ 更新 Redis draft ★★★ │ │ save_draft(session_id, { │ │ "selected_station": 神经内科, │ │ "awaiting_selection": false, │ │ "awaiting_confirm": true ← 标记为等待确认 │ │ }) │ │ 4. 返回: "确认发车到神经内科吗?" │ └─────────────────────────────────────────────────────────────────┘

Redis 状态: tk:draft:session123 = { "selected_station": {...}, "awaiting_confirm": true ← 已更新! }

═══════════════════════════════════════════════════════════════════ 第3轮: 用户说 "确认" ═══════════════════════════════════════════════════════════════════

┌─────────────────────────────────────────────────────────────────┐ │ router_node │ │ 1. 读取 Redis draft → {"awaiting_confirm": true} │ │ 2. awaiting_confirm = true → 直接去 send_car_node │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ send_car_node │ │ 1. 读取 Redis draft → 拿到 selected_station │ │ 2. 用户说 "确认" → 调用发车 API │ │ 3. ★★★ 清除 Redis draft ★★★ │ │ clear_draft(session_id) ← 流程结束,清空草稿 │ │ 4. 返回: "发车成功!" │ └─────────────────────────────────────────────────────────────────┘

Redis 状态: tk:draft:session123 = (已删除) 总结:读写时机 函数 调用位置 时机 get_draft() router_node 每次请求进来,检查是否在多轮对话中 get_draft() send_car_node 恢复上一轮的状态 (候选站点、已选站点) save_draft() send_car_node 匹配到多个站点时 / 用户选择后等待确认时 clear_draft() send_car_node 发车成功或取消后,清空草稿 核心思想: 草稿就像一个"暂存区",在多轮对话过程中保存中间状态,让下一轮请求能"接上"上一轮的进度。

好的,来讲解一下这次 Redis 上下文记忆的实现:

我们加了什么? 两种持久化存储:

存储类型 Redis Key 用途 过期时间 对话历史 tk:chat:{session_id} 闲聊模块的上下文记忆 15分钟 业务草稿 tk:draft:{session_id} 发车多轮对话状态 15分钟 为什么需要两种? 闲聊模块 → 对话历史 (chat_context) 用户: "你好" 助手: "你好!我是小瑞" 用户: "你叫什么名字" ← 需要知道上文才能理解 助手: "我叫小瑞呀~"

业务模块 → 草稿 (draft) 用户: "发车到神经" 助手: "找到多个站点: 1.神经内科 2.神经外科" 用户: "1" ← 需要知道上一轮的候选列表 助手: "确认发车到神经内科吗?" 数据流程图 ┌─────────────────────────────────────────────────────────────┐ │ 用户请求 (带 session_id) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ router_node (路由节点) │ │ 1. 从 Redis 读取 draft,检查是否在多轮对话中 │ │ - awaiting_selection = true → 直接去 send_car_node │ │ - awaiting_confirm = true → 直接去 send_car_node │ │ 2. 否则调用大模型判断意图 │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────┐ │ send_car_node │ │ chit_chat_node │ │ 1. 读取 draft │ │ 1. 读取 chat_history │ │ 2. 处理选择/确认/新请求 │ │ 2. 拼接到 prompt │ │ 3. 保存 draft 到 Redis │ │ 3. 调用大模型 │ │ 4. 保存对话到 Redis │ │ 4. 保存对话到 Redis │ └─────────────────────────┘ └─────────────────────────┘ 关键代码

  1. config.py - 配置

TK_REDIS_HOST = "10.86.40.152" TK_REDIS_PASSWORD = "5Tb6nQd4" TK_CHAT_PREFIX = "tk:chat:" # 对话历史 TK_DRAFT_PREFIX = "tk:draft:" # 业务草稿 TK_CHAT_HISTORY_LENGTH = 6 # 保留最近6条 (3轮) 2. tkAgent.py - 辅助函数

get_chat_history(session_id) # 获取对话历史 save_chat_message(session_id, role, content) # 保存一条对话 get_draft(session_id) # 获取业务草稿 save_draft(session_id, data) # 保存草稿 clear_draft(session_id) # 清除草稿 (发车完成后) 3. tkMain.py - 传递 session_id

inputs = { "messages": [...], "session_id": session_id, # ← 新增,传给 Agent ... } 实际效果 现在你可以测试多轮对话了:

闲聊上下文

用户: "你好" 助手: "你好!我是小瑞..." 用户: "你刚才说你叫什么?" ← 能记住上文 助手: "我叫小瑞呀~"

发车多轮

用户: "发车到神经" 助手: "找到多个站点: 1.神经内科 2.神经外科" 用户: "1" ← 能记住候选列表 助手: "确认发车到神经内科吗?" 用户: "确认" ← 能记住选择的站点 助手: "发车成功!"

posted @ 2026-03-24 11:15  烈酒清茶  阅读(3)  评论(0)    收藏  举报