🎬 演示视频
demo.mp4(0.74 MB,1440×900,H.264,14.5 秒)是本 Release 的附件,README 里内嵌的 GIF 预览由同一份录屏转出。
这是真录屏,不是 AI 生成的示意动画:无头 Chromium 真实打开 localhost:3000,真实调用后端 SSE 接口,画面里的每个字都是模型当场流式吐出来的。
视频内容:
| 时间 | 画面 |
|---|---|
| 0.0–1.2s | 聊天首页加载(深色) |
| 1.2–2.2s | 主题切换到浅色,再切回深色 |
| 2.2–6.5s | 点快捷问题「混合检索是怎么工作的?」→ 真实流式回答(打字光标) |
| 6.5–8.0s | 展开引用溯源,悬停消息展示复制 / 重新生成 |
| 8.0–14.5s | 追问「企业版买 20 个账号多少钱?」→ 模型算对 1280 × 85% × 20 = 21,760 元 |
🐛 RAG 数据链路三个静默丢内容的缺陷
共同点:都不报错,链路全是 200 OK,只在模型侧表现为「答非所问 / 说原文被截断 / 未找到相关信息」。
- 清洗器把行内百分号当 LaTeX 注释删了。
%.*$会把行内任意%到行尾整段删除,「按原价的 85% 收费;如客户购买 20 个账号……」入库时被削成「……按原价的 85」。改为只认行首的整行注释。 - 上下文截断在三处各写死一次且都小于 chunk_size(300 / 600 / 600 vs 默认 500–5500),长 chunk 文末被静默切掉,导致 Agent 链路答「未找到相关信息」而 RAG 链路却答得出来。统一为
settings.context_snippet_chars。 - 推理模型
<think>思考块混进正文。新增app/core/text_utils.py,流式侧用状态机过滤(能处理<think>被切到两个 chunk 之间的情况)。
另外修了测试污染:conftest 只重定向了 *_PERSIST_DIR,而 kb_registry.json 直接挂在 DATA_DIR 上,跑一次 pytest 就会把本地知识库注册表冲掉。
✅ 测试
378 passed(新增 29 条回归)
🔁 复现演示
cd backend && python run_demo.py kb-unikb-demo
cd frontend && NEXT_PUBLIC_DEMO_KB=kb-unikb-demo npm run dev
cd frontend && node record_demo.mjs
python scripts/build_demo_assets.py