随着大语言模型的发展,很多开发者开始尝试把 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 通常是一个值得优先尝试的方向。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐