首先我们得知道什么是Agent?Agent 代理的核心思想是使用大语言模型来选择要采取的一系列动作,不过Agent 不是在开始前就把所有动作一次性全选好。而是不断观察结果、思考对策、采取行动的循环中,逐步接近目标。
1.先思考:根据现在的目标,决定第一步做什么动作。
2.去执行:调用工具把这个动作做了。
3.看结果:观察这个动作做完了是什么情况,比如查到了数据,或者报错了。
4.再思考:根据刚才的结果,再决定下一步该做什么动作

而大语言模型作为大脑只负责下命令,不负责亲自干活,比如它会喊 “去调用一下天气查询工具,参数是珠穆朗玛峰!” 但它自己是没有手和脚的,真正去跑腿、执行代码、调用接口的,是背后写好的程序代码或者其他工具,同时能够将一个工具的输出数据作为另一个工具的输入数据。最后它们把干完活的结果(比如珠穆朗玛峰今天0度)再拿回来汇报给大语言模型,模型看了结果后,再决定下一步怎么办。所以AI Agent 就是给大语言模型装上了手脚和记忆功能,让它不仅能思考,还能通过不断选择并指挥一系列动作,去帮你把事情办成。
1. Agent的基本使用
我们接下来构建一个具有两种工具的代理
1.在线工具
一种用于在线查找使用Tavily,当然也可以使用Firecrawl、Exa他们都差不多。
使用Tavily需要注册账号获取API密钥
https://tavily.com/
然后使用TavilySearchResults()来进行在线搜索
2.本地检索工具
一种用于查找加载到向量库索引中的数据。
加载网页数据
切分文档、初始化 Embedding 模型
构建 Chroma 向量库、创建检索器
接下来我们来用代码演示一个完整示例,
import os
from dotenv import load_dotenv
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_openai import ChatOpenAI
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain.agents import create_openai_functions_agent
from langchain.tools.retriever import create_retriever_tool
from langchain.agents import AgentExecutor
# 用于构建自定义 Prompt
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder# 加载环境变量
load_dotenv(verbose=True)# 1. 数据与向量库准备
loader = WebBaseLoader("https://www.163.com/dy/article/KR9ONNH00556IYVO.html")
docs = loader.load()
documents = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200
).split_documents(docs)api_key = os.getenv("QW_KEY")
api_url = os.getenv("QW_URL")
embedding_model = DashScopeEmbeddings(dashscope_api_key=api_key)vector = Chroma.from_documents(documents=documents,embedding=embedding_model,persist_directory="/Users/yuxl/3.Resources/Demo/llm/db/chroma"
)retriever = vector.as_retriever()# 包装成本地工具
retriever_tool = create_retriever_tool(retriever, "rate of unemployment_search", "搜索失业率相关数据")
# 创建联网搜索工具
search = TavilySearchResults()
# 组装工具箱
tools = [search, retriever_tool]# 2. LLM 初始化
llm = ChatOpenAI(api_key=api_key, base_url=api_url, model="qwen-turbo", temperature=0)# 3.自定义 Prompt,强制模型必须查资料
prompt = ChatPromptTemplate.from_messages([("system","你是一个严谨的AI助手。当前时间是2026年5月。\n""重要规则:对于任何关于事实、新闻、人物职位(特别是2024年以后)的问题,\n""你必须调用工具进行搜索!严禁直接使用你训练数据中的旧知识回答,因为那些知识已经过时了。"),("human", "{input}"),MessagesPlaceholder(variable_name="agent_scratchpad"),
])# --- 4. 组装 Agent (保持不变) ---
agent = create_openai_functions_agent(llm, tools, prompt)
agent_excutor = AgentExecutor(agent=agent, tools=tools, verbose=True) # verbose=True 已经在控制台输出详细日志了# --- 5. 执行与调试 ---
print("\n>>> 开始提问...")
result = agent_excutor.invoke({"input": "2026年正在任期的美国总统是谁?"})print("\n" + "="*50)
print("最终回答:", result['output'])
print("="*50)
核心的思路可以看下代码的流程图

2.常见核心Agent类型
在上面我们对agent一点点了解,并且使用create_openai_functions_agent 实现了一个简单的agent,接下来我们看下一些常见的agent分类。
1. OpenAI Functions Agent
现在用的 create_openai_functions_agent本质上就是在用 LangChain 的方式,调用 OpenAI 的 Function Calling函数调用机制。openai function call 是底层的能力,create_openai_functions_agent是 LangChain 对这一能力的封装.

我们把工具列表(函数名、参数结构、描述)交给模型。模型不再输出杂乱文本,而是直接返回一个结构化的 JSON 调用请求(如下面代码 {function: "query_name", arguments: {p_id: "1"}})。LangChain 拿到这个标准结构化输出,直接精准调用对应工具,再把结果喂回模型做下一步思考或最终回复。
OpenAI Functions Agent代码示例
import os
from dotenv import load_dotenvfrom langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.tools import Tool
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI# ======================
# 环境 & 工具
# ======================
load_dotenv()def query_name(p_id):return "当前用户为Vip用户" if p_id == "1" else Nonedef get_age(name):return "我的年龄是18岁" if name == "admin" else Nonetools = [TavilySearchResults(max_results=1),Tool(name="query_name", func=query_name, description="根据用户ID查询用户身份"),Tool(name="get_age", func=get_age, description="根据用户名查询年龄"),
]# ======================
# LLM & Prompt
# ======================
llm = ChatOpenAI(api_key=os.getenv("QW_KEY"),base_url=os.getenv("QW_URL"),model="qwen-plus"
)prompt = ChatPromptTemplate.from_messages([("system", "你是客服助手,必须使用工具回答问题。"),("user", "{input}"),MessagesPlaceholder(variable_name="agent_scratchpad"),
])# ======================
# Agent & Executor
# ======================
agent = create_openai_functions_agent(llm, tools, prompt)agent_executor = AgentExecutor(agent=agent,tools=tools,verbose=True,handle_parsing_errors=True
)# ======================
# 测试
# ======================
queries = ["请问id为1的姓名是什么?","请问admin的年龄是多少?","2026年5月15日是星期几?"
]for q in queries:res = agent_executor.invoke({"input": q})print(f"Q: {q}\nA: {res['output']}\n")
输出

2. ReAct Agent
ReAct Agent是什么意思?ReAct = Reason + Act(推理 + 行动),它并不是很多人说的一个会反省自己的智能体,而是一个固定格式的推理流程:
1.Thought(思考):我现在需要知道什么
2.Action(动作):我要调用哪个工具
3.Observation(观察):工具返回的结果
4.Thought(再思考)
5.Final Answer(最终回答)

典型应用举例
你问AI:" 2026 年 5 月 15 日是星期几?ReAct Agent会这样想:
1.Thought: 我不知道未来的日期,需要搜索
2.Action: GoogleSearch[2026年5月15日是星期几]
3.Observation: 2026年5月15日是星期五
4.Thought: 现在我有了答案
5.Final Answer: 2026年5月15日是星期五

其实它不会反思自己错了没,它只是 按模板一步步走,ReAct适合稳定场景,因为每一步都写得很清楚能看到,它用了什么工具,参数对不对,结果合不合理,可以描述解释也可调试 但它不是越用越聪明,大模型不会因为你用 ReAct就自动变聪明,学习 ≠ 权重更新,只是 prompt 更长。
ReAct Agent代码示例
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import osload_dotenv()# 初始化大模型:语言模型控制代理
llm = ChatOpenAI(api_key=os.getenv("QW_KEY"),base_url=os.getenv("QW_URL"),model="qwen-turbo")# 设置工具:加载使用的工具,serpapi:调用Google搜索引擎
tools = load_tools(["serpapi"], llm=llm, SERPAPI_API_KEY=os.getenv("SERPAPI_API_KEY"))prompt = hub.pull("hwchase17/react")agent = create_react_agent(llm, tools, prompt)# 创建 Agent 执行器
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)# 执行任务并打印结果
result = agent_executor.invoke({"input": "珠穆朗玛峰截止到2026年是多少米?用中文回答"})
print(result)
输出

3. Self-Ask with Search Agent
自问搜索代理是专门解决多跳推理问题的 AI 智能体框架。它先拆解问题,再调用搜索的策略,将复杂问题转化为一系列简单小问题,并利用搜索引擎获取准确事实,最终再合并出答案。核心工作原理就是模拟人类的推理过程,包含三个关键步骤:
1.问题拆解(Self-Ask):大模型(LLM)分析复杂问题,判断是否需要拆解,并生成第一个子问题。
2.工具调用(Search):Agent 自动调用搜索引擎,查询该子问题的答案。
3.迭代与整合:将搜索到的“中间答案”喂给模型,模型基于新信息提出下一个子问题,循环直至信息足够,输出最终答案。

典型应用举例
例如你向 AI 提问:”这周末想带女朋友去看那部评分最高的科幻片,哪家影院离我最近且票价最便宜?” ,如果是普通的搜索引擎,可能只会给你一堆零散链接。但拥有 Self-Ask with Search 能力的智能体,会在后台悄悄进行这样的内心推理:
1.第一轮追问与搜索
-
Follow up(内心追问):“现在(2026年5月)正在上映的、且评分最高的科幻电影到底是哪一部?”
-
Search(调用工具):自动去豆瓣或猫眼电影搜索“2026年5月 高分 科幻电影”。
-
Intermediate answer(获取中间答案):搜索结果反馈——目前口碑最好的是《星际穿越2》
2.第二轮追问与搜索
-
Follow up(内心追问):“我现在在武汉(基于你的地理位置),哪些电影院正在排片《星际穿越2》?”
-
Search(调用工具):调用地图或购票软件接口,搜索“武汉 电影院 排片 星际穿越2”。
-
Intermediate answer(获取中间答案):搜索结果反馈——光谷步行街的“xx影城”、街道口的“xx影城”都有排片。
3.第三轮追问与搜索
-
Follow up(内心追问):“这两家影院在这个周末的票价分别是多少?哪家更便宜?”
-
Search(调用工具):查询这两家影院本周六日的具体票价信息。
-
Intermediate answer(获取中间答案):万达影城 45元/张,群光影城 55元/张。
4.Final Answer整合回答
- “这周末评分最高的科幻片是《星际穿越2》。离你较近且票价最便宜的是光谷步行街的xx影城,票价为45元。”
可以看到Self-Ask Agent的特点,AI没有直接猜答案,而是像剥洋葱一样,把一个大问题拆解成了查电影 -> 查影院 -> 查价格三个小步骤,然后一步步搜索拿到证据,最后才拼凑出完美的答案。
Self-Ask Agent代码示例
import osfrom dotenv import load_dotenv
from langchain import hub
from langchain.agents import AgentExecutor, create_self_ask_with_search_agent
from langchain_community.tools.tavily_search import TavilyAnswer
from langchain_openai import ChatOpenAI
load_dotenv()
# 将初始化工具,让它提供答案而不是文档
tools = [TavilyAnswer(name="Intermediate Answer", description="Answer Search")]
# 初始化大模型
llm = ChatOpenAI(api_key=os.getenv("QW_KEY"),base_url=os.getenv("QW_URL"),model="qwen-turbo")# 获取使用提示 可以修改此提示 提示词模版
prompt = hub.pull("hwchase17/self-ask-with-search")agent = create_self_ask_with_search_agent(llm, tools, prompt)
agent_exc = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
agent_exc.invoke({"input": "这周末想带女朋友去看那部评分最高的科幻片,哪家影院离我最近且票价最便宜? 中文回答"})
输出

可以看到结果,顿时是不是傻眼了,一直在Troubleshooting,这是因为Self-Ask的设计缺陷。它只会拆问题,不会判断何时停止,例如问武汉面积比长沙大多少?
1.武汉面积多少?
2.长沙面积多少?
3.两者相减
不过只要还有信息缺失 → 继续问自己新问题,没有那种够用了,可以结束了的判断规则和策略,Self-Ask当做扩展知识用来理解大模型是如何通过拆解问题来突破自身能力局限的 这个逻辑就行了,生产基本没人用,真要上线干活,得慎重考虑下,不然得翻车。
