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

RAG 系统实现指南:Langchain 与纯手搓方案对比

RAG 技术通过检索增强生成提升大模型回答准确性。对比基于 Langchain 框架的快速搭建与纯手搓底层实现两种路径,前者适合快速原型开发,后者有助于理解向量检索等核心机制。内容涵盖环境配置、文档加载、文本切分、向量化存储、检索及生成链构建等关键步骤,并提供常见问题解决方案与最佳实践建议,帮助开发者根据需求选择合适的 RAG 实现方案。

MqEngine发布于 2026/4/5更新于 2026/5/2316 浏览
RAG 系统实现指南:Langchain 与纯手搓方案对比

RAG 系统实现指南:Langchain 与纯手搓方案对比

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

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

在这里插入图片描述

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

1.1 RAG 的核心思想

在这里插入图片描述

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

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

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

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

1.2 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 步骤详解与代码实现

步骤 1:加载文档
from langchain_community.document_loaders import TextLoader

# 创建 TextLoader 实例,加载名为"knowledge.txt"的文本文件
loader = TextLoader("knowledge.txt", encoding="utf-8")
documents = loader.load()
  • 功能说明:这一步负责读取你的原始文档。TextLoader 支持 TXT 格式,如果是 PDF,你可以换成 PyPDFLoader。
步骤 2:文本切分
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 的作用就像你读书时前后翻页保持连贯,防止一句话被切断。
  • 提示:对于中文文档,确保分割符列表包含了中文句号'。'。
步骤 3:向量化并存入数据库

在这里插入图片描述

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 模型。
步骤 4:创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k":3})
  • 功能说明:定义了一个检索策略,每次查询都会返回最相关的 Top-3 结果。
  • 高级选项:可以设置 search_type="mmr" 来使用最大边际相关性算法,避免返回重复冗余的结果。
步骤 5:初始化语言模型
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
  • 功能说明:接入 GPT-3.5 模型进行回答生成。temperature=0 表示输出尽可能确定和稳定。
  • 替代建议:国内用户可以尝试接入通义千问、百川等国产大模型的 API。
步骤 6:构建 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 步骤详解与代码实现

步骤 1:加载并切分文本
# 手动读取文本文件
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 的递归切分器要智能得多。
步骤 2:调用嵌入模型生成向量
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 模型,效果远超通用模型。
步骤 3:构建 Faiss 向量索引

在这里插入图片描述

import faiss

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

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

# 将索引持久化保存,避免每次启动都重新计算
faiss.write_index(index, "faiss_index.bin")
  • 功能说明:Faiss 是一个高效的向量相似度搜索库,特别适合处理大规模向量数据。
  • 性能优化:对于更大的数据集,可以改用 IndexHNSWFlat 等近似最近邻索引,以换取更快的检索速度。
步骤 4:相似度检索
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() 返回的是距离值(越小越相似)和对应的向量索引。
  • 改进建议:在某些场景下,使用余弦相似度比欧氏距离更能反映语义相关性。
步骤 5:拼接 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 系统实现指南:Langchain 与纯手搓方案对比
  2. 一、什么是 RAG?——让大模型“开卷考试”
  3. 1.1 RAG 的核心思想
  4. 1.2 RAG 的工作流程
  5. 二、两种实现方式对比:Langchain vs 纯手搓
  6. 2.1 开发效率对比
  7. 2.2 代码复杂度与维护成本
  8. 2.3 适用场景总结表
  9. 三、Langchain 实现:高效构建你的第一个 RAG 系统
  10. 3.1 环境准备
  11. .env 文件内容
  12. 3.2 步骤详解与代码实现
  13. 步骤 1:加载文档
  14. 创建 TextLoader 实例,加载名为"knowledge.txt"的文本文件
  15. 步骤 2:文本切分
  16. 初始化递归字符切分器
  17. 步骤 3:向量化并存入数据库
  18. 使用 OpenAI 的嵌入模型将文本块转为向量
  19. 步骤 4:创建检索器
  20. 步骤 5:初始化语言模型
  21. 步骤 6:构建 RAG 生成链
  22. 定义一个提示模板,明确告诉大模型如何利用上下文
  23. 构建核心链条:接收问题 -> 检索相关文档 -> 填充提示模板 -> 调用大模型 -> 解析字符串输出
  24. 执行查询
  25. 四、纯手搓实现:深入理解 RAG 底层机制
  26. 4.1 不依赖框架的意义
  27. 4.2 步骤详解与代码实现
  28. 步骤 1:加载并切分文本
  29. 手动读取文本文件
  30. 使用简单的滑动窗口进行切分
  31. 步骤 2:调用嵌入模型生成向量
  32. 加载一个轻量级的开源嵌入模型
  33. 将所有文本块批量编码为向量
  34. 步骤 3:构建 Faiss 向量索引
  35. 创建一个基于欧氏距离(L2)的索引
  36. 将所有文本块的向量添加到索引中
  37. 将索引持久化保存,避免每次启动都重新计算
  38. 步骤 4:相似度检索
  39. 将查询问题也编码为向量
  40. 在向量库中搜索与查询向量最相似的 3 个结果
  41. 根据检索到的索引,取出对应的文本块
  42. 步骤 5:拼接 Prompt 并调用 LLM 生成
  43. 创建一个文本生成管道,这里使用较小的 gpt2 模型作为示例
  44. 构造增强提示词
  45. 调用模型生成回答
  46. 提取出模型生成的回答部分,去掉前面的提示词
  47. 五、环境配置与新手避坑指南
  48. 5.1 推荐开发环境
  49. 5.2 虚拟环境与依赖管理
  50. 创建名为 rag_env 的虚拟环境
  51. 激活虚拟环境 (Linux/Mac)
  52. 激活虚拟环境 (Windows)
  53. 安装依赖
  54. 5.3 新手常见问题与解决方案
  55. 5.4 最佳实践建议
  56. 六、总结与学习建议
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AI 临床副驾驶实战:基于 Go 的电子病历助手与 HIS 对接
  • 零依赖纯前端 AI 辅助病例管理系统:无后端实现诊疗行为核验
  • 使用 DeepSeek 构建高性能贪吃蛇游戏实战
  • GitHub Copilot 同步 Claude Code 本地技能与 Agent 映射方案
  • C++ 内存管理:new/delete 操作自定义类型的构造与析构原理
  • ComfyUI 提示词助手实战:利用自动化流程提升 AI 绘画效率
  • C++11 左值右值引用区别与移动语义解决传值返回对象销毁问题
  • AI 前沿技术日更简报:2026-03-04
  • 自进化医疗智能体:动态记忆与持续运行的 Python 架构设计
  • LazyLLM 框架实战:构建代码专家智能体
  • Matlab 找不到编译器解决方案:MinGW-w64 C/C++环境配置
  • Python Pillow 图像处理与格式转换详解
  • 前端精确数字运算:用 BigNumber.js 解决 JS Number 精度问题
  • 金仓 KingbaseES 融合架构实践:从多库并存到一库多能
  • AI 驱动的虚拟现实与增强现实开发
  • Linux 进程间通信:匿名管道原理与实现
  • Python 爬虫实战:使用 Flet 构建移动端 App
  • C++中string的常用函数用法总结
  • 基于 Rokid 灵珠平台构建旅游 AR 智能体实践
  • 医疗 AI 场景下模型融合与集成策略深度解析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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