你的RAG系统,是“搭积木”还是“盖房子”?Langchain与纯手搓的抉择,决定了你的AI是“玩具”还是“神器”,细思极恐!

你的RAG系统,是“搭积木”还是“盖房子”?Langchain与纯手搓的抉择,决定了你的AI是“玩具”还是“神器”,细思极恐!

你是否曾为大模型“一本正经地胡说八道”而困扰?或者希望它能回答关于你个人笔记或公司内部文档的问题?今天,我们就来一起动手搭建一个简单 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-transformersfaiss)来实现每一个环节。虽然耗时较长,但你能完全掌控每一个细节。

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?可以换用开源的 HuggingFaceEmbeddingsBAAI/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:加载并切分文本
# 手动读取文本文件withopen("knowledge.txt","r", encoding="utf-8")as f: text = f.read()# 使用简单的滑动窗口进行切分 chunk_size =500 overlap =50 chunks =[text[i:i + chunk_size]for i inrange(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 参数控制生成的最大长度,避免模型无限制地生成下去。
  • 步骤 1:加载并切分文本
  • 步骤 2:调用嵌入模型生成向量
  • 步骤 3:构建 Faiss 向量索引
  • 步骤 4:相似度检索
  • 步骤 5:拼接 Prompt 并调用 LLM 生成

✅ 纯手搓 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(支持图片、音频等非文本信息的检索)等更高级的形态。

七、转载声明

本文为原创文章,如需转载,请联系作者获得授权,并注明出处。

Read more

腾讯云端Openclaw+飞书 多机器人配置全攻略(新手友好版)

前言:随着AI自动化工具的普及,Openclaw凭借强大的自主执行能力,成为很多人提升效率的首选;而飞书作为高效协同工具,其机器人功能可无缝融入日常工作流。当两者结合,配置多机器人实现分工协作(如办公提效、信息管理、场景化响应),能进一步释放AI价值。 本文将从前期准备、分步配置、实战调试到常见问题,手把手教你完成Openclaw+飞书多机器人配置,全程无复杂操作,新手也能快速上手,建议收藏备用! 一、配置前必看:核心说明与前置准备 1.1 核心价值 Openclaw+飞书多机器人配置,核心是让多个飞书机器人分别绑定Openclaw的不同Agent,实现「分工协作、各司其职」——无需切换工具,在飞书内即可完成所有操作,大幅提升工作效率。 ✅ 典型分工场景: * 1个机器人负责日常指令响应 * 1个机器人负责定时推送资讯 * 1个机器人负责办公流程自动化(会议整理、报表生成等) 1.2 前置环境准备(必做) 提前准备好以下环境和工具,避免配置过程中卡顿,所有工具均为免费可用: * 基础环境:云端安装Openclaw;

RISC-V开源处理器实战:从Verilog RTL设计到FPGA原型验证

RISC-V开源处理器实战:从Verilog RTL设计到FPGA原型验证

引言:开源浪潮下的RISC-V处理器设计 在芯片设计领域,RISC-V架构正以其开源免授权、模块化扩展和极简指令集三大优势重塑行业格局。与传统闭源架构不同,RISC-V允许开发者自由定制处理器核,从嵌入式微控制器到高性能服务器芯片均可覆盖。本文以Xilinx Vivado 2025工具链和蜂鸟E203处理器为核心,完整呈现从Verilog RTL设计到FPGA原型验证的全流程,为嵌入式工程师和硬件爱好者提供一套可复现的实战指南。 项目目标与技术栈 * 核心目标:基于RISC-V RV32I指令集,设计支持五级流水线的32位处理器核,实现基础算术运算、逻辑操作及访存功能,并在Xilinx Artix-7 FPGA开发板验证。 * 工具链:Xilinx Vivado 2025(逻辑设计、综合实现)、ModelSim(功能仿真)、Xilinx Artix-7 XC7A35T FPGA开发板(硬件验证)。 * 参考案例:蜂鸟E203处理器(芯来科技开源RISC-V核,已在Xilinx FPGA上完成移植验证,最高运行频率50MHz)。 一、数字系统设计流程:从需求到架构 1.

Unitree Go2机器人ROS2开发实战:从零搭建仿真环境

想要快速上手Unitree Go2四足机器人的ROS2开发吗?go2_ros2_sdk项目为你提供了完整的ROS2接口封装,支持Go2 AIR/PRO/EDU全系列机型。这个非官方SDK不仅实现了与真实机器人的无缝对接,还为仿真环境搭建提供了坚实基础。 【免费下载链接】go2_ros2_sdkUnofficial ROS2 SDK support for Unitree GO2 AIR/PRO/EDU 项目地址: https://gitcode.com/gh_mirrors/go/go2_ros2_sdk 🚀 5分钟快速搭建开发环境 环境准备:确保系统已安装ROS2 Humble或更高版本,以及Python 3.8+环境。通过简单的git clone命令即可获取项目源码: git clone https://gitcode.com/gh_