Nexus 线上排障记:知识库问答为什么只让我”去查 SOP”
上周刚把 Nexus 送上云,这周线上知识库问答就出了问题。用户在聊天页问”如何为 TeamfightManager2 创建新英雄 mod”,Agent 第一轮只回一句”去查 SOP 02”;追问具体步骤,它干脆承认”未获取到正文内容”。连续两轮失败,答案明明就在知识库里。于是有了这次排障。
1. 定位根因:先在本地完整复现
排障第一步不是改代码,而是先复现。用与生产完全相同的语义分块器 + embedding 模型,重建 13 份 SOP 文档的索引(125 个分块),原样重放那两轮提问——线上两次失败精确复现。
复现之后看数据,根因不是单点,是四层叠加:
目录页效应(主因)
各 SOP 的标题/简介块、README 索引、“下一步”链接表,和”我想做 X 怎么操作”这类问题在语义上天然最近,会把正文块挤出检索窗口。数据很直观:第一轮检索中,SOP 02 的最佳正文块只排第 13 名;第二轮 Agent 已经命中 SOP 02 标题、明确知道该看哪份文档了,正文块反而排到第 16 名。top_k=5 拿不到,top_k=10 照样拿不到。
top_k 参数化失效
_run 签名里的参数默认值永远会被 Pydantic 填充,导致 config_json 里的 top_k 配置从不生效。讽刺的是,2026-08-02 的评估报告 P0-1 就指出过这个问题,一直没修——这次它和目录页效应叠加,等于窗口本来就小,还调不大。
检索结果缺 document_id / position
工具输出里没有这两个字段,Agent 就算明确知道答案在 SOP 02,也没有办法锁定这一份文档继续翻正文。
单轮检索 + 预注入偏置
任务指令只说”先检索一次”;预注入(pre-inject)恰好注入的又是导航块,开局就把 Agent 推向目录页。
四层叠起来的效果是:检索窗口里全是目录,窗口大小配置调不动,结果里没有文档定位信息,指令也不许它再查一次。Agent 表现成那样,其实已经尽力了。
2. 修复:四件套 + 配套
| 项 | 改动 |
|---|---|
| top_k 修复 | schema 默认值当哨兵 → 改用 top_k_default(config_json 真正生效),默认 5 → 10 |
| 二段检索 | 混合检索 SQL / map_rows / 工具输出全链路带上 document_id + position;knowledge_qa 种子注入多轮检索指令(首轮只有目录 → 换关键词,或锁定 document_id 加大 top_k 再查,最多三轮) |
| 切块上下文化(治本) | 新增 contextualize_chunks:按 markdown 标题层级给每块注入 [文档名 · 章节路径] 前缀(嵌入与存储同时生效);API 上传 + kb_ingest 工具两条入库路径均已接入 |
| 预注入排导航 | 预注入 SQL 排除多块文档的 position=0 导航块(单块文档豁免) |
四项改动分别对应四层根因,其中切块上下文化直接针对目录页效应这个主因。
配套改动一并落地:SOP 语料按 kb_seed/ 惯例入库仓库(语料从此进版本管理)、重入库脚本 reingest_docs.py、复现脚本 repro_sop02.py、前端类型与表单默认值同步、doc/tool-guide.md 更新。
3. 验证:全绿
单测:新增 19 项(top_k 哨兵、输出格式、上下文化、SQL 结构),全量 233 项通过。
本地完整栈:Docker 起 pgvector + zhparser + backend + frontend 的完整环境(顺手修了旧数据卷缺 nexus_app 账号的连库问题),14 份 SOP 重入库后,同样两轮查询 top-10 全部命中 SOP 02 正文,document_id 限定检索精准命中。
聊天端到端是最有说服力的一项。Agent 按设计执行了三轮检索:
- 宽泛检索 → 拿到目录;
- 锁定
document_id=153拉取 15 个分块; - 补查 SOP 03。
最终回答给出了 .data_champion 最小 JSON、字段陷阱、i18n、立绘配置的全流程步骤——和线上那句”未获取到正文内容”形成完整反转。
e2e 冒烟:smoke_rag、smoke_single_chat 均通过。
4. 发布
提交 0e0ae0a(33 个文件,+3635/-258)推送 GitHub master_server,并生成传输包 nexus-rag-fix.bundle——就是上次部署博客里说的 git bundle 私传姿势。服务器侧四步走完:更新代码 → make rebuild → 种子同步 → SOP 重入库,现已确认线上生效。
结语
这次排障两条心得。一是复现优于猜测:先在本地用同款分块器和 embedding 把问题精确复现,再动手改,每一层根因都有数据支撑,而不是凭感觉换 prompt。二是**“Agent 不行”很多时候是”工具不行”**:四个问题单独看哪个都不致命,叠起来才让 Agent 两次都答不上来;把 document_id、多轮检索、上下文化这些能力补上之后,它自己就会走完宽泛 → 锁定 → 补查的完整链路。
现在再问一遍”如何创建新英雄 mod”,Nexus 会把最小 JSON 和字段陷阱一条条讲给你听。上线只是开始,接下来就交给真实用户的问题了。