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 本身并不复杂------复杂的是让它在真实数据上表现稳定。慢慢调,多踩坑,才是正经路子。

相关推荐
青 春 记 忆5 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO35 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO7 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白7 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲9 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)10 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机10 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69211 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy12 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽12 小时前
真实即粗糙,光滑是伪造
人工智能·python