RAG 实战教程:从零构建企业智能问答 Agent

RAG 实战教程:从零构建企业智能问答 Agent

完整代码地址:https://github.com/ziyifast/Demo/tree/main/1-AI/RAG-Knowledge-Base

1.为什么需要RAG:

想象一下,你刚入职一家公司,需要快速了解所有产品信息。你有一个"超级助理"(大语言模型,LLM),它上知天文下知地理,但存在三个致命缺陷:

缺陷 说明 举个例子
知识滞后 只学会了训练截止日期前的知识 问它"2026年最新的行业政策",它可能一无所知
幻觉生成 面对未知问题会"一本正经地胡说八道" 调查显示,约 30% 的复杂问题回答存在事实性错误
无法访问私有数据 完全不了解公司内部信息 问"我们的产品保修期多久",它只能凭空猜测

2.什么是RAG:

RAG(检索增强生成) 正是为解决上述问题而生。它的核心思想很简单:不让模型凭记忆硬答,而是允许它"开卷考试"。

一句话理解:RAG = 给大模型配一个实时更新的"外部知识库"。在回答问题前,模型会先去这个知识库里"翻书"查找相关资料,然后基于查到的资料进行回答。

项目产出:

一个能基于你的私有文档(产品手册、公司制度、学习笔记)进行问答,并能溯源引用来源的智能 Agent。

一、核心概念

1. Embedding(向量嵌入)

计算机不认识"语义",只认识"数字"。Embedding 就是那个"翻译官",负责把人类的文字、图片翻译成计算机能计算的数字列表(向量)。语义相近的内容,翻译出的数字向量在空间中的距离也相近。

💡 核心规律:两个向量在空间中的距离越近 = 语义越相近。 这就是计算机"理解"语义的秘密。

2. 向量数据库(Vector Database)

普通数据库擅长找"完全一样"的内容,而向量数据库擅长找"意思最像"的内容。

核心价值:向量数据库是实现语义搜索和 RAG 的基石。

3. RAG(检索增强生成)

全称:Retrieval Augmented Generation 检索增强生成,RAG 不是一个单一技术,而是一个工作流,核心包含三大步骤:

bash 复制代码
📥 离线建库阶段:将你的私有文档分块、向量化,存入向量数据库。
🔍 在线检索阶段:将用户问题向量化,在向量库中检索最相关的 Top-K 文档块。
✍️ 增强生成阶段:将"用户问题 + 检索到的文档"一起打包发给大模型,让它"有据可依"地生成回答。

4. Agent(智能体)

能调用工具、自主决策的 AI 系统。它不只是"回答",更能"行动"。

bash 复制代码
RAG:  问题 → 检索 → 回答(线性流程)
Agent: 问题 → 思考 → 选工具 → 执行 → 观察 → 再思考 → ... → 回答
              ↑__________________________________________↓
              这个"思考→行动→观察"循环就是 Agent 的智能所在

例如,当你问"查一下订单 123 的退款政策"时,Agent 会:

  1. 思考:需要先查订单信息,再查对应的退款政策。

  2. 行动:调用"订单查询工具"获取产品名。

  3. 观察:得到"产品是 NeoCompute Standard"。

  4. 思考:现在需要查这款产品的退款政策。

  5. 行动:调用"知识库检索工具"。

  6. 最终回答:给出准确的退款政策。

二、快速开始

环境要求

  • Python 3.10+

  • pip 包管理器

1️⃣ 克隆并进入项目

bash 复制代码
git clone <your-repo-url> RAG-Tutorial
cd RAG-Tutorial

2️⃣ 安装依赖

bash 复制代码
# 安装所有必需的 Python 包
pip install -r requirements.txt

3️⃣ 配置 API Key

bash 复制代码
# 复制环境变量模板
cp .env.example .env

# 编辑 .env 文件,填入你的 API Key
# OPENAI_API_KEY=sk-your-real-key-here

💡 没有 OpenAI API Key? 可以使用免费的本地 BGE 模型:

bash 复制代码
# 在所有命令后面加 --embedding bge 即可
python scripts/03_build_knowledge_base.py --embedding bge

4️⃣ 按顺序运行演示

bash 复制代码
# 第一步:感受 Embedding 的魔力(无需 API Key)
python scripts/01_embedding_demo.py

# 第二步:玩转向量数据库 ChromaDB(无需 API Key)
python scripts/02_vector_db_demo.py

# 第三步:构建你的第一个知识库(需要 API Key 或用 bge)
python scripts/03_build_knowledge_base.py

# 第四步:RAG 问答(需要 API Key 或用 bge)
python scripts/04_rag_qa.py

# 第五步:Agent 智能体(需要 API Key)
python scripts/05_agent_demo.py

三、 分步教程

第一步:理解 Embedding

🎯 知识点:语义相近的文字 → 向量距离近。这就是 RAG 检索的基石。

1.运行命令:

bash 复制代码
python scripts/01_embedding_demo.py

2.你会看到什么:

  • 向量的样子 ------ 一句话被表示成 512 个数字

  • 语义相似度对比 ------ 观察"苹果水果"和"苹果公司"的向量距离差异

  • 最简单的语义搜索 ------ 用"保修多久"搜到"保修期3年"

3.效果:

4.关键代码片段:

bash 复制代码
from sentence_transformers import SentenceTransformer

# 加载模型(首次自动下载)
model = SentenceTransformer("BAAI/bge-small-zh-v1.5")

# 文字 → 向量
vector = model.encode("苹果是一种很好吃的水果")
# 结果: [0.23, -0.15, 0.78, ...] (512个数字)

# 计算相似度
sim = cosine_similarity(
    model.encode("产品保修多久"),
    model.encode("云服务器提供 3 年标准保修服务")
)
# 结果: 0.89 (高度相似!虽然字面不同)

第二步:向量数据库实战

🎯 知识点:向量数据库不匹配字面,而是按语义相似度检索。

1.运行命令:

python 复制代码
python scripts/02_vector_db_demo.py

2.你会学到:

操作 说明 类比 MySQL
创建 Collection 创建集合(表) CREATE TABLE
添加文档 存入文档+向量 INSERT INTO
语义查询 按相似度搜索 无对应!传统DB做不到
元数据过滤 精确+语义混合查询 WHERE + 向量搜索
更新/删除 文档管理 UPDATE / DELETE

3.效果:

4.关键代码片段:

python 复制代码
import chromadb

# 连接数据库
client = chromadb.PersistentClient(path="./chroma_demo_db")

# 创建集合
collection = client.create_collection(name="my_knowledge_base")

# 添加文档
collection.add(
    documents=["产品保修期为 3 年", "支持 7 天无理由退款"],
    ids=["doc_1", "doc_2"],
)

# 语义搜索
results = collection.query(
    query_texts=["保修多久"],
    n_results=3,
)
# 结果精确命中"产品保修期为 3 年"!
# 虽然"保修多久"和"保修期为3年"字面不同,但语义相同

第三步:构建知识库

🎯 知识点:分块策略直接影响 RAG 的检索质量。太小丢上下文,太大降精度。

通过免费开源的BGE 中文 Embedding 模型,构建知识库。官方网站:https://bge-model.com/

1.运行命令:

python 复制代码
# 使用免费本地模型(BGE)
python scripts/03_build_knowledge_base.py --embedding bge

# 使用LLM 服务商API(需要修改.env配置)
python scripts/03_build_knowledge_base.py

2.这个脚本做了什么:

bash 复制代码
docs/product_manual.txt(原始文档)
    │
    ▼ 加载文档
1个 Document 对象
    │
    ▼ 分块(chunk_size=500, overlap=50)
约 15-20 个文档块
    │
    ▼ 向量化(Embedding)
每个块 → 1536维向量(OpenAI)/ 512维向量(BGE)
    │
    ▼ 存入 ChromaDB
./chroma_db/ 目录(持久化存储)

分块策略说明:

分块(Chunking)是影响 RAG 检索质量的最关键环节之一

3.效果:

第四步:RAG 问答

🎯 知识点:RAG = 检索 + 生成。Embedding 模型决定了检索的上限(检索是否精准),LLM 决定了生成的下限(回答是否流畅、逻辑清晰)

1.因为涉及问答,所以必须配置外部LLM服务商提供的模型,本地的BGE是无法满足问答需求的。

BGE 等 Embedding 模型只能做"检索"(找相关文档),不具备"生成回答"的能力

2.运行命令:

bash 复制代码
# 演示模式(预设问题)
python scripts/04_rag_qa.py

# 交互模式(自己提问),使用LLM服务商 提供模型,如:Deepseek、Claude、GPT等
python scripts/04_rag_qa.py --interactive

# 使用本地BGE模型进行embedding(问答还是需要LLM服务商提供的模型)
python scripts/04_rag_qa.py --embedding bge

3.效果:

4.RAG 核心流程(完整代码):

bash 复制代码
from app.rag_engine import RAGEngine

# 1. 创建 RAG 引擎
engine = RAGEngine(
    persist_dir="./chroma_db",
    search_k=3,  # 检索 Top-3 最相关文档
)

# 2. 提问
answer, sources = engine.query("产品保修期是多久?")

print(answer)
# 输出: "根据产品手册第2.1节,NeoCloud所有自研硬件产品
#        享有3年标准保修服务,核心部件(CPU、内存、主板)
#        享有5年有限保修..."

# 3. 查看引用的源文档
for doc in sources:
    print(doc.page_content[:100])

chain_type 选择:

  • stuff:一次性将所有文档块放入 Prompt,速度最快,但受上下文窗口限制。适用于文档块较少(少于5个)的场景,新人首选。

  • map_reduce:对每个文档块单独生成答案,再将所有答案汇总后生成最终回答。速度较慢,能处理大量文档块。适合文档数量多、需综合信息的场景。

  • refine:逐篇迭代优化答案------先用首个文档块生成初始回答,后续文档块依次对上一轮答案进行补充修正。速度最慢,质量最高。适用于对准确性要求极高的场景。

  • map_rerank:对每个文档块分别生成答案并打分,最终只返回最高分答案。速度较快,适合仅需一个最佳答案的场景(如FAQ)。


第五步:Agent 智能体

🎯 知识点:Agent = RAG + 工具调用 + 自主决策。它能判断该用什么工具、按什么顺序,而不仅仅是回答问题。

1.运行命令:

bash 复制代码
# 基础 Agent(只有知识库工具)
python scripts/05_agent_demo.py

# 带额外工具的 Agent
python scripts/05_agent_demo.py --with-extras

# 交互式 Agent
python scripts/05_agent_demo.py --interactive

效果:

Agent 与普通 RAG 的区别:

bash 复制代码
# 普通 RAG:线性流程
answer = engine.query("产品保修多久")
# 内部:问题 → 向量化 → 检索 → 生成 → 返回

# Agent:思考-行动循环
response = agent.run("查订单 ORD-001,告诉我对应的退款政策")
# 内部:
#   Thought: 需要先查订单信息,再查退款政策
#   Action: OrderQuery("ORD-001")
#   Observation: 订单产品是 NeoCompute Standard
#   Thought: 现在需要查这个产品的退款政策
#   Action: KnowledgeBase("NeoCompute Standard 退款政策")
#   Observation: 按量付费支持随时退款,包月7天内无理由退款
#   Thought: 我有足够信息了
#   Final Answer: 订单 ORD-001(NeoCompute Standard)的退款政策是...

添加自定义工具:

python 复制代码
from app.agent import RAGAgent

agent = RAGAgent()

# 添加你自己的工具
def my_custom_tool(input_text: str) -> str:
    """你的工具逻辑"""
    return f"处理结果: {input_text}"

agent.add_tool(
    name="MyTool",
    func=my_custom_tool,
    description="这个工具用于XXX。当你需要XXX时使用。输入:XXX格式。"
)

四、 整体架构

完整代码地址:https://github.com/ziyifast/Demo/tree/main/1-AI/RAG-Knowledge-Base

python 复制代码
RAG/
├── README.md                          # 📖 本文档
├── requirements.txt                   # 📦 Python 依赖
├── .env.example                       # 🔑 环境变量模板
│
├── docs/                              # 📂 文档目录(放你的知识库文档)
│   └── product_manual.txt             #    示例:产品手册
│
├── scripts/                           # 🔧 可执行脚本(按顺序学习)
│   ├── 01_embedding_demo.py           #    第一步:理解 Embedding
│   ├── 02_vector_db_demo.py           #    第二步:向量数据库操作
│   ├── 03_build_knowledge_base.py     #    第三步:构建知识库
│   ├── 04_rag_qa.py                   #    第四步:RAG 问答
│   └── 05_agent_demo.py              #    第五步:Agent 智能体
│
├── app/                               # 📚 核心代码模块
│   ├── __init__.py                    #    包初始化
│   ├── knowledge_base.py              #    知识库构建(文档加载、分块、向量化)
│   ├── rag_engine.py                  #    RAG 引擎(检索 + 生成)
│   └── agent.py                       #    Agent 智能体(工具调用 + 自主决策)
│
└── chroma_db/                         # 🗄️ 向量数据库存储目录(自动生成)
    └── ...                            #    ChromaDB 持久化文件
模块 核心文件 职责
知识库 app/knowledge_base.py 文档加载、文本分块、向量化存储
RAG 引擎 app/rag_engine.py 执行检索、构建 Prompt、调用 LLM 生成
Agent app/agent.py 管理工具、执行"思考-行动"循环

五、 进阶优化

当你跑通基础流程后,可以通过以下方式提升效果:

1. 检索优化

优化方向 方法 效果
混合检索 关键词检索 (BM25) + 语义检索 (Embedding) 兼顾精确匹配和语义理解,显著提升召回率
重排序 (Rerank) 先用 Embedding 粗排 Top-50,再用 Cross-Encoder 精排 效果提升最明显,能极大提升 Top-3 准确率
多路召回 从不同角度(不同分块策略、不同模型)检索合并 提升召回覆盖率,减少漏检

2. 分块优化

优化方向 方法
语义分块 按段落、章节等语义边界切分,而非机械地按字数切割
父子文档 (Parent Document Retriever) 检索细粒度的小块(精准),返回粗粒度的大块(上下文完整)
滑动窗口 用滑动窗口生成更多有重叠的块,丰富上下文信息

3. Prompt 优化

bash 复制代码
❌ 差 Prompt:
"回答问题: {question}\n参考资料: {context}"

✅ 好 Prompt:
"你是一个专业的企业知识库助手。请严格基于以下参考资料回答问题。
如果资料中没有相关信息,请明确说'根据现有资料无法回答',不要编造。

参考资料:
{context}

问题: {question}

请用中文回答,并注明信息来源。"

4. Embedding 模型选择

模型 维度 中文效果 费用 适用场景
OpenAI text-embedding-3-small 1536 ⭐⭐⭐⭐ $0.02/1M tokens 通用英文优先
OpenAI text-embedding-3-large 3072 ⭐⭐⭐⭐⭐ $0.13/1M tokens 高精度需求
BAAI/bge-small-zh-v1.5 512 ⭐⭐⭐⭐ 免费 中文场景首选
BAAI/bge-large-zh-v1.5 1024 ⭐⭐⭐⭐⭐ 免费 高精度中文场景
moka-ai/m3e-base 768 ⭐⭐⭐⭐ 免费 中文轻量选择

⚠️ Embedding 模型决定了召回的上限------文档向量化时丢失的语义信息,后续任何优化都无法补救。


常见问题

Q1: 我没有 OpenAI API Key 怎么办?

使用本地免费的 BGE 模型:

首次运行会自动下载模型文件(约 100MB)。

Q2: 如何替换成国产大模型(DeepSeek/Qwen/GLM)?

修改 .env 文件:

Q3: 分块大小(chunk_size)如何选择?

FAQ/短问答:300-500 字符

通用文档:500-800 字符(推荐新手从 500 开始)

技术文档/长文章:800-1500 字符

重叠:始终设为 chunk_size 的 10%

Q4: 检索多少文档(search_k)合适?

注意:k 值太大,容易引入噪声,反而干扰 LLM 生成。

k=3:大部分场景(默认推荐)

k=5:需要综合多方面信息时

k=1:精准问答(如FAQ)

Q5: 为什么检索到的内容不相关?

1.检查 Embedding 模型是否适合你的语言(中文文档用中文模型)

2.调整 chunk_size(当前可能太大或太小)

3.检查文档质量(是否包含太多噪声)

4.尝试增大 k 值看是否有相关内容被排在后面


参考资料

相关推荐
BaoshengTT2 小时前
2026年双流区汽车贴膜种类及挑选要点保圣威固7V不凡门店
python
chatexcel2 小时前
ChatExcel AI Word 升级:多模态读资料、按模板生成、智能排版配图,还能批注修订和联动Excel 复核
人工智能·ai·word·excel·ai写作
zhiSiBuYu05172 小时前
Flask 请求与响应新手实战指南
后端·python·flask
宸津-代码粉碎机2 小时前
告别手动Jar部署!生产级无损热部署方案,彻底解决OOM与更新失效问题
java·大数据·开发语言·人工智能·python
米码收割机2 小时前
【移动】线上购物移动端网站(源码+文档)【独一无二】
java·开发语言·前端·python·django
未知违规用户2 小时前
大模型项目: 学习FastAPI 服务器开发
服务器·人工智能·python·学习·fastapi
想会飞的蒲公英2 小时前
PyTorch reshape、view、transpose、广播到底怎么选?
人工智能·pytorch·python
卷无止境2 小时前
Python装饰器:一层糖衣包裹的函数魔法
后端·python
xlrqx2 小时前
长治家电清洗培训基地如何挑选及行业基本培训标准科普
大数据·python