这道题问的是[[RAG]]的完整工作流,其实本质是在问:怎么把大模型的知识边界和实时性不足这个短板,用外部知识库补上,同时还要控制[[幻觉]]。不是简单拼凑,而是每个环节都要做取舍。
先说检索之前,有个预处理。用户的问题往往不规整,比如“上次那个退款怎么还没到”,这里“上次”指代什么?得先做查询改写,把指代消解掉,拆成“订单号xxx的退款进度”。这一步不做,后面检索全是错的。
然后进入检索,这是最核心的部分。很多人以为向量检索就够,但实际落地,纯向量语义检索在专有名词、订单号、政策条款号上几乎必挂。我一般用 [[Hybrid Search]],把向量召回和 [[BM25]] 关键词召回结合起来,分数加权融合。举个例子,客服场景里用户问“满200减30怎么用”,向量能理解“满减”语义,但BM25能精准匹配活动ID或商品SKU,两条腿走路才稳。
检索出来Top-K比如100条,不能全扔给大模型,上下文窗口有限,而且噪声多。所以第二步是[[重排序]]。这里我会用 [[Cross-Encoder]] 做精排,把query和每个文档拼接打分,虽然慢,但精度高。粗排是 [[Bi-Encoder]] 快速筛,精排用Cross-Encoder挑出最相关的5-10条。这里有个坑:重排序分数低的不直接丢掉,要设个置信度阈值,低于阈值的触发兜底逻辑,比如告诉用户“没找到相关信息,请换个问法”。
接下来是上下文构建。文档长度不一,不能硬塞。我会按相关性排序后拼接,超长时做截断,优先保留高相关片段而不是开头。同时把来源、时间、标题这些元信息结构化注入,方便生成时引用。Prompt模板也很关键,要明确区分系统指令、检索结果和用户问题,否则模型容易混淆。
生成阶段,我会约束模型必须基于检索结果回答,不确定时明确说“根据已有资料无法回答”,而不是瞎编。同时要求输出引用标注,比如“[1][2]”,方便溯源。最后做一次后处理校验,检查生成内容与检索结果的事实一致性,冲突时过滤掉。
还有一个点值得注意:当检索结果为空或置信度极低时,是直接拒绝还是触发联网搜索?我倾向先拒绝,因为RAG的目标是可控性,联网搜索会引入不可控风险。但如果业务允许,可以设计一个降级策略,比如提示用户补充关键词。
整体上,我会把RAG看成一个检索增强的闭环系统,不是简单的管道。每个环节的失败场景都要有预案,比如知识库更新不及时导致旧政策被检索出来,这时需要版本控制或时间戳过滤。上线前,我会用 [[RAGAS]] 这类工具评估 [[Faithfulness]] 和 [[Context Recall]],保证回答既忠实于检索内容,又覆盖了必要信息。