LangChain 的 bind_tools 依赖模型能输出符合 OpenAI Tool Calling 格式的响应(即包含 tool_calls 字段的消息)。

from langgraph.graph import StateGraph, END, START, MessagesState
from langchain_core.tools import tool
from langchain_ollama import ChatOllama
from langchain_core.messages import ToolMessage
from langgraph.checkpoint.memory import MemorySaver

llm = ChatOllama(model="qwen3:8b", base_url="http://localhost:11434")


@tool
def search_tool(input: str):
    """支持查询北京和上海的天气"""
    if "上海" in input.lower():
        return "晴天,气温27度"
    elif  "北京" in input.lower():
        return "晴转多云,气温20度"


tools = [search_tool]

model = llm.bind_tools(tools)


def call_model(state: MessagesState):
    message = state["messages"]
    respone = model.invoke(message)
    return {"messages": [respone]}


def tool_node(state: MessagesState):
    last_msg = state['messages'][-1]
    tool_call = last_msg.tool_calls[0]

    tool_name = tool_call["name"]
    args = tool_call["args"]
    input = args.get("input", "")

    # 找到对应的工具函数
    tool_func = {t.name: t for t in tools}[tool_name]

    # 直接调用工具函数(不是 model!)
    result = tool_func.invoke(input)  # ✅ 正确调用方式

    return {"messages": [ToolMessage(content=str(result),
                                     tool_call_id=tool_call["id"])]}


# 定义路由函数,决定是否走哪条边
def should_continue(state: MessagesState):
    messages = state['messages']
    last_message = messages[-1]
    # 判断LLM是否需要调用工具
    if last_message.tool_calls:
        return "tool"
    # 否则,结束
    return END


workflow = StateGraph(MessagesState)

workflow.add_node("tool", tool_node)
workflow.add_node("agent", call_model)

workflow.add_edge(START, "agent")
workflow.add_conditional_edges("agent", should_continue, ["tool", END])

workflow.add_edge("tool", "agent")

graph = workflow.compile()

graph.get_graph().draw_mermaid_png(output_file_path="1.png")

inputs = {"messages": [('human', "今天上海的天气怎么样?")]}
res = graph.invoke(inputs)
print(res["messages"][-1].content)

打断点:

分析如下:

state:

其中0(HumanMessage)如下:

HumanMessage(content='今天上海的天气怎么样?', additional_kwargs={}, response_metadata={}, id='ef338c50-e6bf-4726-887e-7c4ad8699726')

其中1(AIMessage)如下:

content='' additional_kwargs={} response_metadata={'model': 'qwen3:8b', 'created_at': '2025-12-25T03:14:28.9946579Z', 'done': True, 'done_reason': 'stop', 'total_duration': 26736100700, 'load_duration': 231792600, 'prompt_eval_count': 143, 'prompt_eval_duration': 656036400, 'eval_count': 95, 'eval_duration': 25769589900, 'model_name': 'qwen3:8b'} id='run--490413d4-2667-4b50-814f-96ad29447c5f-0' tool_calls=[{'name': 'search_tool', 'args': {'input': '上海'}, 'id': 'd41df242-af88-4aa9-a9ad-d48a3be63649', 'type': 'tool_call'}] usage_metadata={'input_tokens': 143, 'output_tokens': 95, 'total_tokens': 238}

最终传给model的如下:state状态更新

[HumanMessage(content='今天上海的天气怎么样?', additional_kwargs={}, response_metadata={}, id='da68f03c-cd51-4350-9937-02b9c2be027a'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'qwen3:8b', 'created_at': '2025-12-25T03:26:07.8786592Z', 'done': True, 'done_reason': 'stop', 'total_duration': 40361880100, 'load_duration': 213874600, 'prompt_eval_count': 143, 'prompt_eval_duration': 680992200, 'eval_count': 136, 'eval_duration': 39304178100, 'model_name': 'qwen3:8b'}, id='run--9204a268-0a5a-45ac-8009-21e57b6cfb4e-0', tool_calls=[{'name': 'search_tool', 'args': {'input': '上海'}, 'id': '183d70bd-f0e1-4c21-aa89-b58329873cbb', 'type': 'tool_call'}], usage_metadata={'input_tokens': 143, 'output_tokens': 136, 'total_tokens': 279}), ToolMessage(content='晴天,气温27度', id='4c5a8c6a-fbbb-4c05-8c1c-2ad3582506b2', tool_call_id='183d70bd-f0e1-4c21-aa89-b58329873cbb')]

输出结果:

[respone]:

[AIMessage(content='上海今天天气晴朗,气温27摄氏度,适合外出活动哦!', additional_kwargs={}, response_metadata={'model': 'qwen3:8b', 'created_at': '2025-12-25T03:35:40.1167725Z', 'done': True, 'done_reason': 'stop', 'total_duration': 55149192000, 'load_duration': 16352963400, 'prompt_eval_count': 182, 'prompt_eval_duration': 3931605900, 'eval_count': 120, 'eval_duration': 34648799800, 'model_name': 'qwen3:8b'}, id='run--75a75fd4-f91e-44c2-9b01-80ebef675a39-0', usage_metadata={'input_tokens': 182, 'output_tokens': 120, 'total_tokens': 302})]

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐