大模型LLMs基于Langchain、Langgraph的Agent使用

写在前文

什么是Agent?

是一种能够感知环境、自主决策并采取行动以实现特定目标的智能程序或系统

是指一种能够模拟人类思考和行为来自动执行任务,以解决复杂问题的程序或系统;

以下是我个人理解,可能不太准确。

比如我们可以把Agent理解为是一个人,独立自己的一个有独立思考、行动能力的人,人的大脑是“规划模块”也有记忆功能,而人的眼睛、鼻子、耳朵是“感知模块”、人的手脚是“行动模块”,锄头、刀、勺子、叉子就是“工具模块”了。

也就是说,假如你有一个指令,比如你要计算“1+1等于几”。你把命令发给这个人也就是Agent,Agent的规划模块即这个人的大脑就会去规划他的行动---比如需要什么步骤才能完成任务?比如需要那些工具?需要怎么做才能得到结果?聪明的Agent也会根据其他信息去验证结果的准确性,然后把最准确的答案反馈给你。

如果把Agent比作一个人,所以在“1+1等于几”这个命令的驱动下,可能会发生如下步骤:

        1、你告诉这个人你需要计算1+1等于几。

        2、这个人Agent,拿到这个指令后,会去规划怎么才能完成这个命令。比如我需要用手(行动)去使用计算器(工具)才能计算,

        3、此刻你只有手,你是找不到计算器的,这时候你明白,需要眼睛(感知)去帮你找到你的计算器。

        4、但是光有感知和行动还是不够,你家很大,你不可能说为了找一个计算器,把整个家翻出来吧?这就需要你的大脑的记忆来帮你找到计算器了。在你的记忆中,你知道计算器在哪里。

        5、但是有了记忆、有了眼睛、有了手,你依然不一定能拿到你的计算器,这个时候可能还需要脚(另外的行动),带你走过去。可能还需要梯子(额外的工具),带你爬上去...等等之类的。

        6、最终流程可能就是:你收到指令以后,经过大脑的分析,你需要计算器来获得答案,在你的记忆中,你的计算器在2楼的衣柜顶部,这个时候你就需要一个梯子工具、手脚行动、眼睛感知、大脑记忆模块来共同行动你才能拿到计算器。也就是说,首先你通过记忆知道你的梯子在三楼,然后控制你脚根据眼睛的视线感知,你去三楼用手搬一个梯子到二楼的衣柜旁边,然后架上梯子去拿衣柜顶部的计算器,再用手输入你的数字计算获得最终答案。获得答案后,你通过视觉感知,在通过嘴巴喉咙的行动模块告诉发给你命令的这个人。

当然,聪明的智能体,他可能会通过其他信息,来验证这个答案是否正确,而不仅仅是根据指令去完成任务...。

Agent就一个创建Agent(人)+Agent执行器(手脚);

 agent类型

--- 好像在传统定义Agent的时候会用到,但是在使用langgraph的时候不会用到~~~~
    会话类型CONVERSATIONAL_REACT_DESCRIPTION:其他代理通常优化用于查找最佳响应的工具,但在对话环境中这并不理想,因为您可能希望代理能够与用户进行聊天。
    聊天模型CHAT_CONVERSATIONAL_REACT_DESCRIPTION:使用聊天模型创建对话代理,而不是 LLM。
    结构化工具聊天STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION:
    OPENAI函数OPENAI_FUNCTIONS:
    自问自答带搜索SELF_ASK_WITH_SEARCH:

创建方法

1、使用 create_tool_calling_agent 创建 agent 、使用 AgentExecutor 创建 Agent_Executor
2、使用 create_openai_tools_agent 创建 agent 、使用 AgentExecutor 创建 Agent_Executor
3、使用 initialize_agent 创建 agent
4、使用 langchain 的 create_react_agent 创建 agent 和 executor
5、使用 langgraph 的 create_react_agent 创建 agent
6、使用 langgraph 的 create_tool_calling_executor创建Agent --- 工作中推荐
7、原生ReActAgent --- 了解

初始化

初始化工具包

其他方法,见上一篇

os.environ['serpapi_api_key'] = 'xxxxxxxx'
os.environ["TAVILY_API_KEY"] = 'tvly-xxxxxxxx'

# 提供了很多常用的网站,比如天气网站,可以查询到很多天气
tavily = TavilySearchResults(max_results=2)

# 提供了搜索功能
serpApi = SerpAPIWrapper()


@tool("xiang_u")
def xiang_U(a: int, b: int) -> int:
    """ a和b参数需要“U”时才会使用
    Args:
        a: First integer
        b: Second integer
    """
    print(f'调用了U函数:[{a},{b}]')
    return a + b


@tool("xiang_t")
def xiang_T(a: int, b: int) -> int:
    """ a和b参数需要“T”时才会使用
    Args:
        a: First integer
        b: Second integer
    """
    print(f'调用了T函数:[{a},{b}]')
    return a * b


@tool("add", return_direct=True)
def add_(a: int, b: int) -> int:
    """Add two integers.

    Args:
        a: First integer
        b: Second integer
    """
    return a + b


@tool("multiply", return_direct=True)
def multiply_(a: int, b: int) -> int:
    """Multiply two integers.

    Args:
        a: First integer
        b: Second integer
    """
    return a * b


@tool("tavily", return_direct=True)
def tavily_(question: str):
    """
    只有需要了解某个地方和某日的天气时才会调用这个工具
    :return:
    """
    print(f"调用天气工具了...{question}")
    return tavily.run(question)


@tool("serpApi", return_direct=True)
def serpApi_(question: str):
    """
    只有需要了解实时信息或者不知道的事情的时候才会使用这个工具
    :return:
    """
    print(f"调用搜索工具了...{question}")
    return serpApi.run(question)

初始化LLMs并与工具集合绑定

from typing import TypedDict, Annotated

from langchain.agents import create_tool_calling_agent, AgentExecutor, create_openai_tools_agent, initialize_agent, \
    AgentType
from langchain.memory import ConversationBufferMemory
from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableWithMessageHistory
from langgraph.checkpoint.memory import MemorySaver, InMemorySaver
from langgraph.graph import add_messages, StateGraph
from langgraph.prebuilt import create_react_agent, chat_agent_executor
from tensorboard.notebook import display

from utils import *


# 工具集合
tools = [add_, multiply_, tavily_, serpApi_, xiang_T, xiang_U]

# ### DK系列的好像都不支持tool调用,Qwen系有一部分不支持...
# #### llama 不支持调用 Tools ,所以此处报错...:does not support tools (status code: 400)
# 支持工具调用:部分Qwen(qwen2.5)、llama3.1:latest、llama3-groq-tool-use(这个好像是微调了...)、部分ChatGLM
llm = ChatOpenAI(base_url='https://open.bigmodel.cn/api/paas/v4/',
                          api_key='ءءءءء.ءءءء',
                          model='glm-4-plus',
                          temperature=0.8,
                          verbose=False)
### 绑定tools时是不会自动自行方法的,需要我们手动调用...
llm_with_tool = llm.bind_tools(tools)

原始调用Tools ---- 了解即可

就是在不结合Agent的时候调用工具生成文本的方法

def test01():
    from langchain_core.tracers import ConsoleCallbackHandler
    from langchain_core.messages import HumanMessage
    ### 原来绑定tools时是不会自动自行方法的,需要我们手动调用...
    llm_with_tool = llm.bind_tools(tools)
    query_0 = "2U8的结果是多少?"
    ai_msg = llm_with_tool.invoke(query_0, config={"callbacks": [ConsoleCallbackHandler()]})
    print(f"ai返回的消息:{ai_msg}")
    print(f"打印出要调用的工具方法:{ai_msg.tool_calls}")  # 打印出要调用的方法..。
    messages = [HumanMessage(content=query_0), ai_msg]
    for tool_call in ai_msg.tool_calls:
        # [{'name': 'jiemeng', 'args': {'question': '梦见了一条蛇'}, 'id': 'call_-8969341968746077052', 'type': 'tool_call'}]
        print(tool_call)
        selected_tool = {"add": add_,
                         "multiply": multiply_,
                         "xiang_u": xiang_U,
                         "xiang_t": xiang_T,
                         "tavily": tavily_,
                         "serpapi": serpApi_,
                         "jiemeng": jiemeng_
                         }[tool_call["name"].lower()]
        tool_msg = selected_tool.invoke(tool_call)
        messages.append(tool_msg)
        print(f"tool_msg返回的数据:{tool_msg}")
    print(f"最终结果:{llm_with_tool.invoke(messages)}")
    print("---------------原始使用---------------")
test01()

1、创建Agent:原生langchain创建一个agent --- 了解

关于提示词使用时,可以使用huggingface官方的,也可以使用自定义;官方的需要VPN下载。

原始的langchain创建agent,

        - 使用create_tool_calling_agent创建agent、

        - 使用AgentExecutor创建Agent_Executor

使用hub创建的提示词

def create_calling_agent_hub_prompt():
    """
    使用hub提示词模板
    :return:
    """
    from langchain import hub
    from langchain.agents import create_tool_calling_agent
    from langchain.agents import AgentExecutor

    prompt_hub_1 = hub.pull("hwchase17/openai-functions-agent")
    # [SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')),
    #  MessagesPlaceholder(variable_name='chat_history', optional=True),
    #  HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')),
    #  MessagesPlaceholder(variable_name='agent_scratchpad')]
    print(f"使用hub获得的提示词:[{prompt_hub_1.messages}]")

    agent_hub_prompt_1 = create_tool_calling_agent(
        llm=llm,
        tools=tools,
        prompt=prompt_hub_1
    )
    agent_hub_prompt_executor_1 = AgentExecutor(
        agent=agent_hub_prompt_1,
        tools=tools,
    )
    print(agent_hub_prompt_executor_1.invoke({"input": "成都天气今天怎么样?"})['output'])

 使用自定义提示词

def create_calling_agent_custorm_prompt():
    """
    使用自定义提示词模板创建Agent
    :return:
    """
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.prompts import MessagesPlaceholder
    from langchain.agents import create_tool_calling_agent
    from langchain.agents import AgentExecutor
    prompt_chat_custom_1 = ChatPromptTemplate.from_messages(
        [
            ("system",
             """
             你是我定义的一个工具,一个搜索实时信息的工具
             这代表着如果有你不知道的信息,你都可以使用它们获得最准确的结果。
             如果工具也无法处理,请直接回复“无法处理”即可,切勿过多修饰。
             """),
            ("human", "{text}"),
            # 添加,不然报错ValueError: Prompt missing required variables: {'agent_scratchpad'}
            # 等价于("placeholder", "{agent_scratchpad}")....("placeholder", "{其他...参数}"),
            MessagesPlaceholder(variable_name='agent_scratchpad'),

        ]
    )
    agent_custom_chat_1 = create_tool_calling_agent(
        llm=llm,
        tools=tools,
        prompt=prompt_chat_custom_1
    )
    agent_custom_chat_executor_1 = AgentExecutor(
        agent=agent_custom_chat_1,
        tools=tools,
    )
    # print(f"使用ChatPromptTemplate获得的提示词:[{prompt_chat_custom_1}]")
    print(f"{agent_custom_chat_executor_1.invoke({"text": "1U8等于多少?"})}")

2、创建Agent --- Langchain create_openai_tools_agent创建 

即:通过create_openai_tools_agent创建Agent,通过AgentExecutor去创建Agent的执行器

def create_openai_tools_agent():
    # ### 使用自定义提示词模板创建Agent
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.prompts import MessagesPlaceholder
    from langchain.agents import create_openai_tools_agent
    from langchain.agents import AgentExecutor
    prompt_chat_custom_1 = ChatPromptTemplate.from_messages(
        [
            ("system",
             """
             你是我定义的一个工具,一个搜索实时信息的工具
             这代表着如果有你不知道的信息,你都可以使用它们获得最准确的结果。
             如果工具也无法处理,请直接回复“无法处理”即可,切勿过多修饰。
             """),
            ("human", "{text}"),
            # 添加,不然报错ValueError: Prompt missing required variables: {'agent_scratchpad'}
            # 等价于("placeholder", "{agent_scratchpad}")....("placeholder", "{其他...参数}"),
            MessagesPlaceholder(variable_name='agent_scratchpad'),

        ]
    )
    prompt_2 = prompt_chat_custom_1
    agent_openai_2 = create_openai_tools_agent(
        llm=llm,
        tools=tools,
        prompt=prompt_2,
    )

    agent_executor_2 = AgentExecutor(
        agent=agent_openai_2,
        tools=tools,
    )
    print(f"{agent_executor_2.invoke({"text": "1T7等于多少"})['output']}")

3、创建Agent --- 老版本使用initialize_agent创建(过时)

# 此处使用ZERO_SHOT_REACT_DESCRIPTION可能会报错:ValueError: ZeroShotAgent does not support multi-input tool add.,
# 原因是工具中的参数是输入了多个参数:比如 def add_(a: int, b: int)
# agent可选:ZERO_SHOT_REACT_DESCRIPTION、REACT_DOCSTORE、SELF_ASK_WITH_SEARCH、CONVERSATIONAL_REACT_DESCRIPTION、CHAT_ZERO_SHOT_REACT_DESCRIPTION、CHAT_CONVERSATIONAL_REACT_DESCRIPTION、STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION、OPENAI_MULTI_FUNCTIONS、OPENAI_FUNCTIONS 具体可以参考:AgentType类,但是,,这种方法是过时的,官方推荐的是通过“LangGraph”来创建Agent,LangGraph中好像不太需要AgentType
def create_initialize_agent():
    from langchain.agents import initialize_agent
    from langchain.agents import AgentType
    agent = initialize_agent(  # 过时
        tools=tools,
        llm=llm,
        agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
        # verbose=True
    )
    # print(f"{agent.run({"input": {"text": "1U8等于多少"}})}")  # 过时了,使用invoke
    # print(f"create_initialize_agent:{agent.invoke({"input": "1T8等于多少"})}")
    print(f"create_initialize_agent:{agent.invoke({"input": "1U8等于多少"})['output']}")

4、创建Agent --- 使用create_react_agent创建

create_react_agent有两个:
    - langchain.agents.create_react_agent
    - langgraph.prebuilt.create_react_agent

如果我们使用langchain.agents的create_react_agent话,那么我们需要再提示词中添加如下参数: tools、tool_names、input、agent_scratchpad...

使用langchain.agents.create_react_agent

def create_langchain_react_agent():
    """
    如果要使用langchain.agents.create_react_agent的话,那么必须传递进:
    tools、tool_names、input、agent_scratchpad这几个参数
    流程为:通过create_react_agent获取Agent,通过AgentExecutor获取执行器,然后再用执行器.invoke()
    :return:
    """
    from langchain.agents import create_react_agent
    from langchain import hub
    # prompt = hub.pull("hwchase17/react")  # 示例prompt 标准的ReAct模板

    # 下面是翻译出来的 --- 使用这种,可能会出现问题..最好的办法还是使用hub.pull("hwchase17/react")直接使用
    prompt = PromptTemplate.from_template("""
    尽你所能回答以下问题。
        您可以访问以下工具: \n\n{tools}\n\n
        使用以下格式:\n\n
        Question: 输入的问题\n
        Thought: 你的思考过程
        Action: 要采取的操作应该是〔{tool_names}〕之一\n
        Action Input: 工具输入\n
        Observation:  工具返回结果\n
        ...(重复思考/行动/工具输入/观察 可以重复N次)\n
        Thought: 我现在知道最终答案了\n
        Final Answer: 最终结论\n\n
        Begin!\n\n
        Question: {input}\n
        Thought: {agent_scratchpad}
    """)
    # 创建Agent
    langchain_react_agent = create_react_agent(llm, tools, prompt)

    # 创建执行器
    from langchain.agents import AgentExecutor
    agent_executor = AgentExecutor(
        agent=langchain_react_agent,
        tools=tools,
        max_iterations=3,
        handle_parsing_errors=True  # 发生错误时,则错误将作为观察结果发送回LLM。
    )
    result = agent_executor.invoke({"input": "1U8等于多少?"}, config=config)
    print(result)

使用langgraph.prebuilt.create_react_agent --- 不带提示词

def create_langgraph_no_prompt_react_agent():
    """
    不带提示词
    是langgraph.prebuilt不是langchain.agents
    """
    from langgraph.prebuilt import create_react_agent
    agent_langgraph_no_prompt_4 = create_react_agent(
        model=llm,
        tools=tools
    )
    from langchain_core.messages import HumanMessage
    # result = agent_langgraph_no_prompt_4.invoke({"messages": [HumanMessage(content="what is 1U8?")]})
    result = agent_langgraph_no_prompt_4.invoke({"messages": "1U8等于多少?"}, config=config)
    print(f"HumanMessage数据体发送:{result["messages"][-1].content}")
    # messages_4 = agent_langgraph_no_prompt_4.invoke({"messages": [("human", "1U8等于多少")]})
    # print(f"human字符串发送:{messages_4}")
    #
    # new_query_result = agent_langgraph_no_prompt_4.invoke(
    #     {"messages": messages_4["messages"] + [("human", "9T1呢?")]}
    # )
    # print(f"new query:{new_query_result["messages"][-1].content}")

使用langgraph.prebuilt.create_react_agent --- 带字符串提示词 

def create_langgraph_str_prompt_react_agent():
    """带字符串提示词"""
    from langgraph.prebuilt import create_react_agent
    system_message_str_4 = """
        你是一个工具助手
    """
    agent_langgraph_str_prompt_4 = create_react_agent(model=llm, tools=tools, prompt=system_message_str_4)
    # print(f"带字符串提示词:{agent_langgraph_str_prompt_4.invoke({"messages": [("human", "1U8等于多少?")]})["messages"][-1].content}")
    print(f"带字符串提示词:{agent_langgraph_str_prompt_4.invoke({"messages": "1U8等于多少?"})["messages"][-1].content}")

使用langgraph.prebuilt.create_react_agent --- 带对象提示词 

即创建的带有role(System/human/AI)之类的提示词

def create_langgraph_obj_prompt_react_agent():
    """带对象提示词"""
    from langchain_core.messages import SystemMessage
    from langgraph.prebuilt import create_react_agent
    system_message_str_4 = """
           你是一个助手
       """
    system_message_object_4 = SystemMessage(content=system_message_str_4)
    agent_langgraph_object_prompt_4 = create_react_agent(model=llm, tools=tools, prompt=system_message_object_4)
    print(f"带object提示词:{agent_langgraph_object_prompt_4.invoke(
        {"messages": [("human", "1T8等于多少?")]}
    )["messages"][-1].content}")

5、创建Agent:使用create_tool_calling_executor创建

"""
推荐使用...
langgraph.prebuilt.chat_agent_executor.create_tool_calling_executor和langgraph.prebuilt.create_react_agent的区别:
create_react_agent:基于ReAct框架
    模式:采用经典的 ReAct(Reason + Act) 模式,代理通过显式的推理步骤(Thought)和工具调用(Action)循环解决问题。
    流程:每个步骤生成文本格式的思考(如 "Thought: 我需要查询天气;Action: search_tool(...)"),执行器解析动作、调用工具、返回结果(Observation),循环直到任务完成。
    适用场景:教学或调试场景,需要观察代理的思考过程。使用不支持结构化输出的模型(如某些开源LLM)。
create_tool_calling_executor:工具调用执行器。基于模型原生工具调用能力。
    模式:直接利用模型原生的结构化工具调用能力(如OpenAI的tool_calls),无需显式生成思考步骤。
    流程:模型直接返回工具名及参数(结构化数据),执行器调用工具并返回结果,模型根据结果决定下一步,流程更简洁。
    适用场景:生产环境的高效工具调用,适合支持结构化输出的模型(如结合GPT-4处理多步骤用户请求)。需要减少Token消耗、提升响应速度的场景。

 create_react_agent            |  create_tool_calling_executor
需要自定义提示模板和输出解析器    |      依赖模型原生能力,实现更简单
需处理中间步骤(思考、动作分离)  |          直接执行工具调用
适用于所有模型(如开源LLM)      |   通常需特定模型支持(如GPT-4)
ReAct代理:
    - 要求模型生成的文本符合Thought/Action/Observation格式,对模型输出规范性要求较高。兼容性广,可用于任何能生成此格式文本的模型(如开源LLM)。
    - 需要解析非结构化文本,处理潜在的格式错误,流程步骤更多。适合需要人类可读的中间推理步骤的场景。
Tool Calling执行器:
    - 依赖模型原生支持结构化工具调用(如OpenAI的API返回的tool_calls字段)。效率更高,但需特定模型支持。
    - 直接处理结构化数据,省去文本解析步骤,错误率更低。适合自动化程度高、需快速执行工具的场景。
"""
def create_langgraph_tool_calling_executor():
    # ### 也可以使用hub自带的提示词
    from langchain import hub
    # prompt = hub.pull("wfh/react-agent-executor")
    """
    input_variables=['{messages}'] 
    input_types={'{messages}': list[typing.Annotated[typing.Union[typing.Annotated[langchain_core.messages.ai.AIMessage, Tag(tag='ai')], typing.Annotated[langchain_core.messages.human.HumanMessage, Tag(tag='human')], typing.Annotated[langchain_core.messages.chat.ChatMessage, Tag(tag='chat')], typing.Annotated[langchain_core.messages.system.SystemMessage, Tag(tag='system')], typing.Annotated[langchain_core.messages.function.FunctionMessage, Tag(tag='function')], typing.Annotated[langchain_core.messages.tool.ToolMessage, Tag(tag='tool')], typing.Annotated[langchain_core.messages.ai.AIMessageChunk, Tag(tag='AIMessageChunk')], typing.Annotated[langchain_core.messages.human.HumanMessageChunk, Tag(tag='HumanMessageChunk')], typing.Annotated[langchain_core.messages.chat.ChatMessageChunk, Tag(tag='ChatMessageChunk')], typing.Annotated[langchain_core.messages.system.SystemMessageChunk, Tag(tag='SystemMessageChunk')], typing.Annotated[langchain_core.messages.function.FunctionMessageChunk, Tag(tag='FunctionMessageChunk')], typing.Annotated[langchain_core.messages.tool.ToolMessageChunk, Tag(tag='ToolMessageChunk')]], FieldInfo(annotation=NoneType, required=True, discriminator=Discriminator(discriminator=<function _get_type at 0x000001FED38EF240>, custom_error_type=None, custom_error_message=None, custom_error_context=None))]]} partial_variables={} metadata={'lc_hub_owner': 'wfh', 'lc_hub_repo': 'react-agent-executor', 'lc_hub_commit_hash': 'bccfbbc5de8559d19d44c8ea2229bb6d06c99e402ea29b8694b294a31730a7a5'} 
    messages=[
        SystemMessagePromptTemplate(
            prompt=PromptTemplate(
                input_variables=[], 
                input_types={}, 
                partial_variables={},
                template='You are a helpful assistant.'),
            additional_kwargs={}
        ),
        MessagesPlaceholder(variable_name='{messages}')
    ]
    """
    # ### 使用ChatPromptTemplate定义提示词
    # from langchain_core.prompts import ChatPromptTemplate
    # from langchain_core.prompts import MessagesPlaceholder
    # prompt_chat_prompt_template_4 = ChatPromptTemplate.from_messages(
    #     [
    #         ("system", "你是我定义的一个系统助手"),
    #         # 必须加,而且好像必须使用默认key“messages”
    #         # 否则报错:langgraph.errors.InvalidUpdateError: Must write to at least one of ['messages', 'structured_response']
    #         MessagesPlaceholder(variable_name='messages'),
    #         # ("placeholder", "{messages}"),
    #     ]
    # )
    prompt_template = """ 你是我定义的一个系统助手 """
    from langchain_core.messages import SystemMessage
    prompt = SystemMessage(content=prompt_template)

    from langgraph.prebuilt.chat_agent_executor import create_tool_calling_executor
    # chat_agent_executor.create_tool_calling_executor封装了 create_react_agent
    agent_prompt_chat_prompt_template_4 = create_tool_calling_executor(
        model=llm,
        tools=tools,
        prompt=prompt
    )
    print(f"1:{agent_prompt_chat_prompt_template_4.invoke(
        {"messages": [("human", "请问1U8等于多少?")]},
        # config=config
    )["messages"][-1].content}")
    print("-" * 100)
    # print(f"2:{agent_prompt_chat_prompt_template_4.invoke(
    #     {"messages": "请问1U8等于多少?"},
    #     # config=config
    # )["messages"][-1].content}")
    # print("-" * 100)
    # 
    # print(f"3:{agent_prompt_chat_prompt_template_4.invoke(
    #     {"messages": [{"role": "human", "content": "what is 1 T 8"}]}
    # )["messages"][-1].content}")
    # print("-" * 100)
    # for e in agent_prompt_chat_prompt_template_4.stream(
    #         input={"messages": [{"role": "human", "content": "what is 1 T 8"}]},
    #         stream_mode='values'):
    #     message = e['messages'][-1]
    #     print(message)
    #     if isinstance(message, tuple):
    #         print(message)
    #     else:
    #         message.pretty_print()

 6、创建Agent:使用Langchain的API手动创建

即使用ReAct Agent方式

ReActAgent 是基于 ReAct(Reasoning and Acting)框架实现的智能体,其核心思想是模型通过交替进行推理(Reasoning)和行动(Acting)来完成任务。
在代码中,它的工作流程是:
    - 调用模型生成响应;
    - 若响应中包含工具调用(tool_calls),则并行执行所有工具;
    - 将工具执行结果追加到消息历史中,重新调用模型生成新响应;
    - 循环直到模型不再调用工具,返回最终结果。
ReActAgent(用户代码中的实现):
    - 核心:通过交替进行 推理(Reasoning) 和 行动(Action) 完成任务。
    - 是一个手动实现的 ReAct 逻辑,通过 while 循环显式控制工具调用和模型迭代。
    - 需要自行管理消息历史、工具调用结果的拼接。
    - 灵活性更高,但需要更多底层代码。
create_react_agent(如 LangChain 等框架提供的函数):
    - 核心:内置标准化ReAct流程(思考→行动→观察循环);自动处理工具调用和中间状态管理
    - 通常是框架封装好的高阶函数,通过预设的提示词(prompt)和流程自动处理 ReAct 逻辑。
    - 适用于快速搭建标准Agent场景
    
创建ReAct代理,步骤如下:
    1、定义模型和工具
        - llm = llm
        - tools = [工具一、工具二...]
    2、定义任务
        - 任务一:调用模型,我们希望使用消息列表查询我们的聊天模型。
        - 任务二:调用工具,如果我们的模型生成工具调用,我们希望执行它们。
    3、定义入口点:入口点 将处理这两个任务的编排
        - 当我们的 call_model(任务一) 任务生成工具调用时
        - call_tool(任务二) 任务将为每个工具调用生成响应
        - 我们将所有消息附加到单个消息列表中。
    4、使用
    5、添加线程级持久性 --- 即历史记录
        - 选择一个 检查点:在这里我们将使用 MemorySaver,一个简单的内存检查点。
        - 更新我们的入口点以接受先前的消息状态作为第二个参数。在这里,我们只是将消息更新附加到先前的消息序列。
        - 选择哪些值将从工作流返回,哪些值将由检查点程序保存为 previous,使用 entrypoint.final(可选) 

1、定义模型和工具 

# ### 1、定义模型和工具
react_model = ChatOllama(model='qwen2.5:1.5b', temperature=0, verbose=True)
# react_model = get_llm('glm')
# 工具集合
react_tools = tools
# 绑定工具到模型
react_llm_with_tool = react_model.bind_tools(tools)

 2、定义任务

# ### 2、定义任务
from langchain_core.messages import ToolMessage
from langgraph.func import entrypoint, task

tools_by_name = {tool.name: tool for tool in tools}


@task
def call_model(messages):
    """Call model with a sequence of messages."""
    return react_llm_with_tool.invoke(messages)


@task
def call_tool(tool_call):
    tool = tools_by_name[tool_call["name"]]
    observation = tool.invoke(tool_call["args"])
    return ToolMessage(content=observation, tool_call_id=tool_call["id"])

 3、定义入口点

 无记忆版本

# ### 3、定义入口点
# 无记忆
@entrypoint()
def agent(messages):
    llm_response = call_model(messages).result()
    while True:
        if not llm_response.tool_calls:
            break

        # 执行工具
        tool_result_futures = [
            call_tool(tool_call) for tool_call in llm_response.tool_calls
        ]
        tool_results = [fut.result() for fut in tool_result_futures]

        # 添加消息到消息列表
        messages = add_messages(messages, [llm_response, *tool_results])

        # 获取模型返回
        llm_response = call_model(messages).result()

    return llm_response

 有记忆:添加线程级别记忆

# 有记忆
# 选择一个 检查点:在这里我们将使用 MemorySaver,一个简单的内存检查点。
checkpointer = MemorySaver()


@entrypoint(checkpointer=checkpointer)
# 更新我们的入口点以接受先前的消息状态作为第二个参数。在这里,我们只是将消息更新附加到先前的消息序列。
def agent(messages, previous):
    if previous is not None:
        messages = add_messages(previous, messages)

    llm_response = call_model(messages).result()
    while True:
        if not llm_response.tool_calls:
            break

        tool_result_futures = [
            call_tool(tool_call) for tool_call in llm_response.tool_calls
        ]
        tool_results = [fut.result() for fut in tool_result_futures]

        messages = add_messages(messages, [llm_response, *tool_results])

        llm_response = call_model(messages).result()

    # 生成最终响应的消息
    messages = add_messages(messages, llm_response)
    # 选择哪些值将从工作流返回,哪些值将由检查点程序保存为 previous,使用 entrypoint.final(可选)
    return entrypoint.final(value=llm_response, save=messages)

4、使用

使用无记忆版本

# 使用
user_message = {"role": "user", "content": "1U7等于多少"}
print(user_message)

for step in agent.stream([user_message]):
    for task_name, message in step.items():
        if task_name == "agent":
            continue
        print(f"\n{task_name}:")
        message.pretty_print()

 使用:有记忆

# ### 4、使用:有记忆
config = {"configurable": {"thread_id": "1"}}
print(f"带历史记录的ReActAgent: {agent.invoke([{"role": "user", "content": "hi,我叫UU。请问1U7等于多少?"}], config)}")
print(f"带历史记录的ReActAgent: {agent.invoke([{"role": "user", "content": "我刚刚说我叫什么?"}], config)}")
print(f"带历史记录的ReActAgent: {agent.invoke([{"role": "user", "content": "我刚刚问你什么了?"}], config)}")
# for step in agent.stream([user_message], config):
#     for task_name, message in step.items():
#         if task_name == "agent":
#             continue  # Just print task updates
#         print(f"\n{task_name}:")
#         message.pretty_print()

7、在langchain中添加momery内存

自己拼装历史消息

def add_memory_langchain_calling_agent_custom_history():
    """方法一:自己拼装历史消息..."""
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.prompts import MessagesPlaceholder
    prompt_chat_custom_6 = ChatPromptTemplate.from_messages(
        [
            ("system",
             """
             你是我定义的一个工具,一个可以根据我给你提供的工具列表来解决实际问题的工具。
             这代表着如果有你不知道的信息,你都可以使用它们获得最准确的结果。
             如果工具也无法处理,请直接回复“无法处理”即可,除此之外,切勿过多修饰。
             """),
            MessagesPlaceholder(variable_name='agent_history_demo6'),  # 历史记录的key
            ("human", "{agent_input6}"),
            # 添加agent_scratchpad,不然报错ValueError: Prompt missing required variables: {'agent_scratchpad'}
            MessagesPlaceholder(variable_name='agent_scratchpad'),
            # ("placeholder", "{agent_scratchpad}"),
        ]
    )
    from langchain.agents import create_tool_calling_agent
    agent_memory_6 = create_tool_calling_agent(
        llm=llm,
        tools=tools,
        prompt=prompt_chat_custom_6,
    )
    from langchain_core.messages import HumanMessage
    from langchain_core.messages import AIMessage
    from langchain.agents import AgentExecutor
    agent_executor = AgentExecutor(agent=agent_memory_6, tools=tools)
    chat_history_messages = [
        HumanMessage(content="你好,我的名字叫张三"),
        AIMessage(content="你好,张三!我有什么可以帮助你的?"),
    ]
    print(agent_executor.invoke({"agent_history_demo6": chat_history_messages, "agent_input6": "我的名字是啥?"}))

 使用 RunnableWithMessageHistory创建

def add_memory_langchain_calling_agent_runnable_history():
    """方法二:使用 RunnableWithMessageHistory创建"""
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.prompts import MessagesPlaceholder
    prompt_chat_custom_6 = ChatPromptTemplate.from_messages(
        [
            ("system", """
             你是我定义的一个工具,一个可以根据我给你提供的工具列表来解决实际问题的工具。
             这代表着如果有你不知道的信息,你都可以使用它们获得最准确的结果。
             如果工具也无法处理,请直接回复“无法处理”即可,除此之外,切勿过多修饰。
             """),
            MessagesPlaceholder(variable_name='agent_history_demo6'),  # 历史记录的key
            ("human", "{agent_input6}"),
            # 添加agent_scratchpad,不然报错ValueError: Prompt missing required variables: {'agent_scratchpad'}
            MessagesPlaceholder(variable_name='agent_scratchpad'),
            # ("placeholder", "{agent_scratchpad}"),
        ]
    )
    from langchain.agents import create_tool_calling_agent
    agent_memory_6 = create_tool_calling_agent(
        llm=llm,
        tools=tools,
        prompt=prompt_chat_custom_6,
    )

    from langchain.agents import AgentExecutor
    agent_executor_6 = AgentExecutor(
        agent=agent_memory_6,
        tools=tools,
        verbose=True,
    )
    from langchain_core.runnables import RunnableWithMessageHistory
    agent_with_chat_history_6 = RunnableWithMessageHistory(
        agent_executor_6,
        get_session_history=get_session_history,
        input_messages_key='agent_input6',
        history_messages_key='agent_history_demo6',
    )
    config_6 = {'configurable': {"session_id": "1234"}}
    print(agent_with_chat_history_6.invoke({"agent_input6": "hi,你好我叫UU,你叫什么?"}, config=config_6))
    print(agent_with_chat_history_6.invoke({"agent_input6": "对了我忘了,我刚刚说我叫什么来着?"}, config=config_6))

使用 ConversationBufferMemory 创建 

def add_memory_langchain_calling_agent_buffer_memory():
    """方法三:使用 ConversationBufferMemory 创建"""
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.prompts import MessagesPlaceholder
    prompt_chat_custom_6 = ChatPromptTemplate.from_messages(
        [
            ("system",
             """
             你是我定义的一个工具,一个可以根据我给你提供的工具列表来解决实际问题的工具。
             这代表着如果有你不知道的信息,你都可以使用它们获得最准确的结果。
             如果工具也无法处理,请直接回复“无法处理”即可,除此之外,切勿过多修饰。
             """),
            MessagesPlaceholder(variable_name='agent_history_demo6'),  # 历史记录的key
            ("human", "{agent_input6}"),
            # 添加agent_scratchpad,不然报错ValueError: Prompt missing required variables: {'agent_scratchpad'}
            MessagesPlaceholder(variable_name='agent_scratchpad'),
            # ("placeholder", "{agent_scratchpad}"),
        ]
    )
    from langchain.agents import create_tool_calling_agent
    agent_memory_6 = create_tool_calling_agent(
        llm=llm,
        tools=tools,
        prompt=prompt_chat_custom_6,
    )
    # memory_6 = ConversationBufferMemory(memory_key="agent_history_demo6",return_messages=True)
    from langchain.agents import AgentExecutor
    agent_executor_new_6 = AgentExecutor(
        agent=agent_memory_6,
        tools=tools,
        memory=get_memory(uid="123456", key='agent_history_demo6'),
        # memory=memory_6,
    )
    print(agent_executor_new_6.invoke({"agent_input6": "Hello,我叫UU"}))
    print(agent_executor_new_6.invoke({"agent_input6": "我忘了,我刚刚说我叫什么?"}))

8、在LangGraph中添加momery内存

在LangGraph中使用langgraph.prebuilt.chat_agent_executor.create_tool_calling_executor或者langgraph.prebuilt.create_react_agent
创建Agent的时候,一般都需要状态管理来实现添加内存的功能,但是我们可以使用checkpointer=MemorySaver()添加本地内存...
def add_memory_in_checkpointer_by_thread_id():
    system_message_7 = """
         你是我定义的一个代理助手,我会给你很多工具,你可以根据我给你提供的工具来帮我解决实际的问题。
         这代表着如果有你不知道的信息,你都可以使用我给你提供的工具获得最准确的结果。
         如果工具也无法处理,请直接回复“无法处理”即可,除此之外,切勿过多修饰。
     """
    from langchain_core.tracers import ConsoleCallbackHandler
    config_7 = {
        "configurable": {"thread_id": "12345"},
        # "callbacks": [ConsoleCallbackHandler()]
    }
    from langgraph.checkpoint.memory import MemorySaver
    checkpointer_thread_id_7 = MemorySaver()  # 是根据thread_id来创建的...
    # checkpointer_thread_id_7 = InMemorySaver()
    from langgraph.prebuilt import create_react_agent
    from langgraph.prebuilt import chat_agent_executor
    # langgraph_agent_executor_7 = create_react_agent(
    langgraph_agent_executor_7 = chat_agent_executor.create_tool_calling_executor(
        llm,
        tools,
        prompt=system_message_7,
        checkpointer=checkpointer_thread_id_7,
    )
    print(
        f"使用MemorySaver()的step1:{langgraph_agent_executor_7.invoke({"messages": [("user", "hi,我叫KK。")]}, config=config_7)["messages"][-1].content}")
    print(
        f"使用MemorySaver()的step2:{langgraph_agent_executor_7.invoke({"messages": [("user", "对了我刚刚说我叫什么来着?")]}, config=config_7)["messages"][-1].content}")
    # print(f"使用MemorySaver()的step2:{langgraph_agent_executor_7.invoke({"messages": [("user", "对了我刚刚说我叫什么来着?今天的成都天气是多少?")]}, config=config_7)["messages"][-1].content}")

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值