-
01. bind()与bind_tools()
我们在 OpenAI 的 GPT 模型如何添加工具的描述参数,即在实例化的时候传递多一个 tools 参数,如下:
completion = client.chat.completions.create(
model="gpt-3.5-turbo-16k",
messages=messages,
tools=tools,
tool_choice="auto"
)
其实除了上面的这些参数,我们还可以传递 temperature 温度参数,这些参数本质上都是模型生成内容时传递的 运行时参数,所以在 LangChain 中,我们可以使用 convert_to_openai_tool 将自定义工具转换成符合 GPT 模型的参数格式,使用 .bind() 函数来传递对应的 tools 和 tool_choice,从而完成对大语言模型函数的绑定。
运行流程如下:
-

不过由于上述的步骤太过于常见,所以 LangChain 团队单独对支持 函数调用 的大语言模型添加了 .bind_tools() 函数,可以快捷地完成此操作,例如 GPT 模型的 .bind_tools() 函数的核心代码如下
def bind_tools(
self,
tools: Sequence[Union[Dict[str, Any], Type[BaseModel], Callable, BaseTool]],
*,
tool_choice: Optional[
Union[dict, str, Literal["auto", "none", "required", "any"], bool]
] = None,
**kwargs: Any,
) -> Runnable[LanguageModelInput, BaseMessage]:
formatted_tools = [convert_to_openai_tool(tool) for tool in tools]
if tool_choice:
if isinstance(tool_choice, str):
tool_choice is a tool/function name
if tool_choice not in ("auto", "none", "any", "required"):
tool_choice = {
"type": "function",
"function": {"name": tool_choice},
}
'any' is not natively supported by OpenAI API.
We support 'any' since other models use this instead of 'required'.
if tool_choice == "any":
tool_choice = "required"
elif isinstance(tool_choice, bool):
tool_choice = "required"
elif isinstance(tool_choice, dict):
tool_names = [
formatted_tool["function"]["name"]
for formatted_tool in formatted_tools
]
if not any(
tool_name == tool_choice["function"]["name"]
for tool_name in tool_names
):
raise ValueError(
f"Tool choice {tool_choice} was specified, but the only "
f"provided tools were {tool_names}."
)
else:
raise ValueError(
f"Unrecognized tool_choice type. Expected str, bool or dict. "
f"Received: {tool_choice}"
)
kwargs["tool_choice"] = tool_choice
return super().bind(tools=formatted_tools, **kwargs)
02. LLM绑定天气预报与谷歌实时搜索
例如要将前两节课实现的 天气预报 与 谷歌实时搜索 接入到 GPT 模型中,其实只需要创建好自定义工具后,将自定义工具组装成列表,然后调用 .bind_tools() 函数即可完成 LLM 对函数的绑定,当大语言模型返回的内容携带 函数调用参数 时,可以通过 .tool_calls 属性来获取对应的信息。
例如:将 GPT 模型绑定 天气预报 与 谷歌实时,并且当执行工具调用时,将 工具结果 附加到历史消息列表中,再次传递给大语言模型,让其生成对应的内容,完整代码如下
import json
import os
from typing import Type, Any
import dotenv
import requests
from langchain_community.tools import GoogleSerperRun
from langchain_community.utilities import GoogleSerperAPIWrapper
from langchain_core.messages import ToolMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import Field, BaseModel
from langchain_core.runnables import RunnablePassthrough
from langchain_core.tools import BaseTool
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
class GaodeWeatherArgsSchema(BaseModel):
city: str = Field(description="需要查询天气预报的目标城市,例如:广州")
class GoogleSerperArgsSchema(BaseModel):
query: str = Field(description="执行谷歌搜索的查询语句")
class GaodeWeatherTool(BaseTool):
"""根据传入的城市名查询天气"""
name = "gaode_weather"
description = "当你想询问天气或与天气相关的问题时的工具。"
args_schema: Type[BaseModel] = GaodeWeatherArgsSchema
def _run(self, *args: Any, **kwargs: Any) -> str:
"""运行工具获取对应城市的天气预报"""
try:
1.获取高德API秘钥,如果没有则抛出错误
gaode_api_key = os.getenv("GAODE_API_KEY")
if not gaode_api_key:
return f"高德开放平台API秘钥未配置"
2.提取传递的城市名字并查询行政编码
city = kwargs.get("city", "")
session = requests.session()
api_domain = "https://restapi.amap.com/v3"
city_response = session.request(
method="GET",
url=f"{api_domain}/config/district?keywords={city}&subdistrict=0&extensions=all&key={gaode_api_key}",
headers={"Content-Type": "application/json; charset=utf-8"},
)
city_response.raise_for_status()
city_data = city_response.json()
3.提取行政编码调用天气预报查询接口
if city_data.get("info") == "OK":
if len(city_data.get("districts")) > 0:
ad_code = city_data["districts"][0]["adcode"]
weather_response = session.request(
method="GET",
url=f"{api_domain}/weather/weatherInfo?city={ad_code}&extensions=all&key={gaode_api_key}&output=json",
headers={"Content-Type": "application/json; charset=utf-8"},
)
weather_response.raise_for_status()
weather_data = weather_response.json()
if weather_data.get("info") == "OK":
return json.dumps(weather_data)
session.close()
return f"获取{kwargs.get('city')}天气预报信息失败"
4.整合天气预报信息并返回
except Exception as e:
return f"获取{kwargs.get('city')}天气预报信息失败"
1.定义工具列表
gaode_weather = GaodeWeatherTool()
google_serper = GoogleSerperRun(
name="google_serper",
description=(
"一个低成本的谷歌搜索API。"
"当你需要回答有关时事的问题时,可以调用该工具。"
"该工具的输入是搜索查询语句。"
),
args_schema=GoogleSerperArgsSchema,
api_wrapper=GoogleSerperAPIWrapper(),
)
tool_dict = {
gaode_weather.name: gaode_weather,
google_serper.name: google_serper,
}
tools = [tool for tool in tool_dict.values()]
2.创建Prompt
prompt = ChatPromptTemplate.from_messages([
("system", "你是由OpenAI开发的聊天机器人,可以帮助用户回答问题,必要时刻请调用工具帮助用户解答"),
("human", "{query}"),
])
3.创建大语言模型并绑定工具
llm = ChatOpenAI(model="gpt-3.5-turbo-16k", temperature=0)
llm_with_tool = llm.bind_tools(tools=tools)
4.创建链应用
chain = {"query": RunnablePassthrough()} | prompt | llm_with_tool
5.解析输出
query = "广州现在天气怎样,有什么适合穿的衣服呢"
resp = chain.invoke(query)
tool_calls = resp.tool_calls
6.判断是工具调用还是正常输出结果
if len(tool_calls) <= 0:
print("生成内容:", resp.content)
else:
7.将历史的系统消息、人类消息、AI消息组合
messages = prompt.invoke(query).to_messages()
messages.append(resp)
8.循环遍历所有工具调用信息
for tool_call in tool_calls:
tool = tool_dict.get(tool_call.get("name"))
print("正在执行工具: ", tool.name)
id = tool_call.get("id")
content = tool.invoke(tool_call.get("args"))
print("工具输出: ", content)
messages.append(ToolMessage(
content=content,
tool_call_id=id,
))
print("输出内容: ", llm.invoke(messages))
到这里,你已经构建出了第一个用程序实现的 Agent,这个 Agent 拥有 实时信息搜索 和 天气预报查询 功能,但是有没有发现一个问题,原本我们使用 LECL 表达式构建的链应用是非常优雅的,但是加入了 判断、循环、工具调用 等模块后,维护起来也相对吃力,不过这个问题很快就会解决,在 LangChain 中针对 Agent 应用的创建,目前有两种封装好的策略,一种使用传统 Agent,另外一种使用 LangGraph。
LangChain使用函数调用的技巧与流程
AI Echoes2026-02-11 12:28
相关推荐
九.九9 小时前
ops-transformer:AI 处理器上的高性能 Transformer 算子库春日见9 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新小高不会迪斯科9 小时前
CMU 15445学习心得(二) 内存管理及数据移动--数据库系统如何玩转内存恋猫de小郭9 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑YJlio9 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”deephub9 小时前
Agent Lightning:微软开源的框架无关 Agent 训练方案,LangChain/AutoGen 都能用e***8909 小时前
MySQL 8.0版本JDBC驱动Jar包l1t9 小时前
在wsl的python 3.14.3容器中使用databend包大模型RAG和Agent技术实践9 小时前
从零构建本地AI合同审查系统:架构设计与流式交互实战(完整源代码)老邋遢9 小时前
第三章-AI知识扫盲看这一篇就够了