不会RAG的程序员不是好程序员!完整流程解析,让你的大模型不再“一本正经胡说八道“
文章详细介绍了RAG(检索增强生成)技术的完整实现流程,包括文档加载、文本切分、向量存储与检索、重排序与上下文压缩,最终接入LLM生成答案。通过LangChain框架,将RAG流程拆分为可组合、可替换的组件,从基础概念到实际应用,为开发者提供了工程上完整的RAG实现方案,适合大模型开发者和编程初学者学习和实践。
RAG(Retrieval-Augmented Generation,检索增强生成)是当前大模型应用中最常见、也最容易落地的一种架构。
简单来说:
在模型回答问题之前,先从你的知识库中找出相关内容,再把这些内容一并交给模型生成答案。
这一篇将基于一个最小可用、但工程上完整的 RAG 流程,从零梳理:
- 文档是如何被加载为 LangChain 能理解的
Document - 文档是如何被切分
- 向量是如何存储与检索的
- 检索结果如何被压缩 / 重排序
- 最终如何接入到 LLM 调用中
1. RAG 检索整体流程
一个最基本的 RAG 系统,至少包含以下 5 个步骤:
原始文档↓ 加载Document↓ 切分Chunks↓ 向量化VectorStore↓ 检索Relevant Docs↓ 送给 LLMAnswer
我们可以使用LangChain,将上面的步骤拆成一组可组合、可替换的组件,下面我们按这个顺序一步一步来。
2. 文档加载器(Document Loader)
文档加载器作用:
把各种格式的文件,统一转成 Document 对象。
Document 是什么
LangChain 中所有 RAG 的基础数据结构都是:
from langchain_core.documents import DocumentDocument( page_content="正文内容", metadata={"page": 1, "source": "xxx.pdf"})
page_content:参与向量化和生成的文本metadata:不参与 embedding,但可用于过滤、追溯来源
后面的切分、存储、检索,本质上都是在操作 List[Document]。
常见文档加载器
PDF:PyPDFLoader
from langchain_community.document_loaders import PyPDFLoaderloader = PyPDFLoader("example.pdf")# 按页加载docs = loader.load()
Word:Docx2txtLoader
from langchain_community.document_loaders import Docx2txtLoaderloader = Docx2txtLoader("example.docx")docs = loader.load()
Markdown:UnstructuredMarkdownLoader
from langchain_community.document_loaders import UnstructuredMarkdownLoaderloader = UnstructuredMarkdownLoader("README.md")docs = loader.load()
TXT / 日志类文本:TextLoader
from langchain_community.document_loaders import TextLoaderloader = TextLoader("data.txt", encoding="utf-8")docs = loader.load()
3. 文本切分器(TextSplitter)
大模型并不适合直接吃整篇文档:
- 上下文长度有限
- 向量召回精度会下降
切分策略,直接决定 RAG 的上限。
CharacterTextSplitter
基于固定字符长度切分,简单、可控:
from langchain.text_splitter import CharacterTextSplittertext_splitter = CharacterTextSplitter( separator="\n\n", # 使用两个换行符作为分隔符 chunk_size=1000, # 每个文本块的最大字符数 chunk_overlap=200 # 相邻块之间的重叠字符数)split_docs = text_splitter.split_documents(docs)
适合结构简单、段落清晰的文本。
RecursiveCharacterTextSplitter (推荐)
按设定的分隔符列表递归尝试切分文本,直到每个块的大小不超过设定的 chunk_size,并保留一定的 chunk_overlap 以减少上下文丢失。这种方式能最大限度保持段落、句子、单词的完整性,非常适合长文本处理、向量化检索和 RAG 场景。
from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 每个文本块的最大字符数 chunk_overlap=50, # 相邻块之间的重叠字符数 separators=["\n\n", "\n", "。", " ", ""], # 递归尝试切分文本的标识 keep_separator=True # 支持保持分隔符)split_docs = text_splitter.split_documents(docs)
这是 RAG 中最常用的切分方式。
其他切分方式
- TokenTextSplitter:按 token 数切(对齐模型上下文)
- MarkdownHeaderTextSplitter:按 Markdown 标题层级切
- HTMLHeaderTextSplitter:按 HTML 结构切
4. 文本向量化(Embedding)
在前面的步骤中,我们已经拿到了List[Document]
但向量数据库并不能直接存文本,它真正存的是使用向量模型向量化后的高维浮点数组。 这个过程,就叫 Embedding(向量化)。
Embedding 的作用:
把“文本的语义”,映射成一个可以计算距离的向量。
之后所有的检索,都是在:
“问题的向量,和哪一段文档的向量最接近?”
使用 HuggingFace Embedding 运行本地向量模型
以 bge-base-zh 为例(中文效果很好):
from langchain_community.embeddings import HuggingFaceEmbeddingsdef get_embeddings(): return HuggingFaceEmbeddings( model_name="BAAI/bge-large-zh-v1.5", model_kwargs={"device": "cuda"}, # 或 cpu encode_kwargs={"normalize_embeddings": True} # 配合 cosine 相似度效果更稳定 )
在使用 cosine 相似度时,建议开启 normalize_embeddings=True,可以让不同长度文本的向量分布更稳定。
首次加载需要在HuggingFace中下载模型,如果网络问题下载不下来可以使用阿里魔塔等镜像网站下载到本地,然后将
BAAI/改成本地路径
通义千问 DashScope Embedding (云端模型)
from langchain_community.embeddings import DashScopeEmbeddingsdef get_embeddings(): return DashScopeEmbeddings( model="text-embedding-v3", dashscope_api_key="sk-xxx" )
5 向量数据库:PGVector
这里使用 PostgreSQL + pgvector 作为示例。
你可能注意到了一个细节:我们从来没有手动调用 embedding.embed(),这是因为: LangChain 把 embedding 的调用,隐藏在 VectorStore 内部了
from langchain_postgres import PGVectorvectorstore = PGVector( embeddings=get_embeddings(), # 使用定义好的嵌入模型进行向量检索和入库 collection_name="knowledge_base", connection="postgresql+psycopg://user:password@host:5432/db")# 写入向量库vectorstore.add_documents(split_docs)
⚠️ 注意:向量入库和向量检索必须使用完全相同的 Embedding 模型和参数,否则即使文档存在,也几乎无法被检索到。
6 检索器(Retriever)
retriever = vectorstore.as_retriever( search_type="similarity", #按照分值,取最高的 search_kwargs={ "k": 20, #检索前20个相似的 "filter": {"tag": "主角"} #ai或人工标注的标签 })results = retriever.invoke("孙悟空是谁")
常见的检索方式还有:
search_type="mmr":在相似度和多样性之间做平衡search_type="similarity_score_threshold":按阈值过滤
常见filter写法
# 等于{"filter": {"uuid": "123"}}# 或{"filter": {"$or": [{"type": "1"}, {"type": "2"}]}}# 范围{"filter": {"year": {"$gte": 2020, "$lte": 2024}}}
7 重排序与上下文压缩
在 RAG 中,最常见的一步是 向量相似度检索: 把问题和文档都映射成向量,然后找“最相似”的文本片段。
但在真实工程中,你很快就会发现一个问题: 向量召回到的,是“语义相似”的内容,但不一定是“最相关、最可用”的内容。
向量检索(Embedding Search)的本质是:
- 把文本映射到高维空间
- 用余弦距离 / 内积衡量“语义接近程度”
这意味着它擅长的是:
- 同义表达
- 语义模糊匹配
- 大概方向相近的内容
但它 并不理解任务目标,比如:哪一段更适合回答“定义型问题” 哪一段是结论,哪一段只是背景,哪一段虽然语义相似,但其实是反例 / 否定 / 无关描述
举个例子:
问题:“孙悟空是谁?”
向量检索可能会召回:
- 《西游记》的背景介绍
- 关于“齐天大圣”称号的来历
- 描述花果山的段落
- 一段提到孙悟空名字但在讲别的角色的内容
这些内容都“像”孙悟空,但真正适合直接喂给 LLM 的,可能只有其中 1~2 段。如果全部召回,并喂给大模型又会因为噪音过大,幻觉概率变高
所以我们需要重排序(Rerank)拿到真正需要的内容
它是「问题 × 文档」成对判断,而不是各自向量化后比距离。
Rerank 是精匹配,不是近似匹配,以 CrossEncoder / DashScopeRerank 为代表的 rerank 模型。他会把问题 + 文档片段拼在一起,直接判断:这段内容,对回答这个问题有没有帮助
这意味着它能识别:
- 这段是不是在“回答问题”,还是只是“提到了关键词”
- 是定义、结论,还是铺垫背景
- 是否存在否定、反转、条件限制
所以一个成熟、稳定的检索流程通常是 使用向量召回快速找“可能相关的候选集”然后使用重排序从候选集中找top(N) “最有用的内容”
HuggingFace CrossEncoder
使用HuggingFace 本地模型进行重排序,这里我们使用 bge-reranker-base
from langchain_community.cross_encoders import HuggingFaceCrossEncoderfrom langchain.retrievers.document_compressors.cross_encoder_rerank import CrossEncoderRerankerreranker = CrossEncoderReranker( model=HuggingFaceCrossEncoder("bge-reranker-base"), top_n=5)
通义千问 Rerank
也可以使用云端服务提供的重排序,比如阿里的gte-rerank-v2
from langchain_community.document_compressors.dashscope_rerank import DashScopeRerankreranker = DashScopeRerank( model="gte-rerank-v2", dashscope_api_key="sk-xxx", top_n=5)
ContextualCompressionRetriever
把 召回 + 重排序 封装成一个整体:
from langchain.retrievers import ContextualCompressionRetrieverfrom langchain_core.runnables import RunnableLambdacompression_retriever = ContextualCompressionRetriever( base_retriever=retriever, base_compressor=reranker)results = compression_retriever.invoke("孙悟空是谁")
8 接入 LLM,完成 RAG
chain = compression_retriever | prompt | llm | StrOutputParser()chain.invoke("孙悟空是谁")
- 小结
这一篇从真实工程路径出发,梳理了一个完整的 LangChain RAG 流程:
- 文档加载(多格式)
- 文本切分(多策略)
- 向量存储与检索
- 重排序与上下文压缩
- 最终接入 LLM 生成答案
理解这些之后,每一步都可以独立替换和优化
后续无论是:
- 多知识库 RAG
- Agent + RAG
本质上,都只是这些 Runnable 的不同组合形式。
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线科技企业深耕十二载,见证过太多因技术卡位而跃迁的案例。那些率先拥抱 AI 的同事,早已在效率与薪资上形成代际优势,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在大模型的学习中的很多困惑。我们整理出这套 AI 大模型突围资料包:
- ✅ 从零到一的 AI 学习路径图
- ✅ 大模型调优实战手册(附医疗/金融等大厂真实案例)
- ✅ 百度/阿里专家闭门录播课
- ✅ 大模型当下最新行业报告
- ✅ 真实大厂面试真题
- ✅ 2025 最新岗位需求图谱
所有资料 ⚡️ ,朋友们如果有需要 《AI大模型入门+进阶学习资源包》,下方扫码获取~
① 全套AI大模型应用开发视频教程
(包含提示工程、RAG、LangChain、Agent、模型微调与部署、DeepSeek等技术点)
② 大模型系统化学习路线
作为学习AI大模型技术的新手,方向至关重要。 正确的学习路线可以为你节省时间,少走弯路;方向不对,努力白费。这里我给大家准备了一份最科学最系统的学习成长路线图和学习规划,带你从零基础入门到精通!
③ 大模型学习书籍&文档
学习AI大模型离不开书籍文档,我精选了一系列大模型技术的书籍和学习文档(电子版),它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。
④ AI大模型最新行业报告
2025最新行业报告,针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。
⑤ 大模型项目实战&配套源码
学以致用,在项目实战中检验和巩固你所学到的知识,同时为你找工作就业和职业发展打下坚实的基础。
⑥ 大模型大厂面试真题
面试不仅是技术的较量,更需要充分的准备。在你已经掌握了大模型技术之后,就需要开始准备面试,我精心整理了一份大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

以上资料如何领取?

为什么大家都在学大模型?
最近科技巨头英特尔宣布裁员2万人,传统岗位不断缩减,但AI相关技术岗疯狂扩招,有3-5年经验,大厂薪资就能给到50K*20薪!

不出1年,“有AI项目经验”将成为投递简历的门槛。
风口之下,与其像“温水煮青蛙”一样坐等被行业淘汰,不如先人一步,掌握AI大模型原理+应用技术+项目实操经验,“顺风”翻盘!

这些资料真的有用吗?
这份资料由我和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理,现任上海殷泊信息科技CEO,其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证,服务航天科工、国家电网等1000+企业,以第一作者在IEEE Transactions发表论文50+篇,获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。
资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。

以上全套大模型资料如何领取?

更多推荐


所有评论(0)