LangChain 工具调用:从原理、入门到落地

LangChain 工具调用:从原理、入门到落地

在大模型应用开发中,纯文本LLM无法解决实时计算、外部数据查询、API交互等落地场景问题。LangChain 工具调用能力,核心是将自定义Python函数、外部能力封装为大模型可识别、可自主调度的标准化工具,让LLM自主判断何时调用工具、传递什么参数,最终结合工具输出结果生成精准回答。

本文将从零拆解LangChain工具调用的核心原理、核心组件、基础实操、手动/生产级两种实现方案、多工具调度、LCEL整合及生产避坑规范,所有代码均可直接运行,适配OpenAI、硅基流动等主流模型服务。

一、工具调用核心本质与核心概念

1.1 什么是 LangChain 工具(Tool)

LangChain 中的工具,本质是可被LLM自主调用的外部能力载体,是对普通Python函数、第三方API、数据库查询、计算器等能力的标准化封装。

简单来说:LLM 只擅长文本推理,无法执行计算、联网查询、读写数据,工具就是弥补LLM能力短板的外部插件,常见工具场景:

  • 基础能力:四则运算、单位换算、数据校验

  • 外部查询:天气查询、知识库检索、数据库查询

  • 业务交互:调用第三方API、发送邮件、执行脚本、流程操作

1.2 工具调用核心运行逻辑

LangChain 工具调用的核心链路可总结为一句话:函数标准化封装 → 模型绑定工具 → LLM自主决策调用 → 工具执行回传结果 → LLM整合输出答案

全程无需人工干预参数传递和工具触发,由模型根据用户问题自主判断是否需要调用工具。

二、工具调用五大核心组件

LangChain 工具调用依赖固定核心组件,各司其职,构成完整调用闭环,核心组件及作用如下:

核心组件 核心作用
@tool 装饰器 将普通Python函数转为LangChain标准结构化工具,自动生成参数规约、工具描述
支持工具调用的LLM 如DeepSeek-V3、GPT-3.5/4,具备工具决策、参数生成能力
bind_tools() 将工具列表绑定到模型,让LLM感知可用工具的能力、参数、使用场景
ToolMessage 标准化工具执行结果,接入对话上下文,供LLM二次推理
Agent/AgentExecutor 自动化完成多轮工具调用、循环推理,实现生产级闭环执行

三、第一步:标准化封装工具(@tool 深度解析)

普通Python函数无法被LLM识别,必须通过 @tool 装饰器 完成标准化封装,这是工具调用的基础。

3.1 @tool 底层原理

@tool 本质是对 StructuredTool.from_function() 的封装,不会修改原函数的执行逻辑,仅为函数附加大模型可识别的元信息,最终生成标准工具实例,核心附加信息:

  • name:工具名称(默认函数名),LLM通过该名称定位要调用的工具

  • description:取自函数docstring,告知LLM工具用途、适用场景

  • args_schema:通过函数类型注解自动生成Pydantic参数模型,约束参数类型、生成标准JSON Schema,避免参数传错

  • func:保留原始Python执行逻辑,保证工具功能不变

3.2 标准工具封装示例(可直接运行)

工具封装核心规范:必须写清晰docstring、必须标注参数类型、增加异常处理,保障LLM精准调用。

python 复制代码
# tools.py
from langchain_core.tools import tool

@tool
def calculator(a: float, b: float, op: str) -> str:
    """
    对两个数字进行四则运算计算
    :param a: 第一个运算数字,浮点类型
    :param b: 第二个运算数字,浮点类型
    :param op: 运算符,仅支持 +、-、*、/ 四种符号
    :return: 运算结果或异常提示
    """
    try:
        if op == "+":
            return str(a + b)
        elif op == "-":
            return str(a - b)
        elif op == "*":
            return str(a * b)
        elif op == "/":
            if b == 0:
                return "计算异常:除数不能为0"
            return str(a / b)
        else:
            return f"计算异常:不支持{op}运算符,仅支持+、-、*、/"
    except Exception as e:
        return f"计算执行失败:{str(e)}"

# @tools之后,就有这这些属性了
print(cal.name)
print(cal.description)

# 封装第二个工具:模拟天气查询
@tool
def get_weather(city: str) -> str:
    """
    查询指定城市的实时天气
    :param city: 城市中文名称,如:北京、上海、广州
    :return: 城市天气及温度信息
    """
    # 模拟接口返回逻辑
    weather_map = {
        "北京": "晴朗,25℃,微风",
        "上海": "多云,23℃,东南风",
        "广州": "小雨,28℃,南风"
    }
    return weather_map.get(city, f"暂未查询到{city}的天气数据")

# 工具列表:统一管理所有可用工具
tools = [calculator, get_weather]

四、第二步:模型初始化与工具绑定

选用支持工具调用的大模型,通过 bind_tools 绑定工具列表,让模型具备工具调用能力。本文适配硅基流动DeepSeek-V3模型,兼容OpenAI系列模型。

4.1 模型配置文件(llm.py

python 复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 适配硅基流动模型,映射OpenAI标准环境变量
os.environ["OPENAI_API_KEY"] = os.getenv("SILICON_KEY")
os.environ["OPENAI_BASE_URL"] = os.getenv("SILICON_BASE_URL")

# 初始化支持工具调用的大模型
llm = init_chat_model("openai:deepseek-ai/DeepSeek-V3")

4.2 工具绑定核心代码

python 复制代码
from llm import llm
from tools import tools

# 为模型绑定所有可用工具,生成具备工具调用能力的模型实例
llm_with_tools = llm.bind_tools(tools)

绑定后,模型推理时会自动根据用户问题判断:是否需要调用工具、调用哪个工具、传递什么参数。

五、两种工具调用实现方案(从调试到生产)

LangChain 工具调用分为手动解析版(调试专用)Agent自动执行版(生产专用),适配不同开发场景。

5.1 方案一:手动解析工具调用(适合调试、学习原理)

手动实现「模型决策→工具执行→结果回传→多轮循环」全流程,直观理解工具调用底层逻辑,适合新手学习和问题调试。

核心规则:模型返回的 tool_calls 非空则需调用工具,content 为空;无需调用工具时tool_calls 为空,content 为直接回答。

python 复制代码
from langchain_core.messages import HumanMessage, ToolMessage
from llm import llm
from tools import tools

# 1. 初始化对话上下文
messages = [HumanMessage(content="先计算3+3,结果再乘以2?北京和上海天气怎么样")]
# 绑定工具
llm_with_tools = llm.bind_tools(tools)
tool_map = {t.name: t for t in tools}

# 2. 模型首次推理
# res的tool_calls是 [{"name": "cal", "args": {"a": 3, "b": 3, "op": "+"}, "id": "xxx"}]
res = llm_with_tools.invoke(messages)
tool_calls = res.tool_calls

# 3. 循环执行工具(支持多轮嵌套调用)
while tool_calls:
    # 记录模型工具调用请求到上下文
    messages.append(res)
    # 遍历执行所有工具调用
    for tc in tool_calls:
        print(f"调用工具:{tc['name']},参数:{tc['args']}")  # 看每次调了什么
        # 执行工具逻辑
        tool_result = tool_map[tc["name"]].invoke(tc["args"])
        # 工具结果写入上下文,关联调用ID
        messages.append(ToolMessage(content=tool_result, tool_call_id=tc["id"]))
    # 二次推理:基于工具结果继续判断是否需要新一轮工具调用
    res = llm_with_tools.invoke(messages)
    tool_calls = res.tool_calls

# 输出最终整合答案
print("最终回答:", res.content)

5.2 方案二:Agent自动执行(生产级首选)

手动写法冗余且易出错,LangChain 提供 create_agent 快速构建智能Agent,自动完成多轮工具调用、上下文管理、循环推理,是企业开发标准方案。

python 复制代码
from langchain.agents import create_agent
from llm import llm
from tools import tools


# 1. 创建Agent:绑定模型、工具、系统提示
agent = create_agent(
    llm,
    tools,
    system_prompt="你是智能助手,计算问题使用calculator工具,天气查询使用get_weather工具,优先使用工具获取精准结果",
)

# 2. 批量提问,自动调度对应工具
result = agent.invoke({
    "messages": [("user", "北京今天天气怎么样?100乘以50再加20等于多少?")]
})

# 3. 输出完整对话流程和最终答案
print("\n===== 完整对话日志 =====")
for idx, msg in enumerate(result["messages"]):
    print(f"[{idx}] {type(msg).__name__}: {msg.content}")

print("\n===== 最终回答 =====")
print(result["messages"][-1].content)

总结

  1. LangChain工具调用的核心是标准化封装+模型绑定+智能调度,@tool装饰器实现Python函数到大模型可识别工具的协议转换;

  2. 手动解析方案适合原理学习与调试,Agent自动执行是生产环境首选,大幅简化多轮工具调用逻辑;

  3. 工具描述、类型注解、异常处理是保障工具稳定调用的三大核心规范。

相关推荐
swipe1 小时前
做多轮对话 Agent,为什么我建议把短期记忆放到 Redis
后端·面试·llm
swipe2 小时前
别再把关系库和向量库拆开了:PostgreSQL 搭建 AI 长期记忆层实战
面试·langchain·llm
元Y亨H4 小时前
大数据转大模型(LLM)进阶学习路线图
大数据·llm
喵叔哟5 小时前
Week 3 -- Day 1:LangGraph 入门
langchain
wuhen_n6 小时前
RAG 实战:语义检索 + 大模型生成精准问答
前端·langchain·ai编程
秦jh_7 小时前
【LangChain核心组件】少样本提示(示例选择器)
人工智能·python·langchain
VipSoft7 小时前
LangChain 入门 Memory 会话记忆
langchain
眠りたいです8 小时前
LangChainv1:agent快速上手与中间件认识
人工智能·python·中间件·langchain·langgraph