Skip to content

v1.1.6

Choose a tag to compare

@bulolo bulolo released this 03 Jun 11:38
· 3 commits to main since this release

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 服务又梳了一遍:

  • ChatContext dataclass: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 的判断永远不触发、进度永远不动。已修正。