Agentic RAG实战教程:从零开始构建智能体的主动检索能力,实现智能信息获取的飞跃!
本文详解Agentic RAG技术,通过LangChain、阿里云百炼DashScope和Chroma向量数据库,构建完整向量数据库流程,展示两种将RAG引入智能体的方法:动态系统提示词和RAG工具封装。这使智能体能主动决定检索策略、组合信息、重试检索并判断信息充分性,实现从"静态检索"到"智能信息获取"的转变,提升知识覆盖度、准确性与可解释性。
简介
本文详解Agentic RAG技术,通过LangChain、阿里云百炼DashScope和Chroma向量数据库,构建完整向量数据库流程,展示两种将RAG引入智能体的方法:动态系统提示词和RAG工具封装。这使智能体能主动决定检索策略、组合信息、重试检索并判断信息充分性,实现从"静态检索"到"智能信息获取"的转变,提升知识覆盖度、准确性与可解释性。
环境准备
本节课我们将以 LangChain 1.0 的 API 为基础,结合阿里云百炼 DashScope 的向量模型与 Chroma 向量数据库。从零开始搭建一个可被 Agent 调用的 RAG 系统。
请提前安装以下依赖:
pip install langchain langchain-community dashscope langchain_chroma beautifulsoup4
接下来我们将基于这些模块正式构建向量数据库,并将其封装为 Agent 可用的工具。
RAG 简介
定义
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合 外部知识库 + 大模型生成能力 的技术,其核心流程包括:
- 根据用户问题进行检索
- 从本地或在线知识库中选出最相关的片段
- 将检索内容作为上下文提供给大模型
- 由大模型基于外部知识进行回答
它的作用是“补充知识”,解决大模型知识滞后、不完整的问题。

传统 RAG vs Agentic RAG
| 类型 | 执行方式 | 能力特点 |
|---|---|---|
| 传统 RAG | 固定流程:检索 → 拼接上下文 → 生成回答 | 模型被动接受检索结果,无法控制查询方式 |
| Agentic RAG | 智能体主动:提出检索请求 → 多轮检索 → 自我判断 → 生成结果 | 能判断检索是否足够、是否需要重新查询,且可组合工具、反思与规划能力 |
Agentic RAG 的优势在于:
- 智能体可以 自主生成检索指令(Retrieval as a Tool)
- 支持 多轮检索与迭代优化策略
- 可以判断检索不足 → 自主补检索
- 可与其他工具协同(如计算器、API 查询)
因此,本节课不仅仅实现一个 RAG,而是构建一个可以:
- 自动检索
- 自动调整检索方式
- 自动结合检索结果回答
- 可嵌入多智能体体系
的 Agentic RAG 工具模块。
代码实战
简介
假如我们希望将 RAG 变成 Agent 可用的工具,首先我们需要创建出一个向量数据库,然后在这个向量数据库的基础上根据问题搜索里面有用的信息并进行使用。
因此我们的步骤分为:
-
向量数据库生成:
-
信息获取
-
文本分割
-
文本向量化
-
向量数据库创建及载入
-
调用向量数据库完成任务:
-
加载向量数据库
-
检索并执行智能体

信息获取
为了能够完成构建向量数据库,第一步,也是最重要的一步就是找到合适的信息源。这里我们就使用开源的书籍《动手学习深度学习》里的简介章节的内容作为我们向量数据库的信息源,后续所有的对话都将在此基础上进行。
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://zh.d2l.ai/chapter_introduction/index.html")
docs = loader.load()
文本分割
在获取到了信息后,此时这个是一大段的字符串信息,假如直接将其载入数据库中,未来调用的时候就会非常的耗费 token 。因此对于所有 RAG 系统都必须要做的事情就是将其进行切分,比如下面这个就是将一大段字符切分为一块块,每一块包含 1500 个字符。同时为了能够让上下文信息连贯, 也额外的添加了上下各 150 个 token。
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=150)
splits = text_splitter.split_documents(docs)
那这就意味着将可能几万 token 的内容拆分成了几十个 1800 token 的分块,这样的话每次检索的时候,我们只要找到最相关的前几块并给到大模型就好。这样比起直接将所有内容都传给大模型要更节省 token 的消耗。
文本向量化
在将文本字符分块后,我们就要准备将其存储到向量数据库当中。但是此时的分块里还是字符串,而字符串并不能直接载入到向量数据库中。我们需要先将这些分块转为向量信息,然后再将向量信息存储到向量数据库当中。
这里我们使用的就是阿里云百炼大模型平台的 text-embedding-v1 词向量模型,其会将传入的信息转为 1,536 维的向量,这样信息就能够保存到向量数据库中了:
from langchain_community.embeddings import DashScopeEmbeddings
import os
embeddings = DashScopeEmbeddings(dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"), model="text-embedding-v1")
向量数据库创建及载入
在准备好了文本分割完的字符串块体、embedding 模型后,我们就可以使用 LangChain 中比较推荐的 Chroma 向量数据库,并将转化好的向量载入到向量数据库中。这里我们还需要设置一下向量数据库保存的位置(目前在当前文件夹下的 chroma 文件夹中):
from langchain_chroma import Chroma
vectordb = Chroma.from_documents(documents=splits, embedding=embeddings, persist_directory="./chroma")
这样我们把向量数据库准备好了,后续就可以当做工具进行使用了。以上的内容我们可以单独制作成一个文件(vectordb.py),未来假如我们想要对向量数据库进行调整,就可以在该文件进行修改使用,完整的代码如下所示:
from langchain_community.document_loaders import WebBaseLoader
import os
loader = WebBaseLoader("https://zh.d2l.ai/chapter_introduction/index.html")
docs = loader.load()
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=150)
splits = text_splitter.split_documents(docs)
from langchain_community.embeddings import DashScopeEmbeddings
embeddings = DashScopeEmbeddings(dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"), model="text-embedding-v1")
from langchain_chroma import Chroma
vectordb = Chroma.from_documents(documents=splits, embedding=embeddings, persist_directory="./chroma")
加载向量数据库
在创建完向量数据库后,接下来我们就可以基于这个数据库进行进一步的工具开发。这里我们可以重新新建一个文件(RAG_Agent.py),然后先载入 embedding 模型及已经创建好的 Chroma 数据库,为后续的调用打下基础。
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_chroma import Chroma
import os
embeddings = DashScopeEmbeddings(dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"), model="text-embedding-v1")
vectordb = Chroma(embedding_function=embeddings,
persist_directory="./chroma"# 必须与上一步保持一致)
应用实践
接下来我们就可以基于这个 vectordb 进行向量数据库的检索工作了。这里介绍两个应用场景:
- 根据用户问题在向量数据库中找到相关片段并拼接到系统提示词中,后续智能体在发出工具指令以及调用工具时就能够基于这部分信息更智能的完成任务。
- 将向量数据库作为检索工具,根据问题提炼出检索的语句,然后看返回的结果是否能够满足。假如能够满足则返回整理后的信息,假如不满足则调整检索语句再次检索,直至智能体认为符合要求为止。这种方式也被称为是 Agentic RAG 的形式。
载入系统提示词中
假如我们希望根据用户的提问实时的修改系统提示词,我们可以使用 LangChain 的内置中间件来实现。这里我们使用的是 wrap_model_call 的特殊形式 dynamic_prompt 来实现。相比起 wrap_model_call 作用在整个模型调用的过程中,并需要传入的参数 request 和 handler。dynamic_prompt 只作用在第一次模型调用前,并且也只对系统提示词产生影响,无法真正执行调用信息:
from langchain.agents.middleware import dynamic_prompt, ModelRequest
from langchain.agents import create_agent
import os
@dynamic_prompt
def prompt_with_context(request: ModelRequest) -> str:
"""自动根据用户问题检索知识并注入到系统提示"""
last_query = request.state["messages"][-1].text
retrieved_docs = vectordb.similarity_search(last_query, k=3)
docs_content ="\n\n".join(doc.page_content fordocin retrieved_docs)
system_message =("You are a helpful assistant. ""Use the following retrieved context to answer the user:\n\n"
f"{docs_content}")return system_message
# 创建智能体
agent = create_agent(llm, tools=[], middleware=[prompt_with_context])# 测试查询
query ="What is computer vision?"forstepin agent.stream({"messages":[{"role":"user", "content": query}]},
stream_mode="values",
):
step["messages"][-1].pretty_print()
那这个 prompt_with_context 函数实际上实现了:
- 从 request.state 中获取最新一条的 messages 里的信息(用户提问)
- 然后根据用户提问使用相似度检索的方式找到前 3 条最相关的片段
- 然后把这三条片段拼接起来,形成一段字符串 docs_content
- 然后将这段字符串传给 system_message 并最后进行返回
然后在创建智能体时将这个函数以 middleware 的形式传入到 agent 中,后续就能够实现根据用户提问动态调整系统提示词。
RAG 工具
那这里的第二种方案就是将 RAG 作为工具进行使用。首先我们需要将其变为工具:
from langchain.tools import tool
@tool(response_format="content_and_artifact")
def retrieve_context(query: str):
"""Retrieve information to help answer a query."""
retrieved_docs = vectordb.similarity_search(query, k=2)
serialized ="\n\n".join((f"Source: {doc.metadata}\nContent: {doc.page_content}")fordocin retrieved_docs
)return serialized, retrieved_docs
这里由于我们不仅仅导出一段文本,并且我们还要导出原始的对象,因此在 response_format 参数里我们设置为 content_and_artifact。这部分信息将会自动被保存在系统层中,后续我们可以在中间件或节点中进行调用。
然后我们需要将大模型、工具、提示词统一配置到 create_agent 中,并对其进行调用:
from langchain_community.chat_models import ChatTongyi
llm = ChatTongyi(model="qwen-max")
tools =[retrieve_context]# If desired, specify custom instructions
prompt =("You have access to a tool that retrieves context from a deep learning book. ""Use the tool to help answer user queries.")
from langchain.agents import create_agent
agent = create_agent(llm, tools, system_prompt=prompt)
query =("What is the deep learning model used in computer vision tasks? ")foreventin agent.stream({"messages":[{"role":"user", "content": query}]},
stream_mode="values",
):
event["messages"][-1].pretty_print()
这个时候就会根据我们的问题去数据库里检索对应的内容,找到足够的内容后整理这些信息并返回结果。
总结
本节课围绕 Agentic RAG 展开,从基础概念、向量数据库构建到实际封装为智能体可用的工具,完成了从“静态检索增强”到“可调度可控制的智能信息获取能力”的转变。
我们首先通过 网页加载—文本切分—向量化—Chroma 存储 这一完整流程构建了知识库,然后演示了两种将 RAG 引入智能体的方法:
-
动态系统提示词(dynamic_prompt)
智能体在第一次模型调用前自动检索知识并注入上下文,使得回答内容更加准确与可靠。
-
RAG 工具(@tool)
将检索过程封装为可调用的工具,使智能体能够自主发起检索、判断信息是否足够,并将其整合到推理链中,形成真正的 Agentic RAG。
通过这些内容,我们可以看到 RAG 不再是一个静态的“补充知识”模块,而成为智能体体系中的关键能力,使智能体能够在面对复杂任务时主动检索、反思与修正,显著提升其知识覆盖度、准确性与可解释性。
最后唠两句
为什么AI大模型成为越来越多程序员转行就业、升职加薪的首选
很简单,这些岗位缺人且高薪
智联招聘的最新数据给出了最直观的印证:2025年2月,AI领域求职人数同比增幅突破200% ,远超其他行业平均水平;整个人工智能行业的求职增速达到33.4%,位居各行业榜首,其中人工智能工程师岗位的求职热度更是飙升69.6%。

AI产业的快速扩张,也让人才供需矛盾愈发突出。麦肯锡报告明确预测,到2030年中国AI专业人才需求将达600万人,人才缺口可能高达400万人,这一缺口不仅存在于核心技术领域,更蔓延至产业应用的各个环节。
那0基础普通人如何学习大模型 ?
深耕科技一线十二载,亲历技术浪潮变迁。我见证那些率先拥抱AI的同行,如何建立起效率与薪资的代际优势。如今,我将积累的大模型面试真题、独家资料、技术报告与实战路线系统整理,分享于此,为你扫清学习困惑,共赴AI时代新程。
我整理出这套 AI 大模型突围资料包【允许白嫖】:
-
✅从入门到精通的全套视频教程
-
✅AI大模型学习路线图(0基础到项目实战仅需90天)
-
✅大模型书籍与技术文档PDF
-
✅各大厂大模型面试题目详解
-
✅640套AI大模型报告合集
-
✅大模型入门实战训练
这份完整版的大模型 AI 学习和面试资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

①从入门到精通的全套视频教程
包含提示词工程、RAG、Agent等技术点

② AI大模型学习路线图(0基础到项目实战仅需90天)
全过程AI大模型学习路线

③学习电子书籍和技术文档
市面上的大模型书籍确实太多了,这些是我精选出来的

④各大厂大模型面试题目详解

⑤640套AI大模型报告合集

⑥大模型入门实战训练

如果说你是以下人群中的其中一类,都可以来智泊AI学习人工智能,找到高薪工作,一次小小的“投资”换来的是终身受益!
应届毕业生:无工作经验但想要系统学习AI大模型技术,期待通过实战项目掌握核心技术。
零基础转型:非技术背景但关注AI应用场景,计划通过低代码工具实现“AI+行业”跨界。
业务赋能 突破瓶颈:传统开发者(Java/前端等)学习Transformer架构与LangChain框架,向AI全栈工程师转型。
👉获取方式:
有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

更多推荐


所有评论(0)