2026-04-22: Unified Chat(事件流)把“可用”升级为“可观测”,Text2SQL v1 跑通最小闭环

0 阅读5分钟

2026-04-22: Unified Chat(事件流)把“可用”升级为“可观测”,Text2SQL v1 跑通最小闭环

日期与进度概览

  • 日期:2026-04-22
  • 进度:Unified Chat v1(RAG/Text2SQL/Chain)联调推进,链路可观测性落地
  • 关键词:Unified Chat、SSE(text/event-stream)、events[](Chain Timeline)、Intent Router v1、Text2SQL v1、FAISS、Supabase/RLS

TL;DR

  • Text2SQL v1 闭环跑通:检索(DDL+样例)→ 生成 SQL → 只读校验 → 执行 → 结果总结,并补齐端到端验收思路。
  • 事件模型 events[] 落地:工具调用、SQL 结果、sources、latency、error 统一事件化,前端可直接渲染 Timeline。
  • Unified Chat 新入口成型:一次性 JSON + SSE 流式 events(v1 以“事件实时”为第一目标)。
  • Intent Router v1 可解释router.decision 输出 why + evidence,右栏可视化,误路由可定位可回归。

1) 今日关键目标

  • 链路可观测:v1 不只跑通,更要“看见链路”——出问题能定位到阶段与证据。
  • Text2SQL 可验收:从“能生成 SQL”推进到“可执行 + 可总结 + 可验收”的最小闭环。
  • 前端实时呈现:SSE 事件增量渲染,Timeline 在 tool 执行过程中实时增长。

2) 关键产出 / 决策(Why + What)

2.1 为什么新增 Unified 入口,而不是直接改旧聊天接口

  • 决策:新增 Unified Chat 作为并行新入口(JSON + SSE),旧接口保持稳定。
  • 原因:旧接口以“流式纯文本”为主,改动风险高;Unified 用 events[] 承载工具链与调试信息,更适合渐进替换。
  • 影响面:前端用统一 Timeline 渲染多模式(rag/text2sql/no_data),后端可按事件回放做回归定位。

2.2 为什么 v1 先做 SSE 事件流,而不是更重的协议

  • 决策:v1 采用 SSE(text/event-stream)推送 event: chain / event: done(可选 token)。
  • 原因:单向推送、实现成本低、BFF 易透传;优先实现“事件实时”,token 级流后续再加。
  • 影响面:工具调用开始/结束、SQL 结果、sources、错误与耗时都能实时出现在 Timeline,排障速度显著提升。

2.3 为什么路由器必须输出证据链,而不只是给最终分类

  • 决策:在事件中新增 router.decision,携带 candidate/final/rule_hits/evidence/fallback
  • 原因:意图路由属于“决策系统”,没有 why/evidence 就无法调参、无法回归、也无法解释误判。
  • 影响面:右栏可直接展示决策过程;后端也能把 evidence 当成可观测指标做长期优化。

3) 前端侧总结(从“能显示”到“能排障”)

3.1 SSE 链路与解析

  • BFF 透传:保持 Content-Type: text/event-stream,并直接返回 upstream.body(ReadableStream),让上游事件无损到达 UI。
  • 解析策略:采用“buffer + block”累积后按 \n\n 切块,仅消费完整块,避免 chunk 边界造成半截 JSON 丢事件。

3.2 Timeline 与答案展示

  • Timeline 增量更新event: chaindata 转为统一 ChainEvent,追加到 events[],中栏 Timeline 逐条增长。
  • 最终答案兜底抽取response.answer → 最后一条 assistant.message → 最后一条 tool.call.end.payload.output.answer,避免“链路有输出但看不到结论”。

3.3 Router Debug(可解释性)

  • 右栏面板:从 events[] 提取 router.decision,展示 final_mode/rule_hits/evidence/fallback,让误路由“可解释、可复现、可截图验收”。

4) 后端侧总结(把链路做成“可回放的事件”)

4.1 Text2SQL v1:最小闭环(可执行 + 可总结)

  • 检索:以“DDL + 示例问答/SQL”为核心语料,FAISS 优先;缺失时降级为 fallback store(纯 Python 相似度排序),保证可用性。
  • 安全:SQL 只读校验(仅 SELECT / WITH…SELECT),执行阶段限制返回行数。
  • 结果总结:对聚合结果(如 count/cnt)做更确定的总结,降低 LLM 把 count=0 误解释为“未查到数据/系统异常”的风险。

4.2 Unified Chat:JSON + SSE(以事件为第一性输出)

  • 一次性 JSON:返回 { ok, run_id, mode, events[] },便于测试与回放。
  • SSE:按阶段输出 event: chain(单条 event JSON),结束输出 event: done
  • 事件模型(v1)tool.call.start/endsql.resultrag.sourcesassistant.messageerrorlatencyrouter.decision

5) 风险与坑位(含排障线索)

5.1 依赖缺失导致 500(FAISS)

  • 现象:Text2SQL store 初始化报缺少 faiss-cpu
  • 根因:运行环境未安装对应依赖。
  • 当前策略:fallback store 兜底 + 可开关调试日志(例如 TEXT2SQL_DEBUG=1)。

5.2 “查询成功但返回 0 行”的假象(RLS / Pooler / 用户名格式)

  • 现象:SQL 执行不报错,但结果集为 0;或连接失败(用户名/租户相关错误)。
  • 常见根因
    • Pooler 连接的用户名格式要求与直连不同
    • RLS policy 没有放行只读角色导致“看不见数据”
  • 修复方向
    • 使用正确的 pooler 连接方式
    • 为 Text2SQL 相关表补齐只读 SELECT policy(并记录到可回归的初始化脚本里)

5.3 多项目环境变量污染

  • 现象:LLM key 401(看起来像 key 无效,但实际是读到了别的环境变量)。
  • 根因:启动流程加载了错误的 .env 来源。
  • 修复方向:启动与自检时明确 dotenv 加载路径或显式 source,避免跨目录污染。

5.4 误路由:SQL 意图被回退到 no_data

  • 现象:明显查数/SQL 意图被判到 no_data
  • 根因:证据校验阈值/召回策略导致 ddl_hits=0 或 evidence 不充分。
  • 修复方向:降低阈值、加入“表名字符串候选召回 + 判别器”替代纯分数阈值。

6) 明日计划(可执行 checklist)

  • 补一组“路由回归用的固定问题集”(rag/text2sql/no_data 各 3–5 条),用同一份 events 输出对比版本差异
  • router.decision 的 evidence 增加更稳定的字段(例如 ddl_hits/fts_hits/top_tables),并在前端面板做结构化展示
  • Text2SQL 的 Supabase 初始化脚本与 RLS policy 固化为可重复执行的版本化文件

工程图(Unified Chat:事件模型驱动的可观测闭环)

router展示

flowchart LR
  U[用户输入] --> UI[前端 Unified Chat UI]
  UI -->|POST SSE| BFF[Next BFF /api/py/unified/chat/stream]
  BFF -->|透传| PY[后端 Unified Chat]

  PY --> R[Intent Router v1]
  R -->|router.decision| EVT[events[] / chain events]

  PY -->|rag| RAG[RAG 链路]
  PY -->|text2sql| T2S[Text2SQL v1]

  RAG --> EVT
  T2S --> EVT

  EVT -->|event: chain| UI
  UI --> TL[Timeline 实时追加]
  UI --> DBG[Router 决策 Debug]
  UI --> ANS[最终答案兜底抽取]