开始做知识库问答之前,我以为难点在提示词和模型选择。真正做下来,大部分时间花在了更朴素的地方:文档从哪里来、内容干不干净、谁能看到。
回答的上限在数据
同一份文档在不同地方存着好几个版本,模型该信哪一个?表格被解析成一串没有表头的数字,检索到了也没法用。没有权限的人提问,能不能被答出来?
这些问题都不是调提示词能解决的。所以项目的第一阶段只做一件事:把文档接入、清洗、管理好版本和可见性,并且保证每一次变更都能可靠地通知到下游。
检索和回答分开看
回答错了,可能是没检索到,也可能是检索到了却没用好。混在一起看,很难知道该改哪里。
所以后台有一个单独的「命中测试」页面:只检索、不生成,直接展示召回的片段、向量与关键词的排名、重排后的分数。先确认资料找得到,再看回答写得对不对。
先评测,再优化
试过一个看起来很合理的优化:把复杂问题改写拆分成几个子问题并行检索,再合并结果。在评测集上对比之后,效果没有明显提升,成本却增加了。于是这个功能保留开关,默认关闭。
如果没有评测集,我大概会凭感觉把它开着。
让每一次回答都能回放
一次回答要经过问题改写、检索、重排、生成好几步。接入 Langfuse 做链路追踪之后,每一次回答用了哪些资料、花了多少 token、哪一步耗时最长,都能完整地回放。线上被点踩的回答可以直接导出,变成下一轮的评测样本。
一点体会
RAG 的「G」很容易做出效果,「R」决定了效果能不能被信任。这个项目还在迭代,权限场景的评测、更细的引用定位,都是接下来要补的课。