为什么把 RAG 当成模块更实用
对很多团队来说,RAG 的最终形态不是“一个大而全的知识库产品”,而是嵌在多个 Skill 里的能力:
- PR/设计文档检索 -> 输出必须带引用
- 工单/FAQ 检索 -> 低置信度触发人工
- 运行手册检索 -> 形成排障步骤
最小 RAG 管线(你应该明确每一步的契约)
把 RAG 写成可替换的步骤:
- 采集(ingest)
- 切分(chunk)
- 表征(embed)
- 检索(retrieve)
- 重排(rerank,可选)
- 生成(generate with citations)
每一步都应该有输入输出契约与失败类型。
Chunking:别迷信固定长度
工程建议:
- 以语义边界切分(标题/段落/代码块)
- 保存结构信息(标题层级、来源、时间)
- chunk 太大:检索噪声高;太小:语义不完整
检索:先做混合检索,再谈高级技巧
建议优先顺序:
- 关键词检索(BM25)+ 向量检索(embedding)混合
- top-k 控制在小范围(例如 5-20)
- 过滤条件优先(时间范围、文档类型、权限范围)
重排(Rerank):用来“提升 top-k 的质量”
重排适合解决:
- 检索召回太宽,top-k 不够准
- 语义相近但不相关的片段混入
工程建议:
- 先记录“检索候选集”和“重排后结果”,便于调参
- 预算明确:重排通常更贵
引用:没有引用的 RAG 等于没有 RAG
强制输出引用(source id / url / file path / snippet)能带来:
- 可验证性(减少幻觉)
- 可评测性(对比引用是否正确)
- 可排障性(知道证据从哪来)
置信度:让系统敢于说“我不知道”
建议在以下情况下触发 LOW_CONFIDENCE:
- 检索结果为空或过少
- 引用之间冲突
- 生成内容无法对应到引用片段
降级策略:
- 要求用户补充信息
- 给出“可能的答案 + 需要的证据清单”
- 走人工确认点
动手做:把 RAG 做成一个可复用子 Skill
你可以把“检索 + 引用输出”单独封装成 knowledge.lookup:
- 输入:query + filters + top_k
- 输出:items(含 snippet + source)+ confidence
- 失败:AUTH_REQUIRED / EMPTY_RESULT / TIMEOUT
上层 Skill 只消费结构化结果,而不关心底层实现细节。
工程化清单
- 每个 chunk 都带来源与权限元数据
- 检索结果可回放(记录 query/filters/top-k)
- 输出必须带引用
- 置信度与降级策略显式
常见坑
- 只做向量检索不做过滤:越权与噪声一起出现
- 不做引用:看似回答对了,但无法验证也无法评测
- 不记录检索过程:调参全靠猜