Agent概念、技术及应用
文章目录
agent认知与原理分析
大语言模型可以接受输入,可以分析&推理、可以输出文字、代码媒体。然而,其无法像人类一样,拥有规划思考能力,运用各种工具与物理世界互动,以及拥有人类的记忆能。
AI Agents是基于LLM的能够自主理解、自主规划决策、执行复杂任务的智能体。
Agent的设计目的是为了处理那些简单的语言模型可能无法直接解决的问题,尤其是当这些任务涉及到多个步骤或者需要外部数据源的情况。
Agent流程图

规划Planning
智能体会把大型任务分解为子任务,并规划执行任务的流程;智能体会对任务执行的过程进行思考和反思,从而决定是继续执行任务,或判断任务完结并终止运行。
规划,可以理解为观察和思考,如果人类来类比,当我们接到一个任务,我们的思维模式可能:
1、思考怎么完成
2、审视已有工具,以及如何使用工具
3、把任务拆分成子任务
4、执行任务时,进行反思和完善,吸取教训以完成未来的不住
5、执行过程中思考任务何时终止
子任务分解
通过LLM使得智能体可以把大型任务分解为更小的、更可控的子任务,从而能够有效完成复杂的任务。
思维链(Chain of Thoughts,CoT)
思维链已经是一种比较标准的提示技术,能显著提升LLM完成复杂人物的效果。当我们对LLM这样要求‘think step by step’,会发现LLM会把问题分解成多个步骤,一步一步思考和解决,能使得输出的结果更加准确。是一种线性的思维方式。
思维树(Tree of Thoughts,ToT)
对Cot的进一步扩展,在思维链的每一步,推理出多个分支,拓扑展开成一棵思维树。使用启发式方法评估每个推理分支对问题解决的贡献。选择搜索算法,使用广度优先搜索BFS或深度优先搜索DFS等算法来探索思维树,并进行前瞻和回溯。
反思与改进
Agent对过去的行动进行自我批评和反思,从错误中学习并改进未来的步骤,从而提高最终结果的质量。
在实际任务中,试错是不可避免的,而自我反思在这个过程中起着至关重要的作用。它允许Agent通过改进过去的行动决策和纠正以前的错误来进行迭代改进。
反思是Agent对事情进行更高层次、更抽象思考的结果。反思是周期性生成的,当Agent感知到的最新事件的重要性评分之和超过一定阈值时,就会生成反思。这可以类比为我们的成语“三思而后行”,做重大决策的时候,我们会反思自己先前的决策。
ReAct框架
《ReAct: Synergizing Reasoning and Acting in Language Models》这篇论文提出一种用于增强大型语言模型的方法,它通过结合推理(Reasoning)和行动(Acting)来增强
推理和决策的效果。
参考:ReAct: Synergizing Reasoning and Acting in Language Models
上图案例分析:
- 标准Standard:没有提供任何推理过程或外部交互,直接给出答案。
- 仅推理Reason only:尝试通过逐步推理来解决问题,但没有与外部环境交互来验证信息。
- 仅行动Act only:通过与外部环境(如维基百科)的一系列交互来获取信息,尝试多次搜索,但缺乏推理支持,未能综合这些观察结果后得出正确答案。
- ReAct:组合推理和行动。首先通过推理确定搜索Apple Remote(苹果遥控器),并从外部环境中观察结果。随着推理的深入,识别出需要搜索Front Row(软件)。在几轮交互后,通过进一步推理,准确得出答案“键盘功能键”。

记忆Memory
记忆:
短期记忆,是指在执行任务的过程中的上下文,会在子任务的执行过程产生和暂存,在任务结束后被清空。
长期记忆是长时间保留的信息,一般是指外部知识库,通常用向量数据库来存储和检索。
生活中的记忆机制
- 感觉记忆:通常只持续几秒钟。记忆的最早阶段,提供在原始刺激结束后保留感觉信息(视觉、听觉等)的印象的能力。
- 短期记忆:一种持续时间较短的记忆。能够暂时存储和处理有限数量的信息。例如记住一个电话号码直到拨打结束。
- 长期记忆:一种持续时间较长的记忆,可以存储大量信息,从几分钟到一生。长期记忆进一步可以分为显性记忆和隐形记忆。显性记忆,可以有意识地回忆和表达信息,显性记忆又可以分为情景记忆(经历的具体事件)和语义记忆(一般知识概念)。隐形记忆,通常是无意识的,涉及技能和习惯,如骑自行车或打字。
智能体中的记忆机制
- 形成记忆:大模型在大量包含世界知识的数据集上进行预训练。在预训练中,大模型通过调整神经元的权重来学习理解和生成人类语言,这可以被视为”记忆“的形成过程。通过使用深度学习和梯度下降等技术,大模型可以不断提高基于预测或生产文本的能力,进而形成世界记忆或长期记忆。
- 短期记忆:在当前任务执行过程中所产生的信息,比如某个工具或者某个子任务执行的结果,会写入短期记忆中。记忆在当前任务过程中产生和暂存,在任务完结后被清空。
- 长期记忆:长时间保留的信息。一般是指外部知识库,通常用向量数据库来存储和检索。
工具Tools/Toolkits
为智能体配备工具API。
Agent可以通过学习调用外部API来获取模型权重中所缺少的额外信息,这些信息包括当前信息、代码执行能力和访问专有信息源等。这对于预训练后难以修改的模型权重来说是非常重要的。
执行Action
根据规划和记忆来实施具体行动,这可能会涉及到与外部世界的互动或通过工具来完成任务。
案例
场景
假设有一个智能家居系统,任务是根据家庭成员的需求调节室内环境。
感知
- 家庭成员通过语音助手说:“我感觉有点冷,能不能把温度调高一些?”
- 智能家居系统通过语音识别和情感分析技术“感知”到用户觉得房间温度太低,需要提高温度。
规划
- 系统根据用户的需求,规划下一步的行动,决定如何让调节房间温度。
- 系统可能会制定以下计划:
1、检查当前的室内温度
2、根据用户的偏好和当前温度决定升高几度合适
3、调整温度设置,并告知用户
行动
- 系统执行计划的行动,首先检查当前温度,例如发现室温是20℃。
- 根据用户的偏好,将温度挑高的23℃,并通过语音助手反馈给用户:“我已经将温度提高到23℃,请您稍等,温度将逐渐上升。”
观察
- 系统观察房间温度的变化,以及用户的反馈。如果用户在几分钟后再次说“现在温度刚刚好”,系统会感知到环境调节成功。
- 如果用户还觉得冷,系统可能会调整计划,进一步调高温度。
循环
- 在每个阶段,智能家居系统都可能根据环境变化和用户反馈调整操作。例如,如果调高温度后用户依然觉得冷,系统会重新规划,进一步调整温度设置。
- 通过这一系列的感知、规划、行动和观察,智能家居系统能够动态响应家庭成员的需求,不断调整室内环境,直到用户感觉舒适为止。
第一个agent代码实例
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain_community.agent_toolkits.load_tools import load_tools
from dotenv import load_dotenv
load_dotenv()
#定义llm
llm = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,#是否打印日志
)
print(agent.run("问题"))
在 LangChain 中,agent 参数用于指定代理(Agent)的类型,它决定了代理如何与工具交互、如何推理以及如何规划行动步骤。“zero-shot-react-description” 是其中一种类型,代表零样本 ReAct 代理(Zero-shot ReAct Agent),其核心特点如下:
ReAct 框架:结合推理(Reasoning)和行动(Acting),代理在每一步先思考(观察当前状态、推理下一步该做什么),然后执行一个动作(调用工具),最后观察结果并继续循环,直至得出最终答案。
零样本(Zero-shot):意味着代理不需要针对特定任务的示例或微调,仅凭工具的描述和当前问题就能决定使用哪个工具以及如何使用。
描述驱动:代理会读取每个工具的描述(即 tool.description),根据问题与描述的匹配程度来选择工具,因此工具的描述质量直接影响代理的表现。
如何使用工具包
参考:https://python.langchain.com/v0.2/docs/integrations/tools/
Dall-E
参考:
https://python.langchain.com/v0.2/docs/integrations/tools/dalle_image_generator/#run-as-a-chain
from langchain_community.chat_models import ChatOpenAI
from dotenv import load_dotenv
load_dotenv()
llm = ChatOpenAI(
temperature=0,
model="gpt-4",
)
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain.agents import initialize_agent
tools = load_tools("dalle-image-generator")
agent = initialize_agent(
tools,
llm,
agent="zero-shot-react-description",
verbose=True
)
output = agent.run("图片描述")
给Agent添加记忆
memory = ConversationBUfferMemory(
memory_key="chat_history",
return_messages=True
)
return_messages 参数控制聊天历史返回的格式:
当设置为 True 时,内存组件在加载聊天历史时会以消息对象列表的形式返回(例如 [HumanMessage(…), AIMessage(…)])。
当设置为 False(默认值)时,返回的是将这些消息拼接成的单个字符串(例如 “Human: …\nAI: …”)。
agent技术框架
其他Agent认知框架
Plan-and-Execute
计划与执行框架侧重于先规划一系列的行动,然后执行。这个框架可以使大模型能够综合考虑任务的多个方面,然后按照计划进行行动。应用在比较复杂的项目管理中或者需要多步决策的场景下会比较合适。
Replan观察子任务状态,未完成生成新的计划。
from langchain_openai import ChatOpenAI
from langchain_expermential.pan_and_execute import PlanAndExecute,load_agent_execute,load_chat_planner
from langchain import SerpAPIWrapper
from langchain import LLMMathChain
from dotenv import load_dotenv
load_dotenv()
# 配置API密钥和基础URL
llm = ChatOpenAI()
# https://serpapi.com/dashboard
#创建工具
search = SerpAPIWrapper()
llm_math_chain = LLMMathChain(llm=llm,verbose=True)
#定义工具列表
tools = [
Tool(
name="Search",
func=search.run,
description="用于回答关于当前事件的问题"
),
Tool(
name=”Calculator“,
func=llm_math_chain.run,
description="用于计算或解决问题"
)
]
#加载规划器和执行器
planner = load_chat_plaaner(llm)
execute = load_agent_executor(llm,tools,verbose=True)
#创建Plan and execute代理
agent = PlanAndExecute(planner=planner,executor=executor,verbose=True)
#运行代理解决实际问题
print(ahent.run("问题"))
SerpAPIWrapper 是 LangChain 社区提供的一个实用工具类,用于封装 SerpAPI 服务。SerpAPI 是一个第三方 API,可以通过传入搜索查询(如 Google 搜索关键词)返回结构化的搜索结果(例如标题、链接、摘要等)。该包装器简化了与 SerpAPI 的交互过程。
无法验收自己的回答,从而出现self-ask
Self-Ask
自问自答框架允许大模型对自己提出问题并回答,来增强对问题的理解以提高回答质量,这个框架在需要深入分析或者提供创造性解决方案下可以比较合适,例如创意写作。
import os
from langchain import hub
from langchain.agents import AgentExecutor, create_self_with_search
from langchain_community.tools.tavily_search import TavilyAnswer
from dotenv import load_dotenv
load_dotenv()
from langchain_fireworks import Fireworks
llm = Fireworks(
#https://fireworks.ai/account/billing
api_key=os.getenv("FIREWORKS_API_KEY"),
model="accounts/firworks/models/llama-v3p1-405b-instruct",#免费
max_tokens=256)
tools = [TavilyAnswer(max_results=1,name="Intermediate Answer",tavily_api_key=os.getenv("TAVILY_API_KEY"))]
prompt = hub.pull("hwchase17/self-ask-with-search")
print(prompt)
agent = create_self_ask_with_search_agent(llm,tools,prompt)
agent_executor = AgentExecutor(agent=agent,tools=tools,verbose=True,handle_parsing_errors=True)
print(agent_executor.invoke({"input":"问题"}))
Thinking and Self-Refection
思考并自我反思框架主要用于模拟和实现复杂决策过程,通过不断自我评估和调整,使系统能够学习并改进决策过程,从而在面对复杂问题时做出更加有效的决策。

ReAct框架
在langchain使用Agent中,我们重点需要理解以下4个元素:
1、llm:提供逻辑的引擎,负责生成预测和处理输入
2、prompt:负责知道模型,形成推理框架
3、tools:外部工具的使用,包含数据增强、清洗、搜索引擎、api等等
4、Agent Executor:负责调用合适的外部工具,并管理整个流程
# 导入环境变量
from dotenv import load_dotenv
load_dotenv()
# 初始化大模型
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model='gpt-4-turbo-preview',temperature=0.5)
# 设置工具
from langchain.prompts import PromptTemplate
template = ('''
'尽你所能用中文回答以下问题,如果能力不够你可以使用以下工具:\n\n'
'{tools}\n\n
Use the following format:\n\n'
'Question: the input question you must answer\n'
'Thought: you should always think about what to do\n'
'Action: the action to take, should be one of [{tool_names}]\n'
'Action Input: the input to the action\n'
'Observation: the result of the action\n'
'... (this Thought/Action/Action Input/Observation can repeat N times)\n'
'Thought: I now know the final answer\n'
'Final Answer: the final answer tothe original input question\n\n'
'Begin!\n\n'
'Question: {input}\n'
'Thought: {agent_scratchpad}'
'''
)
prompt = PromptTemplate.from_template(templat)
#初始化Agent
from langchain.agents import create_react_agent
agent = create_react_agent(llm.tools,prompt)
#构建AgentExecutor
from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(agent=agent,
tools=tools,
handle_parsing_errors=True,
verbose=True)
#执行AgentExecutor
agent_executor.invoke({"input":"""目前市场上玫瑰花的一般进货价格是多少?\n如果我在此基础上加价5%,应该如何定价?"""})

‘Thought: {agent_scratchpad}’ 是在构建 ReAct 风格 Agent 的提示模板时使用的占位符。
agent_scratchpad 是一个特殊变量,它会动态填充 Agent 到目前为止的中间思考与行动记录(即之前的 Thought、Action、Observation 循环)。
作用:让 Agent 能够“记住”自己已经执行过的步骤,从而在决定下一步行动时保持上下文连贯,避免重复或迷失。
在提示中的位置:通常放在提示末尾,引导 Agent 输出新的思考(Thought),例如:
你之前的操作记录:
{agent_scratchpad}
Thought: // 这里模型将生成新的思考
当实际运行时,{agent_scratchpad} 会被替换为类似这样的内容:
Thought: 用户问天气,我需要查询工具。
Action: weather_search[北京]
Observation: 北京今天晴,20℃。
然后模型接着输出下一个 Thought。
create_react_agent的tools:构建Agent的思维提示。
Agent本身是一个由LLM驱动的决策模块,它需要知道”我能使用哪些工具“,以便在思考时规划出合适的动作Action。
传入的tools会被转换成描述文本,嵌入到prompt中,让LLM知道每个工具的功能、名称、参数格式。
AgentExecutor中的tools:为了实际执行工具调用。
AgentExecutor负责运行循环:当Agent输出一个Action(比如要调用某个工具),Executor会从传入的tools列表中找到对应的工具函数并执行,然后把结果Observation返回给Agent,继续下一轮思考。
handle_parsing_errors
作用:当Agent输出的内容不符合预期格式(比如没有按照Thought:…Action:…的格式)时,Langchain默认会抛出解析异常。
设置为True后,它会捕获这个异常,并将错误信息作为Observation返回给Agent,让Agent有机会修正输出,而不是直接奔溃。
prompt
prompt参数是一个字符串模板,定义了Agent如何思考、行动的系统指令。
通常包含:
1、对Agent角色的描述
2、工具列表的占位符(如{tools}))
3、工具的名称和描述的格式化方式
4、输出格式要求(比如必须包含Thought:、Action:、Final Answer:等)
5、一个特殊占位符{agent_scratchpad},用来记录之前的思考过程
tools
tools=可调用对象(函数)+描述信息
在langchain中,工具不仅仅是函数,它还额外携带了元信息,让LLM能够理解:
1、名称name:LLM通过名字来指定要调用的工具
2、描述description:说明工具的功能、何时使用,帮助LLM做出正确选择
3、参数模式args_schema:定义函数需要的参数及其类型,以便LLM生成符合格式的输入(通常是JSON)
如何定义一个Tool?
通常有两种方式:
1、使用@tool装饰器(简洁)
from langchain.tools import tool
@tool
def search(query:str) -> str:
"""查询搜索引擎并返回结果"""
#函数逻辑
return f'搜索结果:{query}'
2、使用Tool类
from langchain.tools import Tool
def search_func(query: str) -> str:
"""查询搜索引擎并返回结果"""
#函数逻辑
return f'搜索结果:{query}'
search_tool = Tool(
name="search",
func=search_func,
description="查询搜索引擎并返回结果")
在 Agent 中 tools 如何被使用?
LLM 看到的不是函数代码,而是工具的描述文本(由 name、description、args_schema 生成)。
例如:
Search: 查询搜索引擎并返回结果。
参数:{{"query": {{"type": "string"}}}}
LLM 在思考后会输出类似 Action: Search[今天的天气],表示要调用 Search 工具,参数是 “今天的天气”。
AgentExecutor 解析这个指令,找到名为 Search 的工具,执行其 func(即你定义的函数),并将返回值作为 Observation 交给 LLM 继续推理。
Function calling函数调用
Function calling是大语言模型(LLM,如OpenAI的GPT系列)提供的一种结构化输出能力,允许模型在生成文本的同时,输出一个结构化的“调用请求”,用于触发外部工具或API。
Function calling 是实现 Tool 调用的一种高效方式,与 ReAct 模式(通过文本生成 Action)相比:
ReAct:模型通过输出 Action: tool_name[input] 这样的文本来表示调用,需要额外解析。
Function calling:模型原生支持结构化输出,调用意图和参数直接以 JSON 格式返回,解析更可靠、效率更高。
# 定义函数描述
functions = [
{
"name": "get_weather",
"description": "获取指定地点的天气",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名称"}
},
"required": ["location"]
}
}
]
# 用户提问
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "北京天气如何?"}],
functions=functions
)
# 模型可能返回 function_call
if response.choices[0].message.get("function_call"):
# 执行函数,拿到结果后再次调用模型生成最终回答
...
通过LlamaIndex实现ReAct RAG Agnet
特点:适用自己的数据、更好干预
LlamaIndex是一个专门为RAG(检索增强生成)应用设计的数据框架。核心目标是简化连接大语言模型LLM与私有外部数据的过程。
LlamaIndex能轻松将各种数据源(如PDF、数据库、API)加载进来,并构建成可供LLM查询的“索引”,从而让LLM在回答问题时能够参考这些数据。
主要功能
1、数据连接器Connectors:可以从超过100种数据源中读取数据
2、索引构建Indexing:将数据切分为块Chunks,并生成向量嵌入,建立索引以便快速检索
3、查询引擎Query Engine:提供高级接口,能够根据用户问题从索引中检索最相关的信息,并结合LLM生成答案
4、与Agent集成:LlamaIndex可以作为工具提供给ReAct Agent使用。Agent可以自主决定何时调用LlamaIndex来查询数据库,从而实现更复杂的推理和行动(这就是“通过LlamaIndex实现ReAct RAG Agent”的含义)
#加载电商财报数据
from llama_index.core import SimpleDirectoryReader
from dotenv import load_dotenv
load_dotenv()
A_docs = SimpleDirectoryReader(
input_files=["./A.pdf"]
).load_data()
B_docs = SimplrDirectoryReader(
input_files=["./B.pdf"]
).load_data()
#从文档中创建索引
from llama_index.core import VectorStoreIndex
A_index = VectorStoreIndex.from_documents(A_docs)
B_index = VectorStoreIndex.from_documents(B_docs)
#持久化索引(保存到本地)
from llama_index.core import StorageContext
A_index.storage_context.persist(persist_dir="./storage/A")
B_index.storage_context.persist(persist_dir="./storage/B")
#从本地读取索引
from llama_index.core import load_index_from_storage
try:
storage_context = StorageContext.from_defaults(
persist_dir = "./storage/A"
)
A_index = load_index_from_storage(storage_context)
storage_context = StorageContext.from_defaults(
persist_dir = "./storage/B"
)
B_index = load_index_from_storage(storage_context)
index_loaded = True
except:
index_loaded = False
SimpleDirectoryReader 是 LlamaIndex 中一个非常基础且常用的数据加载器(Data Loader),它的作用是从本地文件夹中批量读取各类文档文件,并将它们转换为 LlamaIndex 可以进一步处理的数据格式(Document 对象)。
主要功能:
1、自动解析多种文件格式:支持常见的文本文件(.txt)、PDF(.pdf)、Word(.docx)、PowerPoint(.pptx)、Markdown(.md)、CSV、图片(通过 OCR 插件)等。
2、递归读取:默认会读取指定目录下的所有文件,也可以设置是否递归子文件夹。
3、自定义文件过滤:可以通过参数指定只读取某些后缀的文件,或排除某些文件。
agent策略分析与Parer解读
单agent系统与多agent系统
个性化agent应用定制
学习笔记来源:大模型课程
更多推荐



所有评论(0)