前言
大语言模型(LLM)虽然强大,但它们的知识截止于训练数据,无法获取你企业的内部文档、产品手册、业务流程等私有信息。RAG(Retrieval-Augmented Generation,检索增强生成)就是解决这个问题的最佳方案。
一、RAG是什么?
RAG的核心思路很简单:在AI回答问题之前,先从你的知识库中检索相关内容,然后把这些内容作为上下文传给LLM,让AI基于这些真实数据来回答。
RAG工作流程:
- 文档处理:将PDF/Word/网页等文档切分成小块
- 向量化:用Embedding模型将文本块转为向量
- 存储:将向量存入向量数据库
- 检索:用户提问时,检索最相关的文档块
- 生成:将检索结果+问题传给LLM,生成回答
二、向量数据库选型
| 数据库 | 特点 | 适用场景 | 部署方式 |
|---|---|---|---|
| Chroma | 轻量、易用、Python原生 | 原型开发、小型项目 | 嵌入式/服务器 |
| Pinecone | 全托管、高性能 | 生产环境、大规模 | 云服务 |
| Milvus | 开源、分布式、可扩展 | 企业级、大规模 | 自部署 |
| Weaviate | 开源、支持混合搜索 | 语义搜索、多模态 | 自部署/云 |
| Qdrant | 开源、Rust编写、高性能 | 高性能场景 | 自部署/云 |
| pgvector | PostgreSQL扩展 | 已有PG的项目 | 嵌入PG |
三、实战:用LangChain构建RAG系统
3.1 安装依赖
pip install langchain langchain-openai langchain-community chromadb pypdf
3.2 文档加载与切分
from langchain_community.document_loaders import PyPDFLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载PDF文档
loader = PyPDFLoader("产品手册.pdf")
documents = loader.load()
# 文档切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块500字符
chunk_overlap=50, # 块之间重叠50字符
length_function=len,
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " "]
)
chunks = text_splitter.split_documents(documents)
print(f"文档被切分成 {len(chunks)} 个块")
3.3 向量化并存储
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 初始化Embedding模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# 存入Chroma
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db",
collection_name="product_docs"
)
print(f"成功存储 {len(chunks)} 个文档块")
3.4 检索与生成
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
# 检索器
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 4} # 返回最相关的4个文档块
)
# LLM
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.3)
# Prompt模板
prompt = PromptTemplate(
template="""基于以下上下文回答用户的问题。如果上下文中没有相关信息,请说"抱歉,知识库中没有找到相关信息"。
上下文:
{context}
问题:{question}
回答:""",
input_variables=["context", "question"]
)
# 构建QA链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": prompt},
return_source_documents=True
)
# 提问
result = qa_chain.invoke({"query": "产品有哪些核心功能?"})
print(result["result"])
print("\n参考来源:")
for doc in result["source_documents"]:
print(f"- {doc.metadata.get('source', '未知')}: {doc.page_content[:100]}...")
四、优化技巧
4.1 混合搜索
结合向量搜索和关键词搜索,提高检索准确率:
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# BM25关键词检索器
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 4
# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# 混合检索
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.3, 0.7] # 关键词30%,向量70%
)
4.2 重排序(Reranking)
对检索结果进行二次排序,提高相关性:
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
# 使用Cohere重排序
reranker = CohereRerank(model="rerank-v3.5", top_n=3)
compression_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=vector_retriever
)
4.3 查询改写
用LLM改写用户问题,提高检索效果:
REWRITE_PROMPT = """请将以下用户问题改写为更适合搜索的形式,保持原意但更具体:
原始问题:{question}
改写后的搜索查询:"""
def rewrite_query(question: str) -> str:
response = llm.invoke(REWRITE_PROMPT.format(question=question))
return response.content
五、生产环境部署
生产环境建议:
- 使用Milvus或Pinecone替代Chroma,支持更高并发
- 实现增量更新,新文档自动入库
- 添加缓存层,相同问题直接返回缓存
- 监控检索质量和用户满意度
- 实现权限控制,不同用户看到不同知识库
总结
RAG是当前最实用的AI应用技术之一,让LLM真正拥有你的企业知识。通过本文的实战教程,你可以快速搭建自己的RAG系统。如果需要企业级RAG解决方案,欢迎联系17老师。
关于17老师:AI应用·数字化管理·全栈开发·网络安全全栈专家。联系邮箱:j.d88888888@qq.com,微信:AFIST17