RAG 从零到一:用 Python 给大模型接上你的私有知识库

大模型很聪明,但它有个致命弱点------它只知道训练截止日期之前的信息,而且不知道你公司内部的任何东西。

RAG(Retrieval-Augmented Generation,检索增强生成)就是解决这个问题的标准方案:先从你的私有文档里检索出相关内容,再把这些内容拼进 prompt 让大模型回答。

本文带你从零实现一个完整的 RAG 系统,代码可以直接跑。

整体架构

RAG 的流程分两个阶段:

建库阶段(离线):

  1. 加载文档(PDF、txt、网页等)
  2. 切分成小块(chunk)
  3. 向量化每个 chunk
  4. 存入向量数据库

查询阶段(在线):

  1. 用户提问
  2. 把问题向量化
  3. 从向量库里找最相似的 chunk
  4. 把 chunk + 问题拼成 prompt
  5. 大模型生成回答

环境准备

bash 复制代码
pip install langchain langchain-community chromadb openai tiktoken

本文用 ChromaDB 做向量库,用 OpenAI Embedding 做向量化,大模型调 GPT-3.5。如果想换成国内模型(DeepSeek、通义等),只需换掉 LLM 和 Embedding 的初始化部分。

第一步:加载并切分文档

python 复制代码
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 加载文档
loader = TextLoader("knowledge.txt", encoding="utf-8")
documents = loader.load()

# 切分:每块 500 字符,重叠 50 字符
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
)
chunks = splitter.split_documents(documents)
print(f"切分出 {len(chunks)} 个 chunk")

chunk_overlap 是关键参数------让相邻 chunk 有一定重叠,避免一句话被切断后上下文丢失。

第二步:向量化并存入 ChromaDB

python 复制代码
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

embeddings = OpenAIEmbeddings()

# 建库(第一次运行会调 Embedding API,有费用)
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"  # 持久化到本地
)
vectorstore.persist()
print("向量库建立完成")

第三步:检索 + 生成

python 复制代码
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA

# 加载已有的向量库
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=OpenAIEmbeddings()
)

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),  # 取最相关的3个chunk
    return_source_documents=True  # 同时返回来源,方便溯源
)

# 开始提问
question = "我们产品的退款政策是什么?"
result = qa_chain({"query": question})

print("回答:", result["result"])
print("\n来源文档:")
for doc in result["source_documents"]:
    print("-", doc.page_content[:100])

几个实际踩坑点

1. chunk 大小要根据内容调

技术文档、合同这类信息密度高的,chunk_size 设 300-500 比较合适;FAQ 问答类可以更小,100-200 就够。太大会引入噪音,太小会丢失上下文。

2. Embedding 模型和查询要用同一个

建库和查询必须用同一个 Embedding 模型,不然向量空间不一致,检索结果会很差。

3. k 值不是越大越好

retriever 里的 k(返回几个 chunk)建议从 3 开始。k 太大会把不相关内容塞进 prompt,反而干扰模型回答。

4. 中文切分要注意

RecursiveCharacterTextSplitter 对中文支持还行,但如果文档是纯中文,建议加上中文标点作为切分分隔符:

python 复制代码
splitter = RecursiveCharacterTextSplitter(
    chunk_size=300,
    chunk_overlap=30,
    separators=["\n\n", "\n", "。", "!", "?", ";", " ", ""]
)

替换成本地/国产模型

不想用 OpenAI 的话,换成 DeepSeek 只需改两行:

python 复制代码
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(
    model_name="deepseek-chat",
    openai_api_key="your-deepseek-key",
    openai_api_base="https://api.deepseek.com/v1"
)

Embedding 可以换成 HuggingFace 的免费模型:

python 复制代码
from langchain.embeddings import HuggingFaceEmbeddings

embeddings = HuggingFaceEmbeddings(
    model_name="BAAI/bge-small-zh-v1.5"  # 中文效果不错
)

下一步

这是最基础的 RAG 实现。实际项目里还会遇到:

  • 文档更新怎么增量入库
  • 多路召回(关键词 + 向量混合检索)
  • Rerank 对召回结果重排序
  • 对话历史管理(多轮问答)

这些进阶内容在 gufacode.com 的 RAG 教程里有完整讲解,从原理到工程落地都有覆盖,可以继续深入。


跑通这个基础版本之后,你会发现 RAG 本身并不复杂------复杂的是让它在真实数据上表现稳定。慢慢调,多踩坑,才是正经路子。

相关推荐
线上放牧人4 分钟前
Windows删除图标缓存
windows·python·pyqt
qq_54702617931 分钟前
Python 变量和简单数据类型
python
智搜广告2 小时前
智搜广告:科技行业AI回答优化公司如何破局
大数据·python·elasticsearch·geo
IpdataCloud2 小时前
AI智能体调用工具怎么核验来源IP?归属地、网络类型与代理风险识别(含Python代码)
数据库·python·tcp/ip
2601_966949653 小时前
只拿到股票代码还不够:量化程序到底还需要哪些标的信息?——从数据建模开始理解股票元数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
蒸鱼Yuzheng3 小时前
Python 游戏测试开发怎么准备:日志解析、接口校验、并发与可维护性
自动化测试·python·测试开发·面试题·游戏测试
Ivanqhz3 小时前
BM1688 双核架构
python·深度学习·神经网络·cnn·mlir
Java后端的Ai之路3 小时前
Python进阶探索17 - Python中的深拷贝与浅拷贝
人工智能·python·ai·浅拷贝·深拷贝
西柚研究生1234564 小时前
论文分析17:YOLOv11_UAVNet:无人机航拍图像专用目标检测算法
人工智能·python·深度学习·算法·目标检测
沧海一笑-dj5 小时前
【Python】Python学习笔记-初识 Python
python·python安装·python解释器