菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > AI教程 > LangGraph MCP集成:机器人工具调用入门
进阶教程 机器人 MCP集成

LangGraph MCP集成:机器人工具调用入门

2026-06-04
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

LangGraph通过工具调用增强LLM处理实时信息和数学计算的能力。以Web搜索工具为例,仅需少量

LangGraph工具调用基础

话说LLM在处理实时信息、数学计算这类问题上,表现一直不太理想。所以一个合格的Agent,得会调用外部工具来补短板。这篇就从最常见的Web搜索工具入手,带着大家快速上手LangGraph的工具调用。这里拿Ta vilySearch(app.ta vily.com)做演示——新用户有1000次免费搜索额度,够用一阵了。

在之前构建聊天机器人的基础上,只需要加少量代码就能完成工具调用。LangGraph已经把大部分复杂逻辑给封装好了,省心不少。

示例代码

fromtypingimportAnnotated
fromtyping_extensionsimportTypedDict
fromlangchain_openaiimportChatOpenAI
fromlanggraph.graphimportStateGraph, START
fromlanggraph.graph.messageimportadd_messages
frompydanticimportSecretStr
fromlangchain_ta vilyimportTa vilySearch
fromlanggraph.prebuiltimportToolNode, tools_condition

# 此处定义你自己的模型
llm = ChatOpenAI(base_url="http://127.0.0.1:8000/v1", api_key=SecretStr("123123"), model="qwen3_32")

# 定义工具
tool = Ta vilySearch(ta vily_api_key="你的ta vily apikey", max_results=2)
tools = [tool]

# 工具绑定到模型
llm_with_tools = llm.bind_tools(tools)

# 定义图状态
classState(TypedDict):
    messages: Annotated[list, add_messages] # 此处维护完整的消息历史

graph = StateGraph(State)

defchatbot(state: State):
    return{"messages": [llm_with_tools.invoke(state["messages"])]}

# 使用LangGraph提供的工具节点
tool_node = ToolNode(tools=tools)

graph.add_node("chatbot", chatbot)
# 添加工具节点
graph.add_node("tools", tool_node)

# 添加工具条件分支
graph.add_conditional_edges(
    "chatbot",
    tools_condition,
)

graph.add_edge("tools","chatbot")
graph.add_edge(START,"chatbot")

app = graph.compile()

if__name__ =="__main__":
    messages = []
    whileTrue:
        user_input =input("?‍?: ")
        ifuser_input.lower()in["quit","exit","q"]:
            print("Exiting...")
            break
        messages.append({"role":"user","content": user_input})
        response = app.invoke({"messages": messages})
        messages = response["messages"]
        print(f'?:{response["messages"][-1].content}')

效果如下

LangGraph自定义工具与工具节点

LangChain预置了不少常见工具,比如搜索类的(Bing、SerpAPI、Ta vily),代码执行类的(Python REPL、Node.js REPL),还有数据库类、Web数据类、天气API等等。但说实话,真到了企业开发场景,更常见的是自己写定制工具——毕竟每个业务都有自己的特殊需求。

下面演示一个基于BaseTool的自定义Ta vily搜索工具,以及怎么在LangGraph里接进去。

示例代码

importjson
fromlangchain_core.messagesimportToolMessage
fromlanggraph.constantsimportEND
fromtypingimportAnnotated,Type,Optional
fromlangchain_core.callbacksimportCallbackManagerForToolRun, AsyncCallbackManagerForToolRun
fromtyping_extensionsimportTypedDict
fromlangchain_openaiimportChatOpenAI
fromlanggraph.graphimportStateGraph, START
fromlanggraph.graph.messageimportadd_messages
frompydanticimportSecretStr, BaseModel, Field
fromlangchain_core.toolsimportBaseTool
fromta vilyimportTa vilyClient, AsyncTa vilyClient

# 自定义工具部分
classTa vilySearchInput(BaseModel):
    query:str= Field(description=("搜索查询"))

classTa vilySearchTool(BaseTool):
    name:str="ta vily_search"
    description:str="""一个针对全面、准确和可信的结果进行了优化的搜索引擎。当需要回答有关时事的问题时很有用。输入应该是搜索查询。"""
    args_schema:Type[BaseModel] = Ta vilySearchInput
    # return_direct: bool = True
    def_run(self, query:str, run_manager:Optional[CallbackManagerForToolRun] =None ) ->int:
        client = Ta vilyClient()
        search_r = client.search(query=query, max_results=2)
        returnsearch_r

    asyncdef_arun(self,query:str,run_manager:Optional[AsyncCallbackManagerForToolRun] =None, ) ->int:
        client = AsyncTa vilyClient()
        search_r =awaitclient.search(query=query, max_results=2)
        returnsearch_r

# 自定义的工具执行节点
classToolNode:
    def__init__(self, tools:list) ->None:
        self.tools_by_name = {tool.name: toolfortoolintools}
    def__call__(self, inputs:dict):
        ifmessages := inputs.get("messages", []):
            message = messages[-1]
        else:
            raiseValueError("No message found in input")

        outputs = []
        fortool_callinmessage.tool_calls:
            print(f'正在执行工具{tool_call["name"]},参数{tool_call["args"]}')
            tool_result =self.tools_by_name[tool_call["name"]].invoke(tool_call["args"])
            print(f'工具{tool_call["name"]}, 执行结果{json.dumps(tool_result, ensure_ascii=False)}')
            outputs.append(ToolMessage(content=json.dumps(tool_result, ensure_ascii=False),name=tool_call["name"],tool_call_id=tool_call["id"],))
        return{"messages": outputs}

# 此处定义你自己的模型
llm = ChatOpenAI(base_url="http://127.0.0.1:8000/v1", api_key=SecretStr("123123"), model="qwen3_32")

# 定义工具
tool = Ta vilySearchTool()
tools = [tool]

# 工具绑定到模型
llm_with_tools = llm.bind_tools(tools)

# 定义图状态
classState(TypedDict):
    messages: Annotated[list, add_messages] # 此处维护完整的消息历史

graph = StateGraph(State)

defchatbot(state: State):
    return{"messages": [llm_with_tools.invoke(state["messages"])]}

# 工具路由
defroute_tools(state: State):
    ifisinstance(state,list):
        ai_message = state[-1]
    elifmessages := state.get("messages", []):
        ai_message = messages[-1]
    else:
        raiseValueError(f"No messages found in input state to tool_edge:{state}")
    ifhasattr(ai_message,"tool_calls")andlen(ai_message.tool_calls) >0:
        return"tools"
    returnEND

# 使用LangGraph提供的工具节点
tool_node = ToolNode(tools=tools)

graph.add_node("chatbot", chatbot)
# 添加工具节点
graph.add_node("tools", tool_node)

# 添加工具条件边
graph.add_conditional_edges(
    "chatbot",
    route_tools,
    {"tools":"tools", END: END},
)

graph.add_edge("tools","chatbot")
graph.add_edge(START,"chatbot")

app = graph.compile()

if__name__ =="__main__":
    messages = []
    whileTrue:
        user_input =input("?‍?: ")
        ifuser_input.lower()in["quit","exit","q"]:
            print("Exiting...")
            break
        messages.append({"role":"user","content": user_input})
        response = app.invoke({"messages": messages})
        messages = response["messages"]
        print(f'?:{response["messages"][-1].content}')

效果如下

除了继承BaseTool,LangChain还支持通过@tool装饰器来快速定义工具。这种方法更简洁,适合轻量级场景。

fromtypingimportAnnotated
fromta vilyimportTa vilyClient
fromlangchain_core.toolsimporttool

@tool("ta vily_search")
defta vily_search_tool(query: Annotated[str,"搜索查询"]):
    """一个针对全面、准确和可信的结果进行了优化的搜索引擎。当需要回答有关时事的问题时很有用。输入应该是搜索查询。"""
    client = Ta vilyClient()
    search_r = client.search(query=query)
    returnsearch_r

ta vily_search_tool.invoke({"query":"北京2025年8月27日天气怎么样?"})

LangGraph调用MCP

除了自定义工具,LangGraph还支持MCP(Model Context Protocol),这让工具的复用和扩展性更强。要用MCP,需要额外安装一个包:

pip install langchain-mcp-adapters

编写一个简单的MCP Server

还是以Ta vily搜索为例:

importjson
frommcp.server.fastmcpimportFastMCP
fromta vilyimportTa vilyClient

mcp = FastMCP("search")

@mcp.tool()
asyncdefta vily_search(query:str) ->str:
    """一个针对全面、准确和可信的结果进行了优化的搜索引擎。当需要回答有关时事的问题时很有用。输入应该是搜索查询。"""
    client = Ta vilyClient()
    search_r = client.search(query=query, max_results=2)
    returnjson.dumps(search_r, ensure_ascii=False)

if__name__ =="__main__":
    mcp.run(transport="streamable-http")

LangGraph+MCP完整示例代码

importasyncio
fromlangchain_mcp_adapters.clientimportMultiServerMCPClient
fromlanggraph.prebuiltimportToolNode, tools_condition
fromtypingimportAnnotated
fromtyping_extensionsimportTypedDict
fromlangchain_openaiimportChatOpenAI
fromlanggraph.graphimportStateGraph, START
fromlanggraph.graph.messageimportadd_messages
frompydanticimportSecretStr

# 此处定义你自己的模型
llm = ChatOpenAI(base_url="http://127.0.0.1:8000/v1", api_key=SecretStr("123123"), model="qwen3_32")

# 配置MCP Server
client = MultiServerMCPClient({
    "search": {
        "url":"http://localhost:8000/mcp/",
        "transport":"streamable_http",
    }
})

classState(TypedDict):
    messages: Annotated[list, add_messages] # 此处维护完整的消息历史

graph = StateGraph(State)

asyncdefmain():
    tools =awaitclient.get_tools()

    # 工具绑定到模型
    llm_with_tools = llm.bind_tools(tools)

    defchatbot(state: State):
        return{"messages": [llm_with_tools.invoke(state["messages"])]}

    graph = StateGraph(State)
    graph.add_node(chatbot)
    graph.add_node(ToolNode(tools))
    graph.add_edge(START,"chatbot")
    graph.add_conditional_edges(
        "chatbot",
        tools_condition,
    )
    graph.add_edge("tools","chatbot")
    app = graph.compile()

    messages = []
    whileTrue:
        user_input =input("?‍?: ")
        ifuser_input.lower()in["quit","exit","q"]:
            print("Exiting...")
            break
        messages.append({"role":"user","content": user_input})
        response =awaitapp.ainvoke({"messages": messages})
        messages = response["messages"]
        print(f'?:{response["messages"][-1].content}')

asyncio.run(main())

效果如下

以上所有的LangGraph图结构

学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多