假设你已经积累了一批开发笔记,想问:“上次部署博客时,怎样检查服务有没有启动?”直接把问题交给通用模型,它未必知道你那次的操作过程。一个更贴近需求的方案,是先从自己的资料里找出相关片段,再让模型据此回答。
这就是检索增强生成,也常简称为 RAG。原始 RAG 研究把参数化的生成模型与可检索的外部知识结合起来,用于知识密集型任务。下面的个人笔记方案是工程化的简化示例,不是在复现论文的训练流程。Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
先让每个片段可以被找到
可以先以 Markdown 为输入,保留文件路径、文章标题、小节标题和修改时间,再按小节切分正文。遇到过长的小节,再进一步切分。
一条候选记录可以长这样:
{
"id": "deploy-blog/service-check",
"title": "博客部署笔记",
"section": "检查服务状态",
"source": "notes/deploy-blog.md",
"text": "这里保存该小节的完整说明和命令。"
}
切分时要留意语义是否完整。命令与它的解释、配置项与适用条件,尽量保留在同一个片段里。切块长度需要根据文档结构和实际问题调整,没有适用于所有资料的固定数字。
检索方案从最容易验证的开始
资料量不大时,可以先做关键词检索,检查标题、小节和正文能否找到答案。问题中有错误码、函数名和配置键时,精确匹配尤其值得保留。
如果用户经常换一种说法提问,再考虑语义检索:把查询和文本编码为向量,通过相似度找候选片段。这里的相似度只是排序信号,不能直接当成“答案正确的概率”。
还可以把关键词结果和语义结果合并、去重,再检查实际召回效果。选择更复杂的检索方式之前,先保留一组问题,看看它究竟改善了哪些失败案例。
生成阶段要能回到原文
把候选片段交给模型时,为每段材料分配一个编号,并要求回答中的事实对应到这些编号。下面只是便于理解的数据流伪代码:
问题 → 检索候选片段 → 去重与筛选
→ 拼装带编号的材料 → 生成回答
→ 校验引用编号 → 展示答案和原文入口
如果没有足够材料,允许返回“当前笔记中没有找到”。不要为了让页面看起来完整,强制模型为每个问题给出确定答案。
应用还应检查引用编号是否确实存在,并让读者打开对应原文。编号有效和引用内容支持结论,是两项不同的检查。 前者可以程序校验,后者仍需通过评估或人工抽查确认。
先评估检索,再评估回答
可以从二十个自己确实会问的问题开始,其中放入几个资料里没有答案的问题。这个数量只是一个便于起步的工作规模,不是质量保证。
逐个记录:
- 检索结果里是否包含回答所需的原文?
- 生成的结论是否能被原文支持?
- 引用是否指向了正确的小节?
- 没有资料时,系统是否明确说明缺失?
如果正确原文从未进入候选列表,先改检索。原文已经找到,回答仍混淆条件,再检查上下文组织和生成要求。把两类问题分开,调试会具体很多。
把资料更新也纳入流程
笔记改名、删除或修订之后,索引也要同步变化。可以用内容哈希识别变更,只更新发生变化的片段,并清除已删除文件对应的记录。
如果以后接入多人资料,还需要在检索阶段落实访问权限。检索到的文字应当作为参考数据处理,不能因为某个文档写着“忽略规则”,就改变应用的工具权限。
一个有用的笔记问答工具,应该让你更快找到证据,也更容易发现资料的空白。答案的措辞可以慢慢打磨,原文入口值得从第一版就保留下来。