Skip to content

RAG(检索增强) ​

RAG可以用来补充外部知识与上下文


补充整理:下面是课后补充的完整说明与可运行示例,用于复习时对照。

为什么需要 RAG ​

大模型有三个绕不开的短板,RAG 正是用来补这些洞的:

短板表现RAG 的解法
知识有截止日期不知道训练之后发生的事外部知识库随时更新,检索即得
容易幻觉confidently 编造不存在的细节回答基于检索到的原文,可溯源
不懂私有数据没见过公司内部文档、业务库把私有语料切分入库再检索

一句话概括:RAG 不改动模型参数,而是在提问时把相关资料一起塞进上下文,让模型「照着材料答题」。

整体流程 ​

text
离线(建库)                        在线(问答)
文档 → 切分 chunk → 向量化 → 向量库      问题 → 向量化 → 召回 Top-K
                                              ↓
                                       (可选)Rerank 重排
                                              ↓
                                  拼进 Prompt → LLM → 答案 + 引用来源

1. 切分(Chunking) ​

  • 切太大:召回的内容塞不进上下文,噪声多。
  • 切太小:语义被截断,检索时丢失关键句。
  • 常用策略:按固定长度切 + 相邻块之间保留 overlap(重叠部分)避免切断句子。

2. 向量化(Embedding) ​

把文本映射成高维向量,语义相近的文本在空间里距离更近。检索阶段把问题也向量化,用余弦相似度找最相近的片段。

3. 召回与重排 ​

  • 召回:向量库返回 Top-K 个候选片段,追求「别漏掉」。
  • 重排(Rerank):用更精细的交叉编码模型对候选重新打分,追求「排得准」。
  • 两者配合是工业界标配:粗排要快、精排要准。

最小可运行示例(LangChain) ​

python
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# 1. 建库:切分 → 向量化
raw_text = "公司规定:每年可申请 10 天带薪年假,需提前 3 个工作日在 OA 提交。"
splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=30)
docs = splitter.create_documents([raw_text])

vectorstore = FAISS.from_documents(docs, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 2. 问答:检索到的内容拼进 prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "只依据下列资料回答问题,资料中没有的就说不知道。\n\n资料:\n{context}"),
    ("human", "{question}")
])

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

print(chain.invoke("年假要提前几天申请?"))

关键点:

  • retriever 在链里当「数据源」用,自动把召回结果格式化成 context。
  • system prompt 里加「没有就说不知道」能显著压住幻觉。
  • 本地部署可把 ChatOpenAI 换成 vLLM 的 OpenAI 兼容接口,只改 base_url。

常见坑 ​

  • 检索质量差:先别急着换模型,八成是切分和 embedding 的问题。
  • 上下文溢出:Top-K 给太大,塞爆窗口,反而不如少而精。
  • 没有溯源:生产环境一定要把命中的原文片段一起返回,方便人工核验。