RAG 入门到精通:构建你的第一个智能问答系统
RAG(Retrieval-Augmented Generation)是当下最实用的 LLM 应用范式。它让 LLM 能够基于你的私有知识回答问题,无需重新训练模型。
一、为什么需要 RAG?
LLM 有三大局限:
- 知识陈旧:训练数据有截止日期
- 不懂私域:不知道你的企业文档、产品手册
- 会胡说:对不知道的内容会编造
\\\`
用户问题 → 检索相关文档 → 拼接 prompt → LLM → 答案
\\\`
二、核心架构
\\\`python
最简化的 RAG 流程
def rag(query, documents): # 1. 检索:找最相关的 k 个文档 relevantdocs = retrieve(query, documents, k=3) # 2. 构造 prompt context = "\n\n".join(relevantdocs) prompt = f"""基于以下资料回答用户问题。如果资料中没有,请说"我不知道"。资料: {context}
问题:{query}
"""
# 3. 调用 LLM
return llm(prompt)
\\\`
看起来简单,但每个环节都有坑。
三、检索的关键技术
3.1 Embedding 模型
把文本变成向量(一串数字),用向量相似度找相关文档。常用模型:
text-embedding-3-small(OpenAI, 1536 维, $0.02/百万 token)bge-large-zh-v1.5(BAAI, 中文优秀, 开源)text-embedding-v3(Cohere, 多语言)
\\`python
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
model="text-embedding-3-small",
input="Python 怎么读取文件?"
)
vector = response.data[0].embedding # 1536 维向量
\\\`
3.2 向量数据库
存向量、做相似度搜索。| 数据库 | 特点 | |---|---| | Chroma | 轻量、嵌入式、易上手 | | Milvus | 国产、生产级、性能强 | | Qdrant | Rust 写、性能好 | | pgvector | PostgreSQL 插件,运维简单 | | Pinecone | SaaS,托管方便 |
\\\`python
import chromadb
client = chromadb.PersistentClient(path="./chromadb")
collection = client.getorcreatecollection("docs")
存文档
collection.add( documents=["Python 用 open() 读文件...", "Java 用 FileReader..."], ids=["doc1", "doc2"] )检索
results = collection.query( querytexts=["怎么读文件"], nresults=2 ) \\\`
四、Chunking:最容易被忽略的关键
文档不可能整篇塞给 LLM(超出 token 限制),必须切片。
4.1 切片策略
| 策略 | 适用 | 缺点 | |---|---|---| | 固定长度 | 快速实验 | 切断语义 | | 按段落 | 一般文档 | 长段落仍超限 | | 按语义 | 高质量场景 | 慢 | | 按 Markdown 标题 | 结构化文档 | 不适用非 MD | | 滑动窗口 | 长文档 | 信息重复 |
4.2 推荐实践
\\\`python
from langchain.textsplitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter( chunk
size=500, # 每片字符数 chunkoverlap=50, # 重叠字符(避免切断) separators=["\n\n", "\n", "。", "!", "?", " ", ""] ) chunks = splitter.splittext(longdocument) \\\`
五、Prompt 工程
检索出来的内容不会自动成为好答案,需要 prompt 包装。
5.1 经典 RAG prompt 模板
\\\`
你是 {role},专注于回答关于 {domain} 的问题。
规则:
- 只使用参考资料中的信息回答
- 如果参考资料中找不到答案,明确说"我不知道"
- 回答简洁,引用参考资料编号
- 不要编造信息
用户问题:{query}
\\\`
5.2 进阶:HyDE
让 LLM 先生成假设性答案,再拿假设答案去检索,比直接用原始问题检索效果好。六、生产环境最佳实践
6.1 检索质量评估
\\\`python
用 GPT-4 评估检索质量
def evalretrieval(query, retrieveddocs, groundtruth): prompt = f"""判断以下文档是否与问题相关: 问题:{query} 文档:{retrieveddocs} 相关:是 / 否""" return llm(prompt) \\\`
6.2 缓存
相同问题直接返回缓存答案,节省 80% 调用成本。6.3 监控
记录每次调用:- 检索耗时 / LLM 耗时
- 检索命中率
- 用户反馈(点赞 / 点踩)
七、完整代码示例
用 LangChain 30 行代码搭建一个 RAG:
\\\`python
from langchain.document
1. 加载文档
loader = DirectoryLoader("./docs", glob="/.md") docs = loader.load()2. 切片
splitter = RecursiveCharacterTextSplitter(chunksize=500, chunkoverlap=50) chunks = splitter.splitdocuments(docs)3. 存向量
vectordb = Chroma.fromdocuments(chunks, OpenAIEmbeddings(), persistdirectory="./chroma")4. 问答
qa = RetrievalQA.fromchaintype( llm=ChatOpenAI(model="gpt-4o"), retriever=vectordb.asretriever(k=3) ) print(qa.run("什么是 RAG?")) \\\`
八、进阶方向
RAG 是当下 LLM 应用最成熟的范式,值得投入时间深入学习*。
📌 相关推荐