5.4 RAG检索增强生成原理与企业知识库问答系统搭建
一、RAG解决的核心问题
大语言模型存在知识截止与幻觉问题:无法获知训练后的新信息,且可能编造不存在的内容。RAG(Retrieval-Augmented Generation,检索增强生成) 通过"先检索、再生成"的方式,将外部知识库的检索结果作为上下文注入模型,从而提升答案的准确性与时效性。《大模型应用开发极简入门》第5章「构建RAG系统」明确为:RAG原理(检索增强生成、解决幻觉与知识准确性)、LlamaIndex实战(文档加载、分块、嵌入、索引、检索、生成)、企业知识库问答与文档智能检索。本节与之一一对应,并给出可运行代码与部署要点。
二、RAG工作流程
flowchart LR
A[用户问题] --> B[查询向量化]
C[知识库] --> D[向量索引]
B --> E[相似度检索]
D --> E
E --> F[Top-K 文档片段]
F --> G[拼接为上下文]
G --> H[LLM 生成]
A --> H
H --> I[最终回答]
2.1 核心步骤
- 文档处理:加载、分块、向量化
- 索引构建:将向量存入向量数据库
- 检索:用户问题向量化,检索最相似的K个片段
- 生成:将检索结果与问题拼接,送入LLM生成答案
三、企业知识库问答系统搭建
3.1 技术选型
| 组件 | 推荐方案 |
|---|---|
| 文档加载 | LlamaIndex SimpleDirectoryReader |
| 向量化 | OpenAI text-embedding-ada-002 |
| 向量存储 | 内存 / Chroma / Pinecone |
| LLM | GPT-3.5-turbo 或 GPT-4 |
3.2 完整代码(基于LlamaIndex)
"""
企业知识库RAG问答系统
前置: pip install llama-index llama-index-llms-openai llama-index-embeddings-openai python-dotenv pypdf
"""
import os
from dotenv import load_dotenv
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, Settings
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
load_dotenv()
# 配置
Settings.llm = OpenAI(model="gpt-3.5-turbo", temperature=0.1, api_key=os.getenv("OPENAI_API_KEY"))
Settings.embed_model = OpenAIEmbedding(model="text-embedding-ada-002", api_key=os.getenv("OPENAI_API_KEY"))
def build_index(doc_dir: str = "./docs") -> VectorStoreIndex:
"""构建文档向量索引"""
documents = SimpleDirectoryReader(doc_dir).load_data()
index = VectorStoreIndex.from_documents(documents)
return index
def query(index: VectorStoreIndex, question: str) -> str:
"""检索+生成"""
query_engine = index.as_query_engine()
response = query_engine.query(question)
return str(response)
if __name__ == "__main__":
# 首次运行:在 docs/ 下放入 PDF/TXT 等文档
index = build_index()
# 或加载已保存索引: index = load_index_from_storage(...)
answer = query(index, "文档中提到的核心流程有哪些?")
print(answer)
四、优化要点
- 分块策略:按段落或固定长度分块,避免过长或过短
- 检索数量:Top-K 通常取 3–5,过多会增加噪声与成本
- 提示设计:明确"仅基于以下内容回答",避免模型自由发挥
五、分块策略详解
5.1 为什么需要分块
原始文档可能很长,直接向量化会丢失细节,且超出模型上下文。分块将文档切分为小片段,每个片段单独向量化,检索时返回最相关的若干块。
5.2 分块参数
| 参数 | 说明 | 推荐值 |
|---|---|---|
| chunk_size | 每块字符/Token数 | 256-512(中文约150-300字) |
| chunk_overlap | 块间重叠 | 50-100,避免语义被切断 |
| 分隔符 | 按段落/句号/固定长度 | 按段落优先,保持语义完整 |
5.3 LlamaIndex分块配置
from llama_index.core import SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
parser = SentenceSplitter(chunk_size=256, chunk_overlap=50)
documents = SimpleDirectoryReader("./docs").load_data()
nodes = parser.get_nodes_from_documents(documents)
# 然后用nodes构建索引
六、检索优化
6.1 Top-K选择
Top-K过小可能遗漏关键信息,过大则引入噪声、增加Token成本。通常3-5为宜,可根据业务测试调整。
6.2 混合检索
除向量检索外,可结合关键词检索(BM25):对短query,关键词匹配有时更准。混合策略可为:向量检索Top-5 + BM25 Top-3,去重后合并。
6.3 重排序(Rerank)
检索得到Top-K后,可用专门的Rerank模型对候选片段重新排序,提升最相关片段排在前面的概率。可选模型:Cohere Rerank、BGE Reranker等。
七、提示设计要点
RAG的提示需明确告知模型"仅基于以下内容回答",避免模型依赖自身知识编造。示例:
根据以下参考内容回答用户问题。若参考内容中无相关信息,请回复"根据提供的资料无法回答"。
参考内容:
{context}
用户问题:{question}
八、索引持久化与增量更新
首次构建索引后可持久化,避免每次启动重新计算:
# 保存索引
index.storage_context.persist(persist_dir="./rag_index")
# 加载索引
from llama_index.core import StorageContext, load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir="./rag_index")
index = load_index_from_storage(storage_context)
增量更新:新增文档时,可只对新文档分块、向量化,插入现有索引,无需重建全量。
九、常见问题与排查
| 问题 | 可能原因 | 解决 |
|---|---|---|
| 检索不到相关内容 | 分块过细/过粗、query与文档表述差异大 | 调整chunk_size、做query扩展 |
| 回答与文档不符 | 模型未严格遵循"仅基于上下文" | 强化提示、降低temperature |
| 响应慢 | 检索+生成串行、文档量大 | 异步检索、考虑缓存、缩小检索范围 |
| 成本高 | 检索片段过多、模型选型 | 减少Top-K、用gpt-3.5-turbo |
十一、与书中 5.3 节「构建 RAG 系统」的对应
本书第 5 章 5.3 节明确:RAG 原理为检索增强生成,解决幻觉、提升知识准确性;LlamaIndex 实战覆盖文档加载、分块、嵌入、索引、检索、生成;并给出企业知识库问答、文档智能检索的搭建思路。本节与之一一对应:RAG 原理与流程对应「检索增强生成」;文档加载、分块、向量化、检索、提示设计对应 LlamaIndex 与 LangChain 的完整流程;企业知识库问答即书中「企业知识库问答、文档智能检索」的落地。下一节 5.5 将细化 LlamaIndex 的文档与分块配置,本节侧重整体架构与检索优化。实际搭建企业知识库时,建议先在小规模文档上跑通「加载→分块→索引→检索→生成」全流程并验证回答质量,再扩大文档规模与 Top-K 等参数;同时将「仅基于以下内容回答」等防御性提示(见第 4.5 节)纳入 RAG 的 system 或 user,与书中 RAG 原理与实战要求一致。
十、小结
RAG是解决LLM幻觉与知识时效性的主流方案。掌握文档加载、分块、向量化、检索、提示设计与索引持久化的完整流程,即可搭建企业级知识库问答系统。下一节将深入LlamaIndex的文档加载与分块配置。
十二、与 4.5 防御性提示、2.8 Embeddings 的衔接
4.5 节防御性提示:RAG 的 system 或 user 中应明确「仅基于以下检索内容回答;若检索内容中无法找到答案,请说明无法确定」,与 4.5 的限定知识源、承认不确定性一致,可显著降低 RAG 场景下的幻觉。2.8 节 Embeddings:RAG 的向量化即 Embeddings API 的批量调用;建索引与检索需使用同一 embed 模型(如 text-embedding-ada-002),与 2.8 节模型一致性要求一致。将本节流程与 4.5、2.8 结合,即可形成「检索 → 防御性提示 → 生成」的完整知识库问答管线。与 5.5 节 LlamaIndex 的分工:本节侧重 RAG 原理、企业知识库整体架构与检索优化;5.5 节侧重文档加载、分块、嵌入与索引构建的代码细节,两节配合即可从原理到实现完整落地。实际搭建企业知识库时,建议先在小规模文档上跑通「加载→分块→索引→检索→生成」全流程并验证回答质量,再扩大文档规模与 Top-K 等参数。
下一节预告:5.5 LlamaIndex实战:文档加载、分块、嵌入与索引构建