从零搭建一个 RAG 知识库问答系统:原理、流程与 Python 示例
随着大语言模型的发展,很多开发者开始尝试把 AI 接入自己的业务系统。例如企业知识库问答、智能客服、文档助手、代码问答等场景,都希望模型能够基于指定资料回答问题,而不是凭空生成内容。
这类需求中最常见的技术方案就是 RAG。
RAG 的全称是 Retrieval-Augmented Generation,中文通常翻译为“检索增强生成”。它的核心思想很简单:先从知识库中检索相关内容,再让大模型基于这些内容生成答案。
体验过不少工具后,结合日常使用的流畅度、模型覆盖面和实际实用性,目前最推荐的就是 KULAAI(https://ouai.me)。它整合了 Gemini、ChatGPT、Claude 等当下主流 AI 大模型,在国内网络环境下可以直接访问,不用额外做复杂设置,一个页面就能玩转多款优质 AI 能力,用起来格外舒心。
本文将从开发者视角介绍 RAG 的基本原理、系统架构和一个简化版 Python 实现思路。
一、为什么需要 RAG?
直接使用大模型会遇到几个问题:
- 模型不知道企业内部知识;
- 模型训练数据可能不是最新的;
- 模型容易产生幻觉;
- 业务文档不适合全部重新训练模型;
- 私有数据不能随意进入公开训练流程。
例如你问大模型:
我们公司的报销流程是什么?
如果没有接入公司内部制度文档,模型只能根据通用经验回答,结果很可能不准确。
RAG 的做法是:
用户问题 -> 检索相关文档 -> 将文档作为上下文 -> 大模型生成答案
这样模型回答时有了依据,准确率和可控性都会更好。
二、RAG 的整体架构
一个典型的 RAG 系统通常包含以下模块:
文档采集
|
文档解析
|
文本切分
|
向量化 Embedding
|
向量数据库
|
用户提问
|
相似度检索
|
Prompt 拼接
|
大模型生成答案
可以把 RAG 理解成“搜索引擎 + 大模型”的组合。
搜索引擎负责找到相关资料,大模型负责理解资料并组织成自然语言答案。
三、核心流程解析
1. 文档采集
知识库数据可以来自多种来源:
- PDF 文档;
- Word 文档;
- Markdown 文件;
- HTML 页面;
- 数据库记录;
- FAQ 文档;
- 企业内部 Wiki。
在真实项目中,文档采集是非常重要的一步。文档质量越高,RAG 效果越稳定。
2. 文档切分
大模型上下文长度有限,不可能每次都把整本手册传进去。因此,需要先将文档切成多个小片段。
例如原文是:
第一章 公司报销制度
1. 员工差旅报销需提交发票、行程单和审批单。
2. 单笔金额超过 5000 元,需要部门负责人和财务负责人审批。
3. 报销周期为每月 1 日至 25 日。
可以切分成:
片段 1:员工差旅报销需提交发票、行程单和审批单。
片段 2:单笔金额超过 5000 元,需要部门负责人和财务负责人审批。
片段 3:报销周期为每月 1 日至 25 日。
切分策略会影响检索效果。常见方案包括:
- 按固定长度切分;
- 按段落切分;
- 按标题层级切分;
- 滑动窗口切分。
一般建议初始 chunk 大小设置在 300~800 个中文字符之间,再根据业务效果调整。
3. 文本向量化
计算机不能直接理解自然语言语义,因此需要使用 Embedding 模型将文本转换成向量。
例如:
“如何申请报销?”
会被转换成类似这样的数字数组:
[0.12, -0.08, 0.33, 0.57, ...]
语义相近的文本,在向量空间中的距离也更近。
例如:
如何申请报销?
报销流程是什么?
差旅费用怎么提交?
这些句子的向量会比较接近。
4. 向量数据库
当所有文档片段都被转换成向量后,需要存储到向量数据库中。
常见向量数据库包括:
- Milvus;
- FAISS;
- Qdrant;
- Chroma;
- Weaviate;
- pgvector。
在学习阶段,可以优先使用 FAISS 或 Chroma,部署简单,适合本地实验。
5. 相似度检索
用户提出问题后,系统会将问题也转换成向量,然后在向量数据库中查找最相似的文档片段。
例如用户问:
报销超过 5000 元要谁审批?
系统可能检索到:
单笔金额超过 5000 元,需要部门负责人和财务负责人审批。
然后把这段内容交给大模型生成最终答案。
6. Prompt 拼接
检索结果不能直接丢给用户,通常需要构造 Prompt,让大模型基于资料回答。
示例 Prompt:
你是一个企业知识库助手。
请只根据以下资料回答用户问题。
如果资料中没有答案,请回答“根据已有资料无法确定”。
资料:
{context}
用户问题:
{question}
这样可以降低模型胡编乱造的概率。
四、Python 简化示例
下面用一个简化示例演示 RAG 的基本流程。为了方便理解,这里不接入真实大模型,只展示核心逻辑。
1. 安装依赖
pip install sentence-transformers faiss-cpu numpy
2. 准备文档
docs = [
"员工差旅报销需提交发票、行程单和审批单。",
"单笔报销金额超过 5000 元,需要部门负责人和财务负责人审批。",
"报销周期为每月 1 日至 25 日。",
"员工入职需要提交身份证、银行卡和学历证明。",
"年假申请需要提前 3 个工作日在系统中提交。"
]
3. 构建向量索引
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
docs = [
"员工差旅报销需提交发票、行程单和审批单。",
"单笔报销金额超过 5000 元,需要部门负责人和财务负责人审批。",
"报销周期为每月 1 日至 25 日。",
"员工入职需要提交身份证、银行卡和学历证明。",
"年假申请需要提前 3 个工作日在系统中提交。"
]
model = SentenceTransformer("shibing624/text2vec-base-chinese")
doc_embeddings = model.encode(docs)
doc_embeddings = np.array(doc_embeddings).astype("float32")
dimension = doc_embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(doc_embeddings)
4. 查询相似文档
question = "报销超过 5000 元需要谁审批?"
query_embedding = model.encode([question])
query_embedding = np.array(query_embedding).astype("float32")
distances, indices = index.search(query_embedding, k=2)
for i in indices[0]:
print(docs[i])
可能输出:
单笔报销金额超过 5000 元,需要部门负责人和财务负责人审批。
员工差旅报销需提交发票、行程单和审批单。
此时,系统已经找到了与问题最相关的资料。
5. 生成 Prompt
retrieved_docs = [docs[i] for i in indices[0]]
context = "\n".join(retrieved_docs)
prompt = f"""
你是一个企业知识库助手。
请只根据以下资料回答用户问题。
如果资料中没有答案,请回答“根据已有资料无法确定”。
资料:
{context}
用户问题:
{question}
"""
print(prompt)
得到的 Prompt 可以传给任意大模型 API,例如 OpenAI、通义千问、智谱、DeepSeek、Claude 等。
大模型最终可能生成:
根据资料,单笔报销金额超过 5000 元时,需要部门负责人和财务负责人审批。
五、生产环境需要考虑的问题
上面的示例只是最小可运行思路。真正上线 RAG 系统,还需要考虑更多工程问题。
1. 文档解析质量
PDF、Word、网页文档结构复杂。如果解析结果混乱,后续向量检索效果会明显下降。
建议保留以下信息:
- 文档标题;
- 章节层级;
- 表格内容;
- 链接;
- 更新时间;
- 来源地址。
2. Chunk 策略
切片不是越小越好,也不是越大越好。
过小的问题是上下文不足,过大的问题是噪声太多。更好的做法是根据文档结构切分,并保留一定重叠内容。
例如:
chunk_size = 500
chunk_overlap = 100
这样可以减少关键信息被切断的问题。
3. 混合检索
纯向量检索适合语义相似问题,但对编号、代码、接口名、专有名词可能效果一般。
例如:
API-USER-1024 是什么接口?
这种问题更适合关键词检索。
因此,生产环境常使用:
向量检索 + BM25 关键词检索 + Rerank 重排序
4. 权限控制
企业知识库中经常有权限差异。不同员工能看的文档不同。
权限控制应该在检索阶段完成,而不是生成答案后再过滤。
例如检索时添加条件:
department = 用户所属部门
role = 用户角色
project_id in 用户可访问项目
否则可能出现信息泄露问题。
5. 答案可追溯
RAG 系统最好返回答案来源,例如:
答案:超过 5000 元需要部门负责人和财务负责人审批。
来源:《员工报销制度》第 2 条
这能提升用户信任,也方便排查错误。
6. 评估体系
不要只靠主观体验判断 RAG 效果。建议准备一批测试问题,例如 100~300 条,标注标准答案和来源文档。
评估指标可以包括:
- Recall@K:正确资料是否被召回;
- Answer Accuracy:答案是否正确;
- Faithfulness:答案是否忠实于资料;
- Latency:响应耗时;
- Cost:调用成本。
六、RAG 常见优化方向
1. Query Rewrite
用户问题可能很口语化,可以先让模型改写问题。
例如:
这个钱怎么报?
改写为:
员工费用报销流程是什么?
改写后的问题更利于检索。
2. Multi Query
同一个问题可以生成多个查询语句,从不同角度检索,提高召回率。
例如:
报销超过 5000 元需要审批吗?
单笔报销金额超过 5000 的审批流程是什么?
大额报销需要哪些负责人审批?
3. Rerank
初步检索可能召回 20 条结果,再用 Rerank 模型重新排序,选出最相关的 3~5 条传给大模型。
Rerank 通常能显著提升答案准确率。
4. 缓存机制
企业知识库中很多问题会重复出现,例如假期制度、报销流程、入职材料等。
可以对高频问题和检索结果做缓存,降低延迟和成本。
七、RAG 与微调的区别
很多开发者会问:既然要让模型知道企业知识,为什么不直接微调?
简单对比如下:
RAG:
适合频繁更新的知识
可返回来源
成本较低
便于权限控制
微调:
适合学习固定风格或特定任务格式
更新成本较高
不适合存储大量事实知识
难以保证答案来源
在企业知识库场景中,通常优先选择 RAG。微调更适合让模型学会某种输出格式、行业术语风格或分类任务。
两者也可以结合使用:用 RAG 提供知识,用微调提升模型在特定任务上的表现。
八、总结
RAG 是目前大模型落地中非常实用的一种架构,尤其适合企业知识库、智能客服、文档问答等场景。
它的核心流程可以概括为:
文档处理 -> 文本切分 -> 向量化 -> 检索 -> Prompt 拼接 -> 大模型生成
对于开发者来说,搭建一个 Demo 并不复杂,但要做好一个生产级 RAG 系统,需要重点关注文档质量、切片策略、混合检索、权限控制、答案溯源和评估体系。
如果你正在尝试把大模型接入自己的业务系统,RAG 通常是一个值得优先尝试的方向。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)