1. RAG技术:大模型时代的记忆外挂
第一次接触RAG技术是在去年开发一个医疗问答系统时。当时我们使用的大模型在回答专业医学问题时,要么给出过于笼统的建议,要么直接编造不存在的论文引用——直到引入RAG技术,系统才开始准确引用最新临床指南。这种"开挂"般的提升让我意识到,掌握RAG正在成为AI工程师的必备技能。
检索增强生成(Retrieval-Augmented Generation)本质上是大模型的"外部记忆系统"。就像医生诊断前会查阅医学文献,RAG让大模型在生成回答前,先从一个可更新的知识库中检索相关信息。这种架构解决了大模型三大痛点:
- 知识过时:传统大模型训练后知识就冻结了
- 幻觉问题:容易编造看似合理实则错误的内容
- 专业度不足:对垂直领域理解不够深入
举个例子,当用户询问"2023版NCCN胃癌指南主要更新点"时:
- RAG系统会先从构建的医学知识库中检索相关文档
- 将检索到的指南原文片段作为上下文输入大模型
- 模型基于这些权威资料生成准确回答
这种工作模式使系统既能保持大模型强大的语言理解能力,又能确保回答的专业性和时效性。下面我们就深入拆解这项技术的演进历程和实战应用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. RAG技术五大演进阶段详解
2.1 朴素RAG:关键词检索的奠基时代
2017年我在开发第一个问答系统时,用的就是TF-IDF加BM25这套"古典"方法。虽然现在看很原始,但理解这些基础算法对掌握RAG精髓至关重要。
核心原理:
-
TF-IDF(词频-逆文档频率):
- 词频(TF) = 词在文档出现次数 / 文档总词数
- 逆文档频率(IDF) = log(总文档数 / 包含该词的文档数)
- 最终权重 = TF × IDF
-
BM25优化:
- 引入文档长度归一化
- 加入可调参数k和b
- 公式:Σ IDF(qi) × (f(qi,D) × (k+1)) / (f(qi,D) + k × (1-b + b × |D|/avgdl))
典型实现(Python示例):
python复制from rank_bm25 import BM25Okapi
corpus = ["肝癌的常见治疗方法包括...", "胃癌NCCN指南建议..."]
tokenized_corpus = [doc.split() for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
query = "胃癌治疗指南"
tokenized_query = query.split()
doc_scores = bm25.get_scores(tokenized_query)
实战痛点:
- 同义词问题:"肿瘤"和"癌症"可能被当作完全不同的词
- 语义鸿沟:搜索"儿童发热处理"可能错过包含"小儿高热管理"的文档
- 长尾效应:专业术语权重可能被常见词稀释
关键经验:在医疗/法律等专业领域,建议先构建领域同义词库,对查询进行扩展后再检索
2.2 高级RAG:语义理解的突破
2020年接触到的DPR(Dense Passage Retrieval)彻底改变了我的检索系统设计思路。与关键词检索不同,它通过神经网络将文本映射到稠密向量空间。
技术栈演进:
-
编码器选择:
- 早期:BERT-base
- 现在:ANCE、ColBERT等专用检索模型
-
- FAISS(Facebook开源的相似性搜索库)
- Milvus(支持分布式部署)
- Pinecone(全托管服务)
性能对比(MS MARCO数据集):
| 指标 | BM25 | DPR | ColBERT |
|---|---|---|---|
| MRR@10 | 0.184 | 0.312 | 0.368 |
| 召回率 | 0.592 | 0.782 | 0.814 |
| 延迟(ms) | 45 | 120 | 180 |
实现示例:
python复制from sentence_transformers import SentenceTransformer
import faiss
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
corpus_embeddings = model.encode(corpus)
dimension = corpus_embeddings.shape[1]
index = faiss.IndexFlatIP(dimension)
index.add(corpus_embeddings)
query_embedding = model.encode(["胃癌治疗指南"])
D, I = index.search(query_embedding, k=3)
调优技巧:
- 混合检索:结合BM25和向量检索结果(如各取top10再rerank)
- 负采样:在训练时加入困难负样本提升
