ARTICLE · 1312501
AI知识点拆解 · RAG 检索增强生成:给大模型外挂一个"随身资料库"
一、招聘市场怎么说
翻 BOSS 直聘上 大模型应用开发 / AI 算法 / RAG 方向 的近期 JD,RAG 已从"加分项"变成"必选项",且要求越来越细:
注意关键词的变化:一年前 JD 只写"会用 LangChain 搭 RAG",现在写的是"调优、召回率、重排"——企业要的不是能跑 demo 的人,而是能把检索质量提上去的人。这是今天的主线。
二、RAG 是什么:让模型"开卷考试"
大模型有两个先天缺陷:训练数据有截止日期(不知道你们公司上周改的报销规则),没见过你的私有数据(不敢喂给外部 API)。
解决思路有三条,用一个考试类比:
| RAG | 允许带一本资料册,现场翻页 | 随时换 | |
RAG(Retrieval-Augmented Generation,检索增强生成)就是开卷考试:提问时先去你的资料库里检索相关内容,把检索结果和问题一起塞给模型,让它"照着资料答题"。承接前四天:用第 2 天的切分处理文档、第 3 天的 Embedding 算相似度、第 4 天的 Prompt 约束"只准依据资料作答"——RAG 是前四站知识的第一次总装。
三、五步流水线
前两步是离线的(建库,做一次),后两步是在线的(每次提问都走)。类比图书馆:①②③ 是"把书编目上架",④ 是"按索引找书",⑤ 是"管理员照着书回答你"。
四、本机实测:一个 mini RAG
我搭了个"星辰科技行政制度问答":15 条制度原文(差旅、报销、年假、调休等)作为知识库,8 个问题标注了正确出处,全部跑在 CPU 上。第一步先只测检索:
两个反直觉但真实的结论:
五、端到端实测:一个惊喜和一个惊吓
接入 Qwen2.5-1.5B 生成答案(temperature=0),三组对照:
场景 1(库内问题)——RAG 大获全胜
问题:出差去上海住酒店,一晚上最多能报销多少钱?无 RAG:"您需要考虑住宿类型、酒店星级、地理位置……"(一段废话,不给数字)有 RAG:"根据第[2]条:一线城市每晚不超过500元……上海属于一线城市,最多报销 500 元。"(精准引用,还会推理)
场景 2(库外问题)——拒答指令生效
问题:公司股票在哪个交易所上市?无 RAG:一段委婉的推脱"建议您查阅公司官网或咨询投资顾问……"有 RAG:"资料中未找到相关规定。"(因为 System Prompt 里写了"资料中没有就只回答这句话")
场景 3(模拟检索失败)——RAG 最危险的时刻
我故意喂给模型一组与问题无关的检索结果(团建经费、会议室预订),再问"报销单最晚什么时候交":
有 RAG:"根据第[15]条团建经费规定……报销单最晚需要在活动结束后的一周内提交。"——一本正经地胡说八道,且引用了真实条目编号,看起来比无 RAG 时更可信!
这就是 RAG 最重要的失败模式:检索错了,模型会强行把无关资料硬凑成答案,幻觉反而更自信。对策:检索结果加相似度阈值过滤(低于阈值宁可拒答)、Prompt 中允许说"资料与问题无关"、上线后持续评测 badcase。
六、动手:30 行跑通完整链路
环境:pip install sentence-transformers(模型国内从魔搭下载;SSL 报错时设 export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt)。
import torchfrom sentence_transformers import SentenceTransformerfrom transformers import AutoModelForCausalLM, AutoTokenizerE = "/root/.cache/modelscope/models/BAAI--bge-small-zh-v1.5/snapshots/master"Q = "/root/.cache/modelscope/models/Qwen--Qwen2.5-1.5B-Instruct/snapshots/master"PFX = "为这个句子生成表示以用于检索相关文章:"# bge 官方要求的查询前缀docs = ["住宿报销标准:一线城市每晚不超过500元,其他城市不超过400元;超出部分自理。","所有费用发票须在消费后30天内提交报销系统,逾期不予报销。","报销单经直属主管、财务初审、财务总监三级审批,通常3个工作日到账。"]emb = SentenceTransformer(E) # ①②③ 建库dvec = torch.from_numpy(emb.encode(docs, normalize_embeddings=True))tok = AutoTokenizer.from_pretrained(Q)llm = AutoModelForCausalLM.from_pretrained(Q, dtype=torch.float32).eval()defrag(question, k=3): qvec = torch.from_numpy(emb.encode([PFX + question], normalize_embeddings=True)) top = (qvec @ dvec.T).argsort(descending=True)[0][:k].tolist() # ④ 检索 ctx = "\n".join(f"[{i+1}] {docs[i]}"for i in top) sys = ("你是公司行政助理。仅依据《制度资料》回答并引用条目编号,""资料中没有相关内容就只回答'资料中未找到相关规定'。") # ⑤ 生成 msgs = [{"role": "system", "content": sys}, {"role": "user", "content": f"《制度资料》\n{ctx}\n\n问题:{question}"}] ids = tok(tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True), return_tensors="pt") out = llm.generate(**ids, max_new_tokens=120, do_sample=False, pad_token_id=tok.eos_token_id)return tok.decode(out[0][ids["input_ids"].shape[1]:], skip_special_tokens=True)print(rag("出差住宿一晚最多报多少?"))# 实测输出:根据第[1]条:一线城市每晚不超过500元……最多报销500元。一次提问的完整时序:
七、企业级 RAG 的进阶招式(面试拉分项)
真实生产环境在五步流水线上还会叠这些层,对应开头 JD 里的关键词:
一句话:RAG 的天花板不在生成模型,而在检索质量。 生成模型只负责"照着念",念得好不好取决于递到它手里的资料。
八、面试三连问
Q1:RAG 和微调怎么选?RAG 解决"不知道"(知识时效、私有数据),微调解决"不会说"(固定风格、输出格式、领域术语)。默认先 RAG:成本低、知识可随时更新、答案可溯源。需要上千条标注数据且追求极致降本时再上微调,两者常组合使用。
Q2:RAG 系统答不准,怎么排查?先定位坏在哪一环:检索返回的 Top-K 里有没有正确内容(没有→检索问题:切分、Embedding 模型、Query 改写);有但模型没用上→生成问题:上下文太长被稀释、关键信息放结尾、Prompt 约束不够。九成问题出在检索。
Q3:为什么加了 RAG 还是幻觉?三种情况:检索没召回正确内容但模型硬答;召回了相似但过时的版本;Prompt 没给"拒答退路"。对策:相似度阈值、知识库版本管理、允许说"资料中未找到"。
九、总结
今天记住五句话:
一句话记住 RAG:"答案的上限,在你递给模型的那几页资料里。"
明日预告:Function Calling——RAG 让模型"读得到",但模型还不能"动得了手":查库存、下单、发邮件这些真实操作,得让模型学会调用你的 API。明天拆解 Function Calling 的协议设计,并让 Qwen 真实调用一个天气接口。
本文考点参考自 BOSS 直聘等平台 AI 应用开发 / AI 算法 / 大模型开发 / AI Infra 岗位近期公开要求。















































































