这道题问的是[[RAG]]的实现架构,其实本质上是在问:你怎么让大模型在回答时能拿到最新、最准确的外部知识,而不是完全依赖它训练时记住的那些东西。RAG和微调的区别就在这里,微调是往模型脑子里塞知识,但更新成本高、容易遗忘;RAG是把知识挂在外面,需要时再查,这样知识更新和模型解耦。
整体架构分两条线:离线把知识库建好,在线做检索和生成。先说离线部分,核心就是把文档变成可检索的向量。文档解析这块,PDF、网页、Word格式不一样,我一般会保留标题层级和表格位置,因为这些对后面[[分块]]很重要。分块是个关键决策,固定长度切分最简单,比如512个token一块,但容易把逻辑相关的句子拆散;语义分块效果好,但依赖模型且慢。真实落地时我倾向用递归分块,先按段落切,超过上限再按句子切,这样既保留结构又控制长度。分完块后用[[Embedding]]模型编码成向量,存到[[Vector Database]]里,比如Milvus,索引用[[HNSW]],兼顾速度和召回。
在线流程从用户提问开始。先做查询改写,比如用户说“它怎么退款”,得把“它”还原成具体商品或订单号,不然检索会偏。然后是多路检索,这里我强调一下边界:向量检索擅长语义匹配,比如用户说“手机屏幕碎了”能召回“碎屏险理赔流程”;关键词检索擅长精确匹配,比如订单号、错误码。所以真正落地我都是两条路一起上,用[[Hybrid Search]]把向量和[[BM25]]的结果合并。检索完top-K结果后,用[[Rerank]]模型精排,把最相关的几条提到前面,这一步对最终质量影响很大。排完序后组装上下文,注意控制长度,一般不超过LLM上下文的30%到50%,太长会稀释注意力。最后构造Prompt让LLM基于上下文回答。
这里有个常见的失败场景:如果知识库里根本没有正确答案,再好的检索也白搭。所以上线前我会特别关注分块质量,用[[RAGAS]]这类工具评估召回率和[[忠实度]]。还有就是缓存,高频问题直接走缓存,能省掉检索和生成的开销。
还有一个方向是动态分块,根据问题的粒度调整块的大小。比如问“公司年假政策”这种宏观问题,需要大块上下文;问“某天请假扣多少钱”这种具体问题,小块就够。如果面试官有兴趣,可以聊聊怎么用query分类来决定分块策略。
所以整体上,我更倾向于把RAG看成一个检索系统加一个生成系统的组合,检索的精度决定了生成的上限。在工程落地上,我会先保证检索的召回和排序不出大问题,再优化生成侧的Prompt和模型选择。