前言:为什么要学 RAG?

你有没有遇到过这样的场景:

  • 把公司的内部文档、产品手册扔给 ChatGPT,它却一问三不知?
  • 想让 AI "记住"你自己上传的 PDF,却不知道从哪下手?

这正是 RAG(Retrieval-Augmented Generation,检索增强生成) 要解决的问题。

简单说,RAG 做了一件事:在生成答案之前,先去你的私有知识库里找相关内容,再交给大模型回答。

本文将带你从零开始,用大约 100 行 Python 代码,搭建一个真实可用的 RAG 问答应用,并用 Gradio 做成漂亮的 Web 界面。


一、核心概念快速扫盲

在写代码之前,先用 5 分钟搞清楚三个关键词:

1. 什么是 Embedding(嵌入)?

Embedding 是把文字转换成一串数字(向量)的技术。
比如"苹果"和"水果"在向量空间里距离很近,而"苹果"和"汽车"距离很远。

类比:就像图书馆的书籍分类系统,相似内容的书放在一起,方便查找。

2. 什么是向量数据库?

存放 Embedding 向量的数据库,支持"找最相似的几条内容"这种查询方式。

本文使用 FAISS(Facebook AI Similarity Search),它是本地运行的轻量级向量库,不需要启动额外服务,适合学习和小项目。

3. RAG 的完整流程

用户提问
   ↓
把问题转成 Embedding 向量
   ↓
在 FAISS 里找最相似的几段文本(检索)
   ↓
把检索结果 + 原始问题一起发给 LLM
   ↓
LLM 生成最终答案

二、环境准备

2.1 安装依赖

bash

复制

pip install openai faiss-cpu gradio tiktoken langchain langchain-openai langchain-community

💡 如果你在国内,pip 速度慢,可以加镜像源:

bash

复制

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai faiss-cpu gradio tiktoken langchain langchain-openai langchain-community

2.2 配置 API Key

本文使用 OpenAI 兼容接口,创建一个 .env 文件(放在项目根目录):

env

复制

OPENAI_API_KEY=你的API密钥
OPENAI_BASE_URL=https://api.openai.com/v1  # 如果使用国内兼容接口,替换成对应地址

然后在代码里加载:

python

复制

from dotenv import load_dotenv
load_dotenv()

没有安装 python-dotenv?pip install python-dotenv


三、构建知识库

3.1 准备你的文档

新建一个文件夹 docs/,把你的 .txt 文件放进去。
这里我们用一个简单的示例文档 docs/sample.txt

公司简介:
我们是一家专注于 AI 应用开发的初创公司,成立于 2023 年。

产品介绍:
我们的旗舰产品是智能客服系统,支持多轮对话和知识库问答。

联系方式:
邮箱:support@example.com
电话:400-888-8888
工作时间:周一至周五 9:00-18:00

3.2 读取并分块

文档通常很长,一次性送给 LLM 会超出 token 限制,所以需要先切成小块

python

复制

🔧 参数说明

  • chunk_size:每块文本的最大长度。太大会超 token,太小会丢失上下文,500~1000 是常用范围。
  • chunk_overlap:块与块之间的重叠字数,避免一句话被切成两半时语义丢失。

3.3 生成 Embedding 并存入 FAISS

python

复制

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS

def build_vectorstore(chunks):
    """生成向量并构建 FAISS 索引"""
    embeddings = OpenAIEmbeddings()  # 使用 text-embedding-ada-002
    vectorstore = FAISS.from_documents(chunks, embeddings)
    vectorstore.save_local("faiss_index")  # 保存到本地,下次直接加载
    print("✅ 知识库构建完成,已保存到 faiss_index/")
    return vectorstore

def load_vectorstore():
    """加载已有的 FAISS 索引"""
    embeddings = OpenAIEmbeddings()
    return FAISS.load_local(
        "faiss_index", 
        embeddings,
        allow_dangerous_deserialization=True  # 本地文件,信任加载
    )

四、实现 RAG 问答核心逻辑

python

复制

🧠 为什么 temperature 设 0.1?
temperature 控制模型的"创造力",越高越发散,越低越保守。RAG 场景下我们希望 AI 忠实于检索结果,所以设低一点。


五、用 Gradio 做 Web 界面

Gradio 是一个让你用几行 Python 就能做出漂亮 Web 界面的库,非常适合快速展示 AI Demo。

python

复制


六、整合:完整的 app.py

把上面所有模块整合到一个文件里:

python

复制


七、运行效果

bash

复制

python app.py

首次运行会看到:

🔨 正在构建知识库,请稍候...
✅ 知识库构建完成!共 6 个文本块
Running on local URL:  http://127.0.0.1:7860

浏览器打开后,你会看到一个干净的问答界面,试试问:

  • "公司的邮箱是什么?" → AI 会从文档里找到并回答
  • "你们的产品叫什么名字?" → 准确检索并引用原文
  • "明天天气怎么样?" → 因为知识库里没有,AI 会说"没有相关信息"(而不是胡编)

八、常见问题 & 进阶方向

Q1:文档更新了,知识库怎么刷新?

python

复制

vs = get_vectorstore(force_rebuild=True)  # 传 True 强制重建

Q2:想支持 PDF 文件怎么办?

python

复制

pip install pypdf

from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("your_document.pdf")

Q3:回答质量不好?

几个调优思路:

问题 调优方向
检索不准 减小 chunk_size,增大 k
答案太发散 降低 temperature(接近 0)
答案不够详细 修改 prompt,要求"详细说明"
语言混乱 在 prompt 中强调"用中文回答"

Q4:如何支持上传文件?

Gradio 提供了文件上传组件:

python

复制

file_input = gr.File(label="上传文档", file_types=[".txt", ".pdf"])

上传后解析、重建索引,即可实现动态知识库!


进阶路线图

学完本文后,你可以继续探索:

本文内容(入门)
    ↓
多文件 + PDF 支持 → 文档管理系统
    ↓
流式输出(Streaming)→ 更好的用户体验
    ↓
对话历史记忆(Memory)→ 多轮问答
    ↓
混合检索(BM25 + 向量)→ 更高检索精度
    ↓
Reranker 排序 → 工业级 RAG

总结

这篇教程我们完成了:

  • ✅ 理解了 RAG 的核心原理:Embedding → 检索 → 生成
  • ✅ 用 LangChain 搭建了文档加载、分块、向量化的完整流水线
  • ✅ 用 FAISS 构建了本地知识库,支持持久化
  • ✅ 用 Gradio 做出了可交互的 Web 问答界面
  • ✅ 完整代码 < 100 行,可直接运行

RAG 是目前落地最广泛的 LLM 应用模式之一,掌握它,你就能把任何文档变成"可以对话的知识库"。

如果这篇文章对你有帮助,欢迎点赞收藏 🌟
有问题欢迎在评论区讨论!

Logo

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

更多推荐