RAG 实战:让 LLM 准确引用你的文档
【摘要】 检索增强生成(RAG)是解决 LLM 幻觉问题的关键技术。本文深入实践向量检索与上下文注入。
为什么需要 RAG?
大语言模型虽然强大,但存在明显的局限性:
- 知识截止:训练数据有时间边界
- 幻觉问题:会编造看似合理但错误的内容
- 私有数据:无法访问企业内部文档
RAG(Retrieval-Augmented Generation)通过在生成前检索相关文档来解决这些问题。
RAG 基本流程
用户提问 → 向量检索 → 获取相关文档 → 注入上下文 → LLM 生成回答
1. 文档处理
将文档切分为适当的 chunks:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
chunks = splitter.split_documents(documents)
2. 向量化与存储
使用 Embedding 模型将文本转为向量:
from openai import OpenAI
client = OpenAI()
def embed(text):
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
3. 检索
根据用户问题检索最相关的文档片段:
def retrieve(query, top_k=5):
query_vec = embed(query)
# 使用向量数据库(如 Pinecone、ChromaDB)进行相似度搜索
results = vector_db.similarity_search(query_vec, k=top_k)
return results
4. 生成
将检索到的文档注入 prompt:
def rag_answer(question):
docs = retrieve(question)
context = "\n\n".join([doc.text for doc in docs])
prompt = f"""根据以下参考资料回答问题。如果资料中没有相关信息,请说明。
参考资料:
{context}
问题:{question}"""
response = client.chat.completions.create(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
优化技巧
- Chunk 大小:太小丢失上下文,太大引入噪音。通常 300-800 tokens 效果较好
- 重排序:先粗检索 top-20,再用 reranker 精排取 top-5
- 混合检索:结合向量检索和关键词检索(BM25)
- 查询改写:用 LLM 改写用户问题以提高检索质量
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)