Repository navigation
v1.1.6
2026-06-03 👍 用户反馈 + 对话性能透视 (v1.1.6)
这一版围绕**"让对话质量看得见"做了两件事:用户可以给每条 AI 回答点👍/👎(踩还能填原因),管理员能在后台看到差评的分布和具体内容;同时新增了一个可选的对话性能面板**,把"这次回答慢在哪"摊开给用户看。后端这一版还顺手把聊天服务整个重构了一遍,并修了一个"客户端关掉页面、后端还在白白算"的浪费。
用户能直接感受到的:
- 每条 AI 回答能点👍/👎了:点踩可以选个原因(答非所问 / 信息过时 / 等等),反馈会持久化,刷新页面也还在
- 管理员能看差评长什么样:后台「详细分析 → 用户反馈」新增一个 tab,差评原因分布(环形图)+ 差评消息列表(带 markdown 渲染和详情弹窗),复盘"用户到底对哪类回答不满意"
- 对话性能面板(可选):站点设置里打开开关后,对话界面能看到首字延迟、各轮检索耗时、总耗时和 Token 用量;默认关闭,机器人渠道强制关闭
- 关掉聊天页面,后端立刻停手:以前客户端断连后,后端的 AI 推理还会继续跑到结束(白烧算力和 token),现在断连会立刻取消后端图执行
👍 新增:用户反馈系统
客户端 AI 对话的每条回答下方多了👍/👎按钮。点👎时弹出原因选择,反馈实时写库;同一访客对同一条消息只保留一条记录(再点一次切换或取消)。
为什么用 (thread_id, message_seq) 而不是直接传消息行 ID:用户点👍的瞬间,后端的 background task 可能还没把这轮消息落库,前端根本拿不到数据库行 ID。所以前端传"第几条 assistant 回复"这个稳定坐标,后端再解析成真实消息 ID(带重试兼容写库竞态)。一个 turn 在底层可能拆成多条(工具调用 + 工具结果 + 最终回答),message_seq 抽象掉中间步骤,精确定位到最终那条回复。
管理后台「详细分析 → 用户反馈」tab(企业版):
- 顶部 KPI 行 + 差评原因环形图分布
- 差评消息列表:卡片预览用 Streamdown 渲染 markdown(保留 3 行截断),点开是完整内容 + 原因标签 + 时间的详情弹窗
- 分页条常驻,单页时翻页按钮自动禁用
📊 新增:对话性能透视(可选开关)
站点设置新增 show_pipeline_trace 开关(默认关闭)。打开后,客户端对话界面会展示这次回答的性能数据:
- TTFB / 首字延迟 / 总耗时:拆出"后端准备 → 首个数据包 → AI 开始打字 → 全部结束"的各段时间
- 每次工具调用的耗时:通过
run_id把工具开始/结束精确配对,并行检索也不会错位,每个工具卡片显示自己实际花了多久 - Token 用量:input / output / total,多轮 ReAct 的多次 LLM 调用自动聚合
这些数据会跟着历史一起持久化(复用 ChatMessage.additional_kwargs),历史回看时一样能看到。开关关闭时后端一概不下发、不落库——连 LangChain 原生写入的 usage_metadata 也会被剥离,保证 Tokens 不会从历史里"漏出来"。机器人渠道(钉钉/飞书/企微/Telegram)强制关闭,只有站内 / 网页渠道按站点开关走。
⚡ 客户端断连即取消后端计算
以前的流式实现里,如果用户中途关掉页面或断网,后端的 graph.astream_events 还会继续跑完整个 ReAct 循环——上游 LLM 的 token 照烧不误。
这一版把图执行包进独立的 asyncio.Task,通过队列与消费端通信。客户端断连时 finally 块直接 task.cancel(),把 CancelledError 注入到当前正在 await 的 LLM 请求点,后端立即停手。对高并发场景下的算力和 token 成本是实打实的节省。
🏗️ 聊天服务重构
借这次功能落地,把 chat 服务又梳了一遍:
ChatContextdataclass:initialize_chat_context统一返回(llm, initial_state, config, tenant_id),thread_id/model_name收成@property,消除满地散落的config["configurable"]["thread_id"]- 消除双路径重复:completions 和 responses 两条流式路径以前各写各的图组装,现在共用
_generate_graph_chunks产出器(消除 4 处async with get_checkpointer()重复 + 2 个内部闭包) - 图节点提取为模块级:解除原本的嵌套闭包,节点函数独立可测
- tracker 状态机 / 超时保护 / 历史格式化等中优先级审计项一并处理
- usage 始终下发修复:Responses API 按 spec 要求让
response.completed始终携带 usage(前端再按开关决定是否渲染)
🐛 关键修复
- 文档学习状态卡在"排队中"不自动刷新:admin 文档列表的轮询回调里读的是原始 API 数据结构(
{ list }),而非select变换后的{ documents },导致refetchInterval的判断永远不触发、进度永远不动。已修正。