这道题问的是[[RAG]]的完整流程,但我觉得面试官更想听的不是我背一遍流程,而是我有没有真正踩过坑,知道每个环节为什么这么设计。说白了,RAG的本质就是给大模型配一个外挂知识库,让它别再胡编乱造。那这个外挂怎么建、怎么查、怎么用,我分三个阶段来拆解。
先说离线建库。这一步的核心矛盾是:知识颗粒度太粗,模型找不准;太细,又丢了上下文。比如客服场景里的退货政策,一个段落可能有三四百字,里面包含适用条件、退款时限、特殊品类限制,如果按固定512 token切,很可能把条件跟结论切到两个块里,检索时只召回后半段,模型就漏读了前置条件。所以我的做法是优先按语义段落切,比如Markdown标题、空行,实在不行再用递归字符切,同时保留前后重叠。分完块之后做 [[Embedding]],这个环节有个坑:通用Embedding模型在垂直领域效果很差。比如金融风控合同里“不可抗力”这个词,通用模型可能把它跟自然灾害关联,但业务上它更多指政策变更。所以我会建议用领域数据微调Embedding,或者退一步,加上 [[BM25]] 做 [[Hybrid Search]]。索引存储我倾向用 [[Faiss]] 加 [[HNSW]] 图索引,因为它的召回率和延迟平衡得好,但如果业务需要过滤元数据,比如只查某个品类的文档,那 Elasticsearch 更灵活。
再来看在线检索。用户问“我的订单怎么还没发货”,直接拿这个query去向量检索,很可能召回的是“发货流程说明”而不是“物流异常处理”。所以第一步是Query理解:我会把query改写成更精确的表达,比如“订单延迟发货的原因和解决方案”,或者用 HyDE 先生成一段伪文档再检索。检索阶段,我通常召回 Top 50,然后用 [[Cross-Encoder]] 做 [[重排]],把最相关的 3 到 5 个片段挑出来。这里有个关键点:重排模型必须跟向量模型解耦,否则容易陷入局部相似性。比如向量模型认为“价格”和“金额”相似,但重排模型能识别出用户问的是“满减价格”而不是“原价”。
最后是生成阶段。检索结果拼成上下文后,Prompt 怎么写直接影响回答质量。我会明确告诉模型:“如果参考信息里没有,就说不知道,不要自己编。” 同时要求它引用来源片段编号,方便溯源。但光靠Prompt不够,比如用户问“退款多久到账”,参考信息里只说了“1-3个工作日”,模型却可能脑补出“节假日顺延”。所以我会在生成后加一层 [[Faithfulness]] 校验,用另一个小模型检查答案是否严格基于检索内容。
说到这,我想提一个我最近在关注的方向:当知识库频繁更新时,离线建库和在线检索之间的延迟怎么处理。比如电商大促期间,满减政策每小时变一次,如果重建整个索引成本太高,增量更新又可能影响召回一致性。这块我目前是先把新旧版本分层存储,查询时做版本合并,但实时性还是不够理想。
所以整体上,我会把RAG看成一套需要根据场景动态调整的管线。比如客服场景,召回率比延迟更重要,我会用重排加多路召回;但如果是实时问答机器人,延迟敏感,我会牺牲一点召回率,只用向量检索加轻量级过滤。没有银弹,只有取舍。