跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

RAG 系统实战:Langchain 框架与纯手搓方案对比

检索增强生成(RAG)技术通过引入外部知识库解决大模型幻觉问题。对比了基于 Langchain 框架的快速实现与从零手写的底层逻辑方案,涵盖环境配置、向量检索及 Prompt 构建全流程。Langchain 适合快速原型开发,而纯手搓有助于深入理解机制并优化资源受限场景。文章详细拆解了文档加载、文本切分、向量化存储、相似度检索及模型生成等关键步骤,并提供常见错误排查与最佳实践建议。

内存管理发布于 2026/3/27更新于 2026/10/2585 浏览
RAG 系统实战:Langchain 框架与纯手搓方案对比

你是否曾为大模型'一本正经地胡说八道'而困扰?或者希望它能回答关于你个人笔记或公司内部文档的问题?今天,我们就来一起动手搭建一个简单 RAG 系统,让你的大模型从'闭卷考试'变成'开卷考试',大幅提升回答的准确性和实用性。

了解了 RAG 的基本原理后,我们来看看如何动手实现它。

RAG 核心架构图

一、什么是 RAG?——让大模型'开卷考试'

1.1 RAG 的核心思想

RAG 概念示意图

想象一下,你正在参加一场考试。如果只能靠记忆答题,遇到不熟悉的知识点就容易答错甚至瞎编——这就像没有 RAG 的传统大语言模型(LLM)。它们的知识被'固化'在训练数据中,无法获取新信息,也容易产生'幻觉'。

而 RAG(Retrieval-Augmented Generation,检索增强生成)技术,就是给大模型发了一本'参考书'。当用户提问时,系统会先从这本'参考书'(你的知识库)里查找相关信息,再把找到的内容和问题一起交给大模型去生成答案。

这种'开卷考试'的方式带来了三大优势:

  • ✅ 事实更准确:答案基于真实文档,大幅减少胡编乱造。
  • ✅ 知识可更新:只需更新你的知识库文件,就能让大模型掌握最新信息。
  • ✅ 支持私有数据:你可以让它读取你的 PDF 报告、Word 文档、网页内容,解答专属问题。
1.2 RAG 的工作流程

RAG 工作流程图

RAG 系统的工作可以分为两个阶段:离线准备和在线查询。

在你开始使用之前,需要先完成'离线准备'阶段,也就是把你的知识文档处理好,方便后续快速查找。

这个过程包含五个核心步骤:

  1. 用户提问:'阿司匹林的禁忌症是什么?'
  2. 查询向量化:将你的问题转换成一串数字(向量),这是计算机理解语义的方式。
  3. 向量检索:在存储着无数文档片段向量的数据库中,找出与问题向量最相似的几个片段。
  4. 提示增强:把检索到的相关片段和原始问题拼接起来,形成一个新的、信息更丰富的提示词。
  5. 大模型生成:把这个增强后的提示词交给大模型,它就能结合这些参考资料,生成一个有据可依的答案。

整个过程通常在几秒内完成,为你提供精准可靠的信息。

二、两种实现方式对比:Langchain vs 纯手搓

对比示意图

现在,你已经知道了 RAG 是怎么工作的,接下来就要选择用什么方式来搭建它。主要有两种路径:使用成熟的框架 Langchain,或是从零开始 纯手搓 实现。

2.1 开发效率对比
  • Langchain:这就像使用一套高级乐高积木。它已经为你预制好了'文档加载器'、'文本切分器'、'向量数据库接口'等模块。你只需要像搭积木一样把它们组装起来,几分钟内就能跑通整个流程,非常适合快速验证想法。
  • 纯手搓:这就像是自己烧砖、砍木头,再盖房子。你需要手动调用底层库(如 sentence-transformers、faiss)来实现每一个环节。虽然耗时较长,但你能完全掌控每一个细节。
2.2 代码复杂度与维护成本
维度Langchain 实现纯手搓实现
开发时间~25 分钟~180 分钟
代码行数少(高层 API)多(底层集成)
调试难度低高
典型应用场景快速原型、企业系统教学演示、边缘设备

总的来说,Langchain 抽象程度高,学习曲线稍陡,但后期扩展和维护非常方便。而纯手搓代码透明可控,适合教学理解底层机制,但在实际项目中维护成本较高。

2.3 适用场景总结表
维度Langchain 实现纯手搓实现
开发时间~25 分钟~180 分钟
代码行数少(高层 API)多(底层集成)
调试难度低高
典型应用场景快速原型、企业系统、复杂 Agent 编排教学演示、资源受限环境、极致性能优化

通过这个对比,你应该能初步判断哪种方式更适合你当前的需求。接下来,我们将分别用这两种方式,带你一步步实现一个完整的 RAG 系统。

三、Langchain 实现:高效构建你的第一个 RAG 系统

如果你的目标是快速上手并看到效果,那么 Langchain 绝对是首选。让我们开始吧!

3.1 环境准备

首先,你需要安装必要的 Python 包。打开你的命令行工具,执行以下命令:

pip install langchain langchain-openai langchain-text-splitters chromadb faiss-cpu openai python-dotenv 

同时,你需要一个 OpenAI API 密钥来调用 GPT 模型。为了安全起见,建议你创建一个 .env 文件来管理它:

# .env 文件内容
OPENAI_API_KEY=your_actual_api_key_here

这样,你的密钥就不会硬编码在 Python 脚本里了。

3.2 步骤详解与代码实现
加载文档
from langchain_community.document_loaders import TextLoader

# 创建 TextLoader 实例,加载名为"knowledge.txt"的文本文件
loader = TextLoader("knowledge.txt", encoding="utf-8")
documents = loader.load()
  • 功能说明:这一步负责读取你的原始文档。TextLoader 支持 TXT 格式,如果是 PDF,你可以换成 PyPDFLoader。
文本切分
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 初始化递归字符切分器
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,      # 每个文本块约 500 个字符
    chunk_overlap=50,    # 块之间重叠 50 个字符
    separators=["\n\n", "\n", "。", ".", "!", "?"]  # 分割符优先级
)
chunks = text_splitter.split_documents(documents)
  • 功能说明:将长文档切成小块,便于后续处理。chunk_overlap 的作用就像你读书时前后翻页保持连贯,防止一句话被切断。
  • 💡 小贴士:对于中文文档,确保分割符列表包含了中文句号'。'。
向量化并存入数据库

向量化过程

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

# 使用 OpenAI 的嵌入模型将文本块转为向量
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
vectorstore = Chroma.from_documents(
    chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"  # 将数据库持久化保存到本地
)
vectorstore.persist()  # 确保数据已写入磁盘
  • 功能说明:embeddings 模型是关键,它能让语义相近的句子(如'猫爱吃鱼'和'猫咪喜欢吃鱼')拥有相似的向量表示。
  • 替代方案:不想依赖 API?可以换用开源的 HuggingFaceEmbeddings 和 BAAI/bge-small-zh 模型。
创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
  • 功能说明:定义了一个检索策略,每次查询都会返回最相关的 Top-3 结果。
  • 高级选项:可以设置 search_type="mmr" 来使用最大边际相关性算法,避免返回重复冗余的结果。
初始化语言模型
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
  • 功能说明:接入 GPT-3.5 模型进行回答生成。temperature=0 表示输出尽可能确定和稳定。
  • 替代建议:国内用户可以尝试接入通义千问、百川等国产大模型的 API。
构建 RAG 生成链
from langchain_core.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser

# 定义一个提示模板,明确告诉大模型如何利用上下文
prompt = ChatPromptTemplate.from_template(
    "请基于以下上下文回答问题,若无法找到答案请回答'我不知道'。\n"
    "上下文:{context}\n\n问题:{question}"
)

# 构建核心链条:接收问题 -> 检索相关文档 -> 填充提示模板 -> 调用大模型 -> 解析字符串输出
rag_chain = ({"context": retriever, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser())

# 执行查询
result = rag_chain.invoke("阿司匹林的禁忌症是什么?")
print("AI 回答:", result)
  • 功能说明:RunnablePassthrough() 的作用是保留用户的原始问题,并将其传递给下一个组件。
  • ✅ 已完成:恭喜!你已经成功用 Langchain 搭建了一个功能完整的 RAG 系统。

四、纯手搓实现:深入理解 RAG 底层机制

现在,让我们放下高级框架,亲手实现一遍 RAG 的核心逻辑,这能帮助你彻底理解它的本质。

4.1 不依赖框架的意义

通过纯手搓实现,你将清晰地看到数据是如何在各个组件间流动的。这对于学习原理、在资源受限的设备上部署,或者进行极致的性能优化都至关重要。

4.2 步骤详解与代码实现
加载并切分文本
# 手动读取文本文件
with open("knowledge.txt", "r", encoding="utf-8") as f:
    text = f.read()

# 使用简单的滑动窗口进行切分
chunk_size = 500
overlap = 50
chunks = [text[i:i + chunk_size] for i in range(0, len(text), chunk_size - overlap)]
print(f"✅ 切分为 {len(chunks)} 个文本块")
  • 功能说明:这是一种最基础的切分方法,通过固定长度和重叠来生成文本块。
  • 缺陷提醒:这种方法缺乏语义感知,可能会在句子中间切断,导致信息丢失。相比之下,Langchain 的递归切分器要智能得多。
调用嵌入模型生成向量
from sentence_transformers import SentenceTransformer
import numpy as np

# 加载一个轻量级的开源嵌入模型
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')

# 将所有文本块批量编码为向量
chunk_vectors = embedding_model.encode(chunks, show_progress_bar=True)
dimension = chunk_vectors.shape[1]  # 获取向量维度
  • 功能说明:SentenceTransformer 库让本地运行嵌入模型变得非常简单。
  • 推荐模型:对于中文场景,强烈推荐使用 BAAI/bge-small-zh 模型,效果远超通用模型。
构建 Faiss 向量索引

Faiss 索引结构

import faiss

# 创建一个基于欧氏距离(L2)的索引
index = faiss.IndexFlatL2(dimension)

# 将所有文本块的向量添加到索引中
index.add(np.array(chunk_vectors))

# 将索引持久化保存,避免每次启动都重新计算
faiss.write_index(index, "faiss_index.bin")
  • 功能说明:Faiss 是一个高效的向量相似度搜索库,特别适合处理大规模向量数据。
  • 性能优化:对于更大的数据集,可以改用 IndexHNSWFlat 等近似最近邻索引,以换取更快的检索速度。
相似度检索
query = "阿司匹林的禁忌症是什么?"

# 将查询问题也编码为向量
query_vector = embedding_model.encode([query])

# 在向量库中搜索与查询向量最相似的 3 个结果
distances, indices = index.search(np.array(query_vector), k=3)

# 根据检索到的索引,取出对应的文本块
retrieved_chunks = [chunks[i] for i in indices[0]]
context = "\n".join(retrieved_chunks)  # 将多个相关片段合并为一段上下文
  • 功能说明:index.search() 返回的是距离值(越小越相似)和对应的向量索引。
  • 改进建议:在某些场景下,使用余弦相似度比欧氏距离更能反映语义相关性。
拼接 Prompt 并调用 LLM 生成
from transformers import pipeline

# 创建一个文本生成管道,这里使用较小的 gpt2 模型作为示例
generator = pipeline("text-generation", model="gpt2")

# 构造增强提示词
prompt = f"根据以下资料回答问题:\n{context}\n\n问题:{query}\n回答:"

# 调用模型生成回答
output = generator(prompt, max_new_tokens=150, do_sample=False)

# 提取出模型生成的回答部分,去掉前面的提示词
answer = output[0]['generated_text'][len(prompt):].strip()
print("AI 回答:", answer)
  • 功能说明:这是整个流程的最后一步,也是最关键的一步。大模型基于你提供的上下文来生成最终答案。
  • 注意事项:max_new_tokens 参数控制生成的最大长度,避免模型无限制地生成下去。

✅ 纯手搓 RAG 系统已成功运行!

五、环境配置与新手避坑指南

环境配置图

为了让你的 RAG 之旅更加顺畅,这里有一份详细的避坑指南。

5.1 推荐开发环境
  • Python 版本:强烈推荐使用 3.9 – 3.11 版本。避免使用 3.12 及以上版本,因为其对 typing 模块的修改可能导致 langchain 等库出现 ImportError: cannot import name 'AsyncGenerator' 的错误。
  • 内存要求:建议 ≥16GB。向量计算和模型加载会消耗大量内存。
  • GPU 建议:如果有 NVIDIA 显卡(显存 ≥8GB),可以显著加速嵌入模型和大模型的推理速度。
5.2 虚拟环境与依赖管理

永远不要在全局环境中安装 Python 包!使用虚拟环境可以避免不同项目间的依赖冲突。

# 创建名为 rag_env 的虚拟环境
python -m venv rag_env

# 激活虚拟环境 (Linux/Mac)
source rag_env/bin/activate

# 激活虚拟环境 (Windows)
rag_env\Scripts\activate

# 安装依赖
pip install langchain sentence-transformers faiss-cpu openai chromadb PyPDF2
5.3 新手常见问题与解决方案
问题类型表现解决方案
Python 版本冲突ImportError: cannot import name 'AsyncGenerator'使用 Python 3.9–3.11
API 密钥未设置AuthenticationError检查 .env 文件中的 OPENAI_API_KEY 是否正确
中文路径报错invalid utf-8 sequence将项目放在纯英文路径下,例如 C:\projects\rag_demo
模型下载失败.model.part 残留检查网络连接,或使用代理;也可尝试离线预载模型
5.4 最佳实践建议
  • 使用 .env 文件:管理 API 密钥等敏感信息,保障安全。
  • 合理设置文本块大小:建议在 200–500 字符之间,并启用 50 字符左右的重叠,以保持语义完整。
  • 约束大模型行为:在提示词中明确指令,如'仅基于以上资料回答,不知道就说'我不知道'',有效防止幻觉。
  • 生产环境容器化:使用 Docker 打包应用,保证在任何服务器上都能一致运行。

六、总结与学习建议

通过本文的学习,相信你已经掌握了 RAG 系统的核心概念和两种主流实现方式。

  • 初学者建议:优先使用 Langchain 快速搭建原型,体验 RAG 带来的强大能力。
  • 进阶学习:再通过 纯手搓 的方式,亲手实现一遍,从而深刻理解向量检索、嵌入模型等底层机制。
  • 未来探索:当你熟练掌握基础 RAG 后,可以进一步探索 GraphRAG(利用图结构进行复杂推理)或 多模态 RAG(支持图片、音频等非文本信息的检索)等更高级的形态。

目录

  1. 一、什么是 RAG?——让大模型“开卷考试”
  2. 1.1 RAG 的核心思想
  3. 1.2 RAG 的工作流程
  4. 二、两种实现方式对比:Langchain vs 纯手搓
  5. 2.1 开发效率对比
  6. 2.2 代码复杂度与维护成本
  7. 2.3 适用场景总结表
  8. 三、Langchain 实现:高效构建你的第一个 RAG 系统
  9. 3.1 环境准备
  10. .env 文件内容
  11. 3.2 步骤详解与代码实现
  12. 加载文档
  13. 创建 TextLoader 实例,加载名为"knowledge.txt"的文本文件
  14. 文本切分
  15. 初始化递归字符切分器
  16. 向量化并存入数据库
  17. 使用 OpenAI 的嵌入模型将文本块转为向量
  18. 创建检索器
  19. 初始化语言模型
  20. 构建 RAG 生成链
  21. 定义一个提示模板,明确告诉大模型如何利用上下文
  22. 构建核心链条:接收问题 -> 检索相关文档 -> 填充提示模板 -> 调用大模型 -> 解析字符串输出
  23. 执行查询
  24. 四、纯手搓实现:深入理解 RAG 底层机制
  25. 4.1 不依赖框架的意义
  26. 4.2 步骤详解与代码实现
  27. 加载并切分文本
  28. 手动读取文本文件
  29. 使用简单的滑动窗口进行切分
  30. 调用嵌入模型生成向量
  31. 加载一个轻量级的开源嵌入模型
  32. 将所有文本块批量编码为向量
  33. 构建 Faiss 向量索引
  34. 创建一个基于欧氏距离(L2)的索引
  35. 将所有文本块的向量添加到索引中
  36. 将索引持久化保存,避免每次启动都重新计算
  37. 相似度检索
  38. 将查询问题也编码为向量
  39. 在向量库中搜索与查询向量最相似的 3 个结果
  40. 根据检索到的索引,取出对应的文本块
  41. 拼接 Prompt 并调用 LLM 生成
  42. 创建一个文本生成管道,这里使用较小的 gpt2 模型作为示例
  43. 构造增强提示词
  44. 调用模型生成回答
  45. 提取出模型生成的回答部分,去掉前面的提示词
  46. 五、环境配置与新手避坑指南
  47. 5.1 推荐开发环境
  48. 5.2 虚拟环境与依赖管理
  49. 创建名为 rag_env 的虚拟环境
  50. 激活虚拟环境 (Linux/Mac)
  51. 激活虚拟环境 (Windows)
  52. 安装依赖
  53. 5.3 新手常见问题与解决方案
  54. 5.4 最佳实践建议
  55. 六、总结与学习建议

更多推荐文章

查看全部
  • TinyWebServer 源码解析:HTTP 机制与高性能设计
  • AI 大模型实战:基于 SkyText 的文本生成与聊天机器人开发
  • Stable Diffusion 控制光线的三种方式
  • 数据结构:双向链表实现与算法实战
  • MambaYOLO:用状态空间模型做目标检测,简单且高效
  • 双指针算法核心概念与 C++ 经典例题解析
  • 本地搭建 Stable Diffusion AI 绘画工具完整指南
  • Python 兼职接单指南:需求评估与平台选择
  • RxJava 迁移至 Kotlin Flow 的背压策略对比与实现
  • PX4 无人机 MID360 激光雷达 FAST-LIO 室内定位与定点悬停配置
  • OpenClaw 实战:基于 Rust+Tauri 构建安全沙箱清理 Skill
  • Linux 系统文件 IO 与重定向原理
  • AI 时代初级开发者的创意生存指南:数据与创新的边界
  • DeepSeek-R1 大模型基于 MS-Swift 框架部署/推理/微调实践
  • Redis 压缩列表、Listpack 及哈希表扩容机制详解
  • 飞算 JavaAI 专业版实测:全栈代码生成与效率提升
  • JSP 基于身份的在线投票系统设计与实现
  • GitHub Copilot 兼容 OpenAI/Anthropic API 代理工具 copilot-api 使用指南
  • 国产数据库新路径:电科金仓融合架构与 AI 实践
  • Python 和 PyCharm 安装配置教程

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online