RAG 知识库搭建实战完全指南:从零构建智能问答系统
RAG(Retrieval-Augmented Generation,检索增强生成)是当前AI应用开发的核心技术,它通过将检索系统与生成模型结合,让大语言模型能够利用外部知识库进行精准回答,有效解决了模型知识截止、幻觉问题等痛点。
一、RAG 核心概念
RAG 是一种将信息检索与文本生成相结合的技术架构。传统的LLM(大语言模型)存在以下局限:
1. 知识截止问题:模型训练数据有时间限制,无法回答最新问题
2. 幻觉问题:面对不确定的问题,模型可能编造错误信息
3. 领域知识缺失:通用模型缺乏特定领域的专业知识
RAG 通过引入外部知识库解决了这些问题。其核心流程是:
用户提问 → 向量检索 → 获取相关文档 → 结合文档生成答案
这种方式让模型能够基于真实、可溯源的知识进行回答,大幅提升了准确性和可信度。
二、RAG 技术架构
一个完整的 RAG 系统包含以下核心组件:
1. 文档处理模块
- 文档加载:支持 PDF、Word、Markdown 等多种格式
- 文本切分:将长文档切分为适当大小的片段
- 元数据管理:保留文档来源、页码等信息
2. 向量化模块
- Embedding 模型:将文本转换为向量表示
- 维度选择:通常 768-1536 维
- 多语言支持:处理中英文混合场景
3. 向量数据库
- 存储向量:高效存储和索引文档向量
- 相似度检索:快速找到最相关的文档片段
- 持久化:数据持久保存,支持增量更新
4. 生成模块
- Prompt 构建:将检索结果与用户问题组合
- LLM 调用:使用大模型生成最终答案
- 答案优化:添加引用来源、格式化输出
三、向量数据库选型
向量数据库是 RAG 系统的核心基础设施。以下是主流选择:
1. Chroma
- 特点:轻量级、易于上手、支持本地运行
- 适用:小型项目、原型验证、个人使用
- 优点:零配置启动、Python 原生支持
2. FAISS (Facebook AI Similarity Search)
- 特点:Meta 开源、高性能、纯内存运行
- 适用:大规模向量检索、对性能要求高的场景
- 优点:支持 GPU 加速、索引类型丰富
3. Milvus
- 特点:企业级、分布式、高可用
- 适用:生产环境、大规模部署
- 优点:支持水平扩展、完善的监控体系
4. Pinecone
- 特点:全托管服务、免运维
- 适用:快速上线、无运维需求
- 优点:开箱即用、自动扩展
本文以 Chroma 为例进行实战演示,因为它上手最简单,适合学习和中小型项目。
四、文档切分策略
文档切分直接影响检索效果。常见的切分策略:
1. 固定长度切分
按字符数或 token 数切分,简单但可能切断语义。
from langchain.text_splitter import CharacterTextSplitter
# 创建文本切分器
text_splitter = CharacterTextSplitter(
chunk_size=500, # 每个片段500字符
chunk_overlap=50, # 片段间重叠50字符
separator="\n\n" # 按段落切分
)
# 执行切分
chunks = text_splitter.split_text(long_text)
print(f"切分后得到 {len(chunks)} 个片段")
2. 递归字符切分
按层级结构(段落 → 句子 → 词)递归切分,保持语义完整性。
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 递归切分器,优先按段落、句子、词切分
recursive_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
chunks = recursive_splitter.split_text(document)
for i, chunk in enumerate(chunks[:3]):
print(f"片段 {i+1}: {chunk[:100]}...")
3. 语义切分
使用嵌入模型计算句子相似度,在语义变化处切分。
from langchain_experimental.text_splitters import SemanticChunker
from langchain.embeddings import HuggingFaceEmbeddings
# 使用语义切分器
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
semantic_splitter = SemanticChunker(
embeddings,
breakpoint_threshold_type="percentile"
)
chunks = semantic_splitter.split_text(document)
最佳实践建议:
- chunk_size:500-1000 字符(中文),200-500 tokens(英文)
- chunk_overlap:chunk_size 的 10%-20%
- 保留文档结构信息作为元数据
五、嵌入模型选择
嵌入模型负责将文本转换为向量,选择要点:
1. OpenAI Embeddings
from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
openai_api_key="your-api-key"
)
text = "这是一段测试文本"
vector = embeddings.embed_query(text)
print(f"向量维度: {len(vector)}")
2. 本地嵌入模型(推荐)
使用 HuggingFace 的开源模型,无需 API 费用:
from langchain.embeddings import HuggingFaceEmbeddings
# 使用中文友好的嵌入模型
model_name = "BAAI/bge-large-zh-v1.5"
model_kwargs = {"device": "cpu"}
encode_kwargs = {"normalize_embeddings": True}
embeddings = HuggingFaceEmbeddings(
model_name=model_name,
model_kwargs=model_kwargs,
encode_kwargs=encode_kwargs
)
texts = ["第一段文本", "第二段文本", "第三段文本"]
vectors = embeddings.embed_documents(texts)
print(f"生成了 {len(vectors)} 个向量")
中文推荐模型:
- BAAI/bge-large-zh-v1.5:性能最强,1024 维
- BAAI/bge-small-zh-v1.5:轻量级,512 维
- sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2:多语言支持
六、实战:构建完整 RAG 系统
下面我们使用 Python 实现一个完整的本地 RAG 智能问答系统。
步骤1:安装依赖
# pip install langchain langchain-community chromadb sentence-transformers # pip install unstructured markdown PyPDF2
步骤2:初始化向量数据库
import os
from langchain_community.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import TextLoader, PyPDFLoader
class RAGKnowledgeBase:
"""RAG 知识库管理类"""
def __init__(self, persist_directory="./chroma_db"):
self.persist_directory = persist_directory
self.embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-large-zh-v1.5",
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True}
)
self.text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
self.vectorstore = None
def add_documents(self, file_paths):
documents = []
for file_path in file_paths:
if file_path.endswith(".pdf"):
loader = PyPDFLoader(file_path)
else:
loader = TextLoader(file_path, encoding="utf-8")
docs = loader.load()
documents.extend(docs)
chunks = self.text_splitter.split_documents(documents)
print(f"文档切分完成,共 {len(chunks)} 个片段")
if self.vectorstore is None:
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings,
persist_directory=self.persist_directory
)
else:
self.vectorstore.add_documents(chunks)
print(f"已添加 {len(file_paths)} 个文档到知识库")
def search(self, query, k=5):
if self.vectorstore is None:
raise ValueError("知识库未初始化")
return self.vectorstore.similarity_search(query, k=k)
步骤3:实现问答功能
from langchain.chains import RetrievalQA
from langchain_community.llms import Ollama
from langchain.prompts import PromptTemplate
class RAGQueryEngine:
"""RAG 问答引擎"""
def __init__(self, knowledge_base, llm_model="qwen2.5:7b"):
self.knowledge_base = knowledge_base
self.prompt_template = PromptTemplate(
template="""你是一个专业的知识库问答助手。请根据参考信息回答问题。
参考信息:
{context}
用户问题:{question}
要求:只基于参考信息回答,不要编造内容。回答:""",
input_variables=["context", "question"]
)
try:
self.llm = Ollama(model=llm_model)
except Exception as e:
print(f"Ollama 初始化失败: {e}")
self.llm = None
if self.llm:
self.qa_chain = RetrievalQA.from_chain_type(
llm=self.llm,
chain_type="stuff",
retriever=knowledge_base.vectorstore.as_retriever(
search_kwargs={"k": 4}
),
return_source_documents=True
)
def query(self, question):
if not self.llm:
return {"answer": "LLM 未初始化", "sources": []}
result = self.qa_chain.invoke({"query": question})
return {
"answer": result["result"],
"sources": [{"content": doc.page_content[:200]}
for doc in result["source_documents"]]
}
七、性能优化技巧
1. 混合检索优化
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# BM25 关键词检索器
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 5
# 混合检索器
ensemble_retriever = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever],
weights=[0.5, 0.5]
)
2. 重排序优化
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-large")
def rerank_results(query, documents, top_k=5):
pairs = [(query, doc.page_content) for doc in documents]
scores = reranker.predict(pairs)
scored_docs = list(zip(scores, documents))
scored_docs.sort(key=lambda x: x[0], reverse=True)
return [doc for _, doc in scored_docs[:top_k]]
八、部署建议
生产环境架构:
- 前端:FastAPI + Swagger 文档
- 向量库:Milvus 或 Qdrant(集群部署)
- LLM:vLLM 部署开源模型
- 缓存:Redis 缓存热门查询
监控指标:
- 检索延迟:P50/P95/P99
- 检索准确率:人工评估或 A/B 测试
- 用户满意度:点赞率、反馈统计
总结
RAG 技术是当前 AI 应用落地的关键基础设施。通过本文学习,你应该掌握:
1. 核心概念:理解 RAG 如何解决 LLM 的局限性
2. 技术架构:了解文档处理、向量化、检索、生成各模块
3. 实战能力:能够使用 Python 构建本地 RAG 系统
4. 优化技巧:掌握混合检索、重排序、缓存等优化方法
建议从简单的 Chroma + 本地 LLM 开始,逐步迭代到生产级架构。RAG 的价值在于让 AI 能够基于真实知识回答问题,是企业 AI 落地的重要方向。
本文链接:https://www.kkkliao.cn/?id=918 转载需授权!
版权声明:本文由廖万里的博客发布,如需转载请注明出处。



手机流量卡
免费领卡
号卡合伙人
产品服务
关于本站
