LangGraph ReAct应用

创建一个简单的 ReAct 代理应用程序,该应用程序可以检查天气。该应用程序由一个代理(LLM)和工具组成。当我们与应用程序交互时,我们将首先调用代理(LLM)来决定是否应该使用工具。然后我们将运行一个循环

  1. 如果代理说要采取行动(即调用工具),我们将运行工具并将结果传递回代理
  2. 如果代理没有要求运行工具,我们将结束(响应用户)

预构建的代理

请注意,这里我们将使用预构建的代理。LangGraph 的一大优势是你可以轻松创建自己的代理架构。因此,虽然从这里开始快速构建代理是不错的选择,但我们强烈建议你学习如何构建自己的代理,这样你就可以充分利用 LangGraph。

python 复制代码
import asyncio
from typing import Literal

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from pyexpat.errors import messages


@tool
def get_wather(city:Literal["深圳","北京"]):
    """
    查询所在城市的天气情况
    :param city:
    :return:
    """
    if city == "深圳":
        return "多云,很多云"
    elif city == "北京":
        return "下雨,很多雨"
    else:
        return "不知道设么天气"

tools = [get_wather]
llm = ChatOpenAI(base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
                 api_key="sk-3ad75cfac*********3d473b2a", model="qwen-plus")
#from langchain.agents import create_agent

graph = create_react_agent(llm, tools)
inputs = {"messages":["深圳天气怎么样"]}

async def main():
    async for chunk in graph.astream(inputs,stream_mode="values"):
        print(chunk)

asyncio.run(main())

向 ReAct 代理添加记忆

要启用内存,我们只需要将 checkpointer 传递给 create_react_agents

python 复制代码
import asyncio
from typing import Literal

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from pyexpat.errors import messages


@tool
def get_wather(city:Literal["深圳","北京"]):
    """
    查询所在城市的天气情况
    :param city:
    :return:
    """
    if city == "深圳":
        return "多云,很多云"
    elif city == "北京":
        return "下雨,很多雨"
    else:
        return "不知道设么天气"

tools = [get_wather]
llm = ChatOpenAI(base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
                 api_key="sk-3ad75cfac***********d3d473b2a", model="qwen-plus")
#from langchain.agents import create_agent
# 初始化 MemorySaver 实例
memory = MemorySaver()
config = {"configurable": {"thread_id": "1"}}

graph = create_react_agent(llm, tools,checkpointer=memory)
async def main():
    inputs = {"messages":["深圳天气怎么样"]}
    async for chunk in graph.astream(inputs,config = config,stream_mode="values"):
        #print(chunk)
        print(chunk['messages'][-1])

    inputs = {"messages":["它有哪些著名景点"]}
    async for chunk in graph.astream(inputs,config = config,stream_mode="values"):
        #print(chunk)
        print(chunk['messages'][-1])

asyncio.run(main())

请注意,当我们传递相同的线程 ID 时,聊天历史记录会保留

python 复制代码
content='深圳天气怎么样' additional_kwargs={} response_metadata={} id='77b64894-e4d6-471c-a69f-dab3c21a3eb6'
content='' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 164, 'total_tokens': 184, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-8251795b-3fbb-49c4-8e99-f54ca41fbf62', 'finish_reason': 'tool_calls', 'logprobs': None} id='lc_run--c4399237-4cd3-40bb-85cc-30a3752a257a-0' tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_32920ee2116b42989b948c', 'type': 'tool_call'}] usage_metadata={'input_tokens': 164, 'output_tokens': 20, 'total_tokens': 184, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
content='多云,很多云' name='get_wather' id='4dbec74f-07a3-4360-808b-4b1174c02378' tool_call_id='call_32920ee2116b42989b948c'
content='深圳目前的天气是多云,天空中有很多云。如果需要更详细的天气信息,比如温度、湿度或风速,请告诉我!' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 30, 'prompt_tokens': 203, 'total_tokens': 233, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-33f3ffd2-7729-4749-8eae-155fdbc2e861', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--58e874f5-f9a6-4067-b01c-b48b166507b4-0' usage_metadata={'input_tokens': 203, 'output_tokens': 30, 'total_tokens': 233, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
content='它有哪些著名景点' additional_kwargs={} response_metadata={} id='62d2b2a8-7ec9-42cc-994a-3b57a304bdfd'
content='深圳作为中国的一线城市,拥有许多著名的景点和地标,融合了现代都市风貌与自然风光。以下是一些深圳的著名景点:\n\n1. **世界之窗**  \n   一个大型主题公园,汇集了全球130多个著名景观的微缩版,如埃菲尔铁塔、自由女神像、金字塔等,适合拍照和家庭游玩。\n\n2. **锦绣中华·民俗村**  \n   包含"锦绣中华"(中国各地名胜微缩景观)和"民俗村"(展示中国56个民族文化的表演与建筑),是了解中国文化的好去处。\n\n3. **欢乐谷**  \n   国家级主题乐园,拥有众多刺激的游乐设施、表演和主题活动,适合年轻人和家庭游客。\n\n4. **东部华侨城**  \n   集生态旅游、休闲度假、户外运动为一体的综合性景区,包含大侠谷、茶溪谷等,风景优美,适合放松身心。\n\n5. **大梅沙海滨公园**  \n   深圳著名的免费海滩,是市民和游客夏日戏水、晒太阳的好地方。\n\n6. **梧桐山**  \n   深圳最高峰,适合登山爱好者,登顶可俯瞰深圳市区和香港新界,自然风光秀丽。\n\n7. **深圳湾公园**  \n   沿海而建的带状公园,是骑行、散步、观鸟和看日落的热门地点,还能远眺香港。\n\n8. **平安金融中心云际观光层**  \n   位于深圳第二高楼,海拔约592米,提供360度城市全景,是俯瞰深圳现代化天际线的最佳地点之一。\n\n9. **南头古城 & NANTOU PRIME**  \n   历史悠久的古城,近年来经过改造,融合了文化、艺术与潮流元素,成为年轻人喜爱的打卡地。\n\n10. **蛇口海上世界**  \n    以一艘巨型游轮"明华轮"为中心的综合商圈,集餐饮、娱乐、艺术展览于一体,夜晚灯光璀璨,氛围浪漫。\n\n如果你告诉我你喜欢自然、历史还是现代娱乐,我可以为你推荐更合适的景点哦!' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 461, 'prompt_tokens': 247, 'total_tokens': 708, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 64}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-c5c2376e-4559-40b8-84d4-c5c7e77a58ce', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--34749ac8-7afc-4e9b-896c-82f5d1be2e82-0' usage_metadata={'input_tokens': 247, 'output_tokens': 461, 'total_tokens': 708, 'input_token_details': {'cache_read': 64}, 'output_token_details': {}}

向 ReAct 代理添加系统提示

您可以通过将字符串传递给state_modifier参数来添加自定义系统提示。

python 复制代码
# 我们可以在这里添加系统提示
prompt = "请以导游身份回答问题"

graph = create_react_agent(llm, tools,checkpointer=memory,prompt=prompt)
python 复制代码
content='深圳天气怎么样' additional_kwargs={} response_metadata={} id='7dbd2c8f-fc31-4408-bfa0-c5799179bffe'
content='' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 171, 'total_tokens': 191, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-5b0218e5-348e-4221-a2b3-46960ea46ea3', 'finish_reason': 'tool_calls', 'logprobs': None} id='lc_run--d90547de-4b38-4043-8cf1-b4c617e1e2a1-0' tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_d498d96dd518449a996a74', 'type': 'tool_call'}] usage_metadata={'input_tokens': 171, 'output_tokens': 20, 'total_tokens': 191, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
content='多云,很多云' name='get_wather' id='0f3d81a3-a5c9-4191-b96f-6651093061f7' tool_call_id='call_d498d96dd518449a996a74'
content='深圳目前的天气是多云,天空中有很多云层。气温适中,适合外出活动,但建议随身携带一件薄外套以防微凉。如果您有户外计划,不用担心,这样的天气非常适合拍照和散步哦!需要我为您推荐一些适合这种天气游玩的地方吗?' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 61, 'prompt_tokens': 210, 'total_tokens': 271, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-4a5672d0-491a-4297-a818-708aee6c18b0', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--2d813894-70f5-48e4-a323-736b96489015-0' usage_metadata={'input_tokens': 210, 'output_tokens': 61, 'total_tokens': 271, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
content='它有哪些著名景点' additional_kwargs={} response_metadata={} id='38e89cf6-76f7-4718-85cc-2cf2936f7ffd'
content='深圳作为一座现代化大都市,融合了科技、自然与人文景观,有许多值得一游的著名景点。以下是一些不容错过的热门打卡地:\n\n1. **世界之窗**  \n   这是一个微缩景观主题公园,汇集了全球130多个著名景点的缩小版,比如埃菲尔铁塔、自由女神像、金字塔等,适合拍照和了解世界各地文化。\n\n2. **锦绣中华·民俗村**  \n   中国首个文化主题公园,展示了中国56个民族的风情和建筑,还有精彩的民俗表演,非常适合家庭出游。\n\n3. **深圳湾公园**  \n   沿海而建的超长滨海步道,是市民休闲散步、骑行的好去处。天气好的时候可以远眺香港,傍晚时分的日落特别美。\n\n4. **东部华侨城**  \n   集生态旅游、娱乐设施和温泉于一体的大型综合度假区,包含大侠谷、茶溪谷等,适合亲子游或朋友结伴游玩。\n\n5. **梧桐山**  \n   深圳最高峰,登山爱好者的好选择。登顶后可俯瞰整个深圳市区,云雾缭绕时宛如仙境。\n\n6. **大鹏所城 & 较场尾海滩**  \n   大鹏所城是明代海防军事要塞,保存完好的古建筑群;旁边较场尾被称为"深圳鼓浪屿",有很多文艺民宿和海边咖啡馆。\n\n7. **欢乐谷 & 华侨城创意文化园(OCT-LOFT)**  \n   欢乐谷是年轻人喜爱的主题乐园,有过山车、水上项目等刺激体验;而几步之遥的OCT-LOFT则是文艺青年的聚集地,常有艺术展、市集和独立书店。\n\n8. **平安金融中心云际观景台**  \n   位于深圳最高楼之一,高达近600米,可以360度俯瞰全城,夜景尤为震撼。\n\n如果您告诉我您喜欢哪种类型的旅行------比如自然风光、历史文化还是现代都市体验------我可以为您定制更合适的推荐路线哦!' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 450, 'prompt_tokens': 285, 'total_tokens': 735, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-fe421516-8bc1-4190-932f-602840c0fec6', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--e644e679-b9c0-4be5-b505-026c194330a1-0' usage_metadata={'input_tokens': 285, 'output_tokens': 450, 'total_tokens': 735, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
python 复制代码
import asyncio
from typing import Literal

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from langgraph.types import interrupt, Command
from pyexpat.errors import messages


@tool
def get_wather(city:Literal["深圳","北京"]):
    """
    查询所在城市的天气情况
    :param city:
    :return:
    """
    c = interrupt("请确认城市")
    print("确认结果",c)
    if city == "深圳":
        return "多云,很多云"
    elif city == "北京":
        return "下雨,很多雨"
    else:
        return "不知道设么天气"

tools = [get_wather]
llm = ChatOpenAI(base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
                 api_key="sk-3ad75cfac*********d3d473b2a", model="qwen-plus")
#from langchain.agents import create_agent
# 初始化 MemorySaver 实例
memory = MemorySaver()
config = {"configurable": {"thread_id": "1"}}

# 我们可以在这里添加系统提示
prompt = "请以导游身份回答问题"

graph = create_react_agent(llm, tools,checkpointer=memory,prompt=prompt,interrupt_before=["tools"])
async def main():
    inputs = {"messages":["深圳天气怎么样"]}
    async for chunk in graph.astream(inputs,config = config,stream_mode="values"):
        #print(chunk)
        print(chunk)

    # 获取图的状态快照
    snapshot = graph.get_state(config)
    # 打印下一步信息
    print("Next step: ", snapshot.next)
    async for chunk in graph.astream(None,config = config,stream_mode="values"):
        #print(chunk)
        print(chunk)

    # 对应interrupt 恢复
    async for chunk in graph.astream(Command(resume="我已确认"),config = config,stream_mode="values"):
        #print(chunk)
        print(chunk)
    # inputs = {"messages":["它有哪些著名景点"]}
    # async for chunk in graph.astream(inputs,config = config,stream_mode="values"):
    #     #print(chunk)
    #     print(chunk['messages'][-1])

asyncio.run(main())
python 复制代码
{'messages': [HumanMessage(content='深圳天气怎么样', additional_kwargs={}, response_metadata={}, id='7cc047ba-dd73-4f20-a9a2-8ccba960997c')]}
{'messages': [HumanMessage(content='深圳天气怎么样', additional_kwargs={}, response_metadata={}, id='7cc047ba-dd73-4f20-a9a2-8ccba960997c'), AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 171, 'total_tokens': 191, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-bd18ec5b-6b5a-4357-a4fb-b7096d60dbc9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--6082f90a-19b1-4740-a1d5-b0837dbf093c-0', tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_a57e9fc6b47347c08f7815', 'type': 'tool_call'}], usage_metadata={'input_tokens': 171, 'output_tokens': 20, 'total_tokens': 191, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]}
Next step:  ('tools',)
{'messages': [HumanMessage(content='深圳天气怎么样', additional_kwargs={}, response_metadata={}, id='7cc047ba-dd73-4f20-a9a2-8ccba960997c'), AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 171, 'total_tokens': 191, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-bd18ec5b-6b5a-4357-a4fb-b7096d60dbc9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--6082f90a-19b1-4740-a1d5-b0837dbf093c-0', tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_a57e9fc6b47347c08f7815', 'type': 'tool_call'}], usage_metadata={'input_tokens': 171, 'output_tokens': 20, 'total_tokens': 191, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]}
{'__interrupt__': (Interrupt(value='请确认城市', id='d0a56560c10769b7b652b867c75366ad'),)}
{'messages': [HumanMessage(content='深圳天气怎么样', additional_kwargs={}, response_metadata={}, id='7cc047ba-dd73-4f20-a9a2-8ccba960997c'), AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 171, 'total_tokens': 191, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-bd18ec5b-6b5a-4357-a4fb-b7096d60dbc9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--6082f90a-19b1-4740-a1d5-b0837dbf093c-0', tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_a57e9fc6b47347c08f7815', 'type': 'tool_call'}], usage_metadata={'input_tokens': 171, 'output_tokens': 20, 'total_tokens': 191, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]}
确认结果 我已确认
{'messages': [HumanMessage(content='深圳天气怎么样', additional_kwargs={}, response_metadata={}, id='7cc047ba-dd73-4f20-a9a2-8ccba960997c'), AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 171, 'total_tokens': 191, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-bd18ec5b-6b5a-4357-a4fb-b7096d60dbc9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--6082f90a-19b1-4740-a1d5-b0837dbf093c-0', tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_a57e9fc6b47347c08f7815', 'type': 'tool_call'}], usage_metadata={'input_tokens': 171, 'output_tokens': 20, 'total_tokens': 191, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}), ToolMessage(content='多云,很多云', name='get_wather', id='085d8e1f-7c5a-4e45-b51b-fa28e572b43e', tool_call_id='call_a57e9fc6b47347c08f7815')]}
{'messages': [HumanMessage(content='深圳天气怎么样', additional_kwargs={}, response_metadata={}, id='7cc047ba-dd73-4f20-a9a2-8ccba960997c'), AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 171, 'total_tokens': 191, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-bd18ec5b-6b5a-4357-a4fb-b7096d60dbc9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--6082f90a-19b1-4740-a1d5-b0837dbf093c-0', tool_calls=[{'name': 'get_wather', 'args': {'city': '深圳'}, 'id': 'call_a57e9fc6b47347c08f7815', 'type': 'tool_call'}], usage_metadata={'input_tokens': 171, 'output_tokens': 20, 'total_tokens': 191, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}), ToolMessage(content='多云,很多云', name='get_wather', id='085d8e1f-7c5a-4e45-b51b-fa28e572b43e', tool_call_id='call_a57e9fc6b47347c08f7815'), AIMessage(content='深圳目前天气为多云,天空中有很多云,整体天气状况较为平稳。适合外出活动,但建议随身携带雨具,以防天气变化。祝您旅途愉快!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 39, 'prompt_tokens': 210, 'total_tokens': 249, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 64}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-edfbd30f-ec45-40ff-a42d-6eb3bb1d28be', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--210aef59-5f0d-4f31-95f0-e3dfb9c5cf5c-0', usage_metadata={'input_tokens': 210, 'output_tokens': 39, 'total_tokens': 249, 'input_token_details': {'cache_read': 64}, 'output_token_details': {}})]}
相关推荐
f***68601 小时前
问题:Flask应用中的用户会话(Session)管理失效
后端·python·flask
爱吃面条的猿1 小时前
Python修改pip install 指定安装包的路径和默认镜像源
linux·python·pip
饭饭大王6661 小时前
Python 模块的概念与导入:从基础语法到高级技巧
java·服务器·python
Sunhen_Qiletian1 小时前
python语言应用实战--------网络爬虫篇 第二篇(selenium库)
爬虫·python·selenium
鄃鳕2 小时前
装饰器【Python】
开发语言·python·数码相机
m0_528489252 小时前
Pycharm修改系统缓存路径(包含config, system, plugins, logs, remote sources等)
ide·python·pycharm·c盘
Franklin3 小时前
AI Coding 基础实践03 - Trae AI在Pycharm中的使用02 - 读取不了项目的文件问题解决
ide·python·pycharm
胖墩会武术3 小时前
【OpenCV图像处理】深度学习:cv2.dnn() —— 图像分类、人脸检测、目标检测
图像处理·pytorch·python·opencv