
模拟用户输入问题后,大模型分析要调用工具,但是工具节点有一定几率调用失败,失败后重新调用,直到成功
python
from langchain.tools import tool
from typing import Literal
from langchain_core.messages import SystemMessage, HumanMessage, ToolMessage, content
from dotenv import load_dotenv
from langgraph.graph import MessagesState, StateGraph,START,END
from rich import print as rprint
from IPython.display import display
from random import randint
load_dotenv()
from langchain.chat_models import init_chat_model
llm=init_chat_model(
model="deepseek-chat"
)
@tool(parse_docstring=True)
def get_weather(city: str):
"""
获取指定城市的天气情况
Args:
city 城市名称
"""
return f"{city}天气晴朗,适合玩出游玩"
tool_map={
"get_weather":get_weather,
}
llm_with_tools=llm.bind_tools([get_weather])
class GlobalState(MessagesState):
user_input: str
result: str
def input_node(state:GlobalState):
value=state["user_input"]
return {
"messages": [HumanMessage(value),]
}
def llm_node(state:MessagesState):
ai_msg=llm_with_tools.invoke(state["messages"])
return {
"messages": [ai_msg]
}
def router(state:MessagesState)-> Literal["tool_node","output_node"]:
messages=state["messages"]
last=messages[-1]
if last.tool_calls:
return "tool_node"
else:
return "output_node"
def tool_node(state:MessagesState):
messages=state["messages"].copy()
ai_msg=messages[-1]
num=5
tool_calls=ai_msg.tool_calls
for tool_item in tool_calls:
if randint(0,9) < num:
con="网络错误,工具调用失败,请重试"
else:
tool=tool_map[tool_item['name']]
res=tool.invoke(tool_item)
con=res.content
messages.append(ToolMessage(content=con,tool_call_id=tool_item["id"]))
return {
"messages": messages
}
def output_node(state:GlobalState):
messages=state["messages"]
return {
"result":messages[-1].content,
}
builder=StateGraph(GlobalState)
builder.add_node(input_node)
builder.add_node(llm_node)
builder.add_node(tool_node)
builder.add_node(output_node)
builder.add_edge(START,"input_node")
builder.add_edge("input_node","llm_node")
builder.add_conditional_edges("llm_node",router)
builder.add_edge("tool_node","llm_node")
builder.add_edge("output_node",END)
graph=builder.compile()
display(graph)
res=graph.invoke({
"user_input": "查询今天上海的天气",
"messages": [SystemMessage(content="如果工具调用失败,必须重新调用直到成功为止")]
})
rprint(res)
以下输出运行信息
python
{
'messages': [
SystemMessage(
content='如果工具调用失败,必须重新调用直到成功为止',
additional_kwargs={},
response_metadata={},
id='4b3be4ef-f86a-4195-8e43-9c0964907641'
),
HumanMessage(
content='查询今天上海的天气',
additional_kwargs={},
response_metadata={},
id='e23b10cd-d4d8-4dd4-bc46-1e6896e7db95'
),
AIMessage(
content='',
additional_kwargs={'refusal': None},
response_metadata={
'token_usage': {
'completion_tokens': 38,
'prompt_tokens': 279,
'total_tokens': 317,
'completion_tokens_details': None,
'prompt_tokens_details': {
'audio_tokens': None,
'cache_write_tokens': None,
'cached_tokens': 128,
'image_tokens': None,
'text_tokens': None
},
'prompt_cache_hit_tokens': 128,
'prompt_cache_miss_tokens': 151
},
'model_provider': 'deepseek',
'model_name': 'deepseek-flash',
'system_fingerprint': 'aeb56401ca74e127821c4f9126dcb669',
'id': '45365c27-4880-40a2-90a4-4e5990d4562e',
'finish_reason': 'tool_calls',
'logprobs': None
},
id='lc_run--01a0a54c-8f8e-7041-951b-e4044cd8bfad-0',
tool_calls=[
{
'name': 'get_weather',
'args': {'city': '上海'},
'id': 'call_00_sSlG4W0XzN44MjY3alrk3781',
'type': 'tool_call'
}
],
invalid_tool_calls=[],
usage_metadata={
'input_tokens': 279,
'output_tokens': 38,
'total_tokens': 317,
'input_token_details': {'cache_read': 128},
'output_token_details': {}
}
),
ToolMessage(
content='网络错误,工具调用失败,请重试',
id='b01f5ccd-a212-4d51-8584-eade0bfc52eb',
tool_call_id='call_00_sSlG4W0XzN44MjY3alrk3781'
),
AIMessage(
content='',
additional_kwargs={'refusal': None},
response_metadata={
'token_usage': {
'completion_tokens': 38,
'prompt_tokens': 339,
'total_tokens': 377,
'completion_tokens_details': None,
'prompt_tokens_details': {
'audio_tokens': None,
'cache_write_tokens': None,
'cached_tokens': 128,
'image_tokens': None,
'text_tokens': None
},
'prompt_cache_hit_tokens': 128,
'prompt_cache_miss_tokens': 211
},
'model_provider': 'deepseek',
'model_name': 'deepseek-flash',
'system_fingerprint': 'aeb56401ca74e127821c4f9126dcb669',
'id': '705a84d7-a91e-4fef-aeb9-94f0769211e5',
'finish_reason': 'tool_calls',
'logprobs': None
},
id='lc_run--01a0a54c-91a8-7d30-bf20-a473f4d70501-0',
tool_calls=[
{
'name': 'get_weather',
'args': {'city': '上海'},
'id': 'call_00_bUbtuHCra9EjoNEuKAZt7966',
'type': 'tool_call'
}
],
invalid_tool_calls=[],
usage_metadata={
'input_tokens': 339,
'output_tokens': 38,
'total_tokens': 377,
'input_token_details': {'cache_read': 128},
'output_token_details': {}
}
),
ToolMessage(
content='网络错误,工具调用失败,请重试',
id='4c65954a-970c-4adb-867c-1347980350a1',
tool_call_id='call_00_bUbtuHCra9EjoNEuKAZt7966'
),
AIMessage(
content='',
additional_kwargs={'refusal': None},
response_metadata={
'token_usage': {
'completion_tokens': 38,
'prompt_tokens': 399,
'total_tokens': 437,
'completion_tokens_details': None,
'prompt_tokens_details': {
'audio_tokens': None,
'cache_write_tokens': None,
'cached_tokens': 256,
'image_tokens': None,
'text_tokens': None
},
'prompt_cache_hit_tokens': 256,
'prompt_cache_miss_tokens': 143
},
'model_provider': 'deepseek',
'model_name': 'deepseek-flash',
'system_fingerprint': 'aeb56401ca74e127821c4f9126dcb669',
'id': 'eccb0c64-fd61-49e5-82d7-263379046b0b',
'finish_reason': 'tool_calls',
'logprobs': None
},
id='lc_run--01a0a54c-93cc-7532-bd46-6878fdb6c76b-0',
tool_calls=[
{
'name': 'get_weather',
'args': {'city': '上海'},
'id': 'call_00_FyDzz3agPKX6iHrfyogA5964',
'type': 'tool_call'
}
],
invalid_tool_calls=[],
usage_metadata={
'input_tokens': 399,
'output_tokens': 38,
'total_tokens': 437,
'input_token_details': {'cache_read': 256},
'output_token_details': {}
}
),
ToolMessage(
content='网络错误,工具调用失败,请重试',
id='463605cd-ba7e-4179-9eaa-77087554f61e',
tool_call_id='call_00_FyDzz3agPKX6iHrfyogA5964'
),
AIMessage(
content='',
additional_kwargs={'refusal': None},
response_metadata={
'token_usage': {
'completion_tokens': 38,
'prompt_tokens': 459,
'total_tokens': 497,
'completion_tokens_details': None,
'prompt_tokens_details': {
'audio_tokens': None,
'cache_write_tokens': None,
'cached_tokens': 256,
'image_tokens': None,
'text_tokens': None
},
'prompt_cache_hit_tokens': 256,
'prompt_cache_miss_tokens': 203
},
'model_provider': 'deepseek',
'model_name': 'deepseek-flash',
'system_fingerprint': 'aeb56401ca74e127821c4f9126dcb669',
'id': '916b62bd-85bd-4bb4-963b-97d0ee2b3bf8',
'finish_reason': 'tool_calls',
'logprobs': None
},
id='lc_run--01a0a54c-964a-7540-9e66-46340e12711b-0',
tool_calls=[
{
'name': 'get_weather',
'args': {'city': '上海'},
'id': 'call_00_XYyBO6xKEDSBteh2Jfsn3542',
'type': 'tool_call'
}
],
invalid_tool_calls=[],
usage_metadata={
'input_tokens': 459,
'output_tokens': 38,
'total_tokens': 497,
'input_token_details': {'cache_read': 256},
'output_token_details': {}
}
),
ToolMessage(
content='上海天气晴朗,适合玩出游玩',
id='1b7a5c0e-90d7-4130-ac8a-cd0a96690bdf',
tool_call_id='call_00_XYyBO6xKEDSBteh2Jfsn3542'
),
AIMessage(
content='今天上海的天气是**晴朗**,适合外出游玩。☀️\n\n(小提示:工具前几次调用失败了,重试后才获取到结
果。)',
additional_kwargs={'refusal': None},
response_metadata={
'token_usage': {
'completion_tokens': 33,
'prompt_tokens': 517,
'total_tokens': 550,
'completion_tokens_details': None,
'prompt_tokens_details': {
'audio_tokens': None,
'cache_write_tokens': None,
'cached_tokens': 256,
'image_tokens': None,
'text_tokens': None
},
'prompt_cache_hit_tokens': 256,
'prompt_cache_miss_tokens': 261
},
'model_provider': 'deepseek',
'model_name': 'deepseek-flash',
'system_fingerprint': 'aeb56401ca74e127821c4f9126dcb669',
'id': 'e98704ab-a962-4a03-bedf-aa2ee8a165c3',
'finish_reason': 'stop',
'logprobs': None
},
id='lc_run--01a0a54c-993e-7330-99a8-52ff579a623c-0',
tool_calls=[],
invalid_tool_calls=[],
usage_metadata={
'input_tokens': 517,
'output_tokens': 33,
'total_tokens': 550,
'input_token_details': {'cache_read': 256},
'output_token_details': {}
}
)
],
'user_input': '查询今天上海的天气',
'result':
'今天上海的天气是**晴朗**,适合外出游玩。☀️\n\n(小提示:工具前几次调用失败了,重试后才获取到结果。)'
}