这道题我觉得核心是在问:你怎么让大模型知道它训练时没见过的东西?[[RAG]] 的思路很简单,用检索代替记忆。模型不需要记住所有知识,需要的时候去外部数据库里查,再把查到的信息塞进 Prompt 让它生成。这样好处很明显:知识更新快,可控,[[幻觉]]也能压下去。
具体分三步走。先说离线索引,就是把文档切碎、转成向量存起来。这里有个前提:切分的粒度直接影响后面召回质量。切太粗,一块里面混着好几件事儿,检索容易带偏;切太细,上下文断了,模型看不懂。一般 chunk size 在 256 到 512 token,但真正落地时我会根据文档结构调整,比如技术手册按章节切,客服对话按轮次切。然后调个 [[Embedding]] 模型把文本转成向量,存到 [[Vector Database]] 里,像 Milvus 或者 [[Faiss]],用 [[HNSW]] 索引加速检索。
第二步是在线检索。用户提问后,同样用那个 Embedding 模型把问题转成向量,去库里做相似度搜索,召回 Top-K 个相关片段。这里有个常见的失败场景:纯用向量检索,碰上关键词匹配的场景容易翻车。比如用户问“订单号 ERR-2024-001”,向量检索可能因为语义不相似而漏掉精确匹配的文档。所以真正上线我一般用 [[Hybrid Search]],把向量检索和 [[BM25]] [[稀疏检索]]结合起来,比如线性加权或者 RRF [[重排]]。举个业务场景:电商客服处理退款,用户说“我买的东西降价了,能退差价吗”,向量检索能召回满减政策,BM25 能精准匹配“差价”这个词,两个互补,召回率能提不少。
第三步是生成。把检索到的片段和用户问题组装成 Prompt,交给大模型。Prompt 里我会明确写“仅根据以下信息回答,不知道就说不知道”,防止模型自由发挥。这里有个优化点:检索出的片段不一定都相关,需要过滤和重排。我会加一层 Rerank,用 [[Cross-Encoder]] 对候选片段和问题做精细匹配,只取置信度高的,这样生成内容更准。
说到优化,现在更前沿的做法是 [[Self-RAG]],让模型自己判断要不要检索、检到什么程度,甚至生成时反思检索结果够不够。比如模型发现当前上下文已经能回答,就不去检索,减少延迟。这种动态策略对长对话场景特别有用,但实现起来需要额外训练,对推理效率也有挑战。
所以整体来看,RAG 不是一套固定流水线,更像一套可插拔的组件。我的倾向是:先保证索引和检索的基础质量,再根据场景逐步加 Rerank、查询改写这些优化。如果上线前发现召回的片段质量波动大,我会优先排查切分粒度和 Embedding 模型的选择,而不是一上来上复杂策略。