问题与目标
模型自身不能查询实时设备状态或修改工单。Function Calling(也常称 Tool Calling)让模型根据工具 Schema 提出“调用哪个工具、使用什么参数”,应用再决定是否允许和执行。
本篇只完成一次受控闭环:用户提问、模型提出调用、应用白名单匹配与参数校验、执行结果回传、模型整理最终答案。不加入循环规划和 Agent;涉及写操作时必须增加授权、确认与幂等控制。
核心概念
工具由两部分组成:
- Schema:名称、用途、参数类型、必填项和约束,供模型选择和构造参数;
- Executor:真正执行查询或操作的受信任代码。
模型返回的 Tool Call 只是候选请求,不是已经执行的事实。应用必须执行:工具白名单、Schema 校验、身份与资源权限、超时、结果大小限制、审计和危险操作确认。
可运行实现
python -m pip install "langchain>=1,<2" "langchain-openai>=1,<2" "pydantic>=2,<3"
from typing import Literal
from pydantic import BaseModel, Field, ValidationError
from langchain_core.messages import HumanMessage, ToolMessage
class DeviceQuery(BaseModel):
device_id: str = Field(pattern=r"^AX-\d{1,4}$")
field: Literal["status", "temperature"]
def query_device(device_id: str, field: str) -> dict:
"""查询指定设备的状态或温度。"""
database = {"AX-3": {"status": "online", "temperature": 41.2}}
if device_id not in database:
return {"found": False}
return {"found": True, "device_id": device_id, field: database[device_id][field]}
tools = {"query_device": (DeviceQuery, query_device)}
llm_with_tools = model.bind_tools([query_device])
messages = [HumanMessage("AX-3 当前温度是多少?")]
response = llm_with_tools.invoke(messages)
messages.append(response)
for call in response.tool_calls:
name, args, call_id = call["name"], call["args"], call["id"]
if name not in tools:
output = {"ok": False, "error": "tool_not_allowed"}
else:
schema, executor = tools[name]
try:
validated = schema.model_validate(args)
output = {"ok": True, "data": executor(**validated.model_dump())}
except ValidationError as error:
output = {"ok": False, "error": "invalid_arguments", "detail": error.errors()}
messages.append(ToolMessage(str(output), tool_call_id=call_id))
final = llm_with_tools.invoke(messages)
print(final.text)
实际应用应使用 JSON 序列化工具结果,并限制返回字段;示例用 str() 只是缩短代码。若模型没有提出工具调用,可以直接处理其文本回复,但仍要检查该问题是否按业务规则必须查询实时数据。
常见问题与排查
模型返回工具名后直接用反射执行
只从显式白名单取 Executor,绝不根据模型字符串动态导入模块或执行表达式。工具描述也不能扩大当前用户权限。
Schema 校验通过就认为有权限
Schema 只证明 AX-3 格式合法,不证明当前用户可以查看它。执行前根据服务端身份检查资源范围,不能相信模型传来的 user_id。
写工具被重复执行
增加显式确认、幂等键和事务。网络重试、用户刷新或模型重复 Tool Call 都可能造成副作用重放。
工具结果太大
限制行数、字段和字节数,敏感字段脱敏,必要时存储结果并回传受控摘要。不能把整张表塞回上下文。
小结
Function Calling 把语言理解与程序能力连接起来,但信任边界没有交给模型。模型负责建议工具和参数,应用负责验证、授权、执行和审计;坚持这条边界,工具调用才是可控能力而不是远程执行入口。
License: CC BY-NC 4.0
Updated 2 hours ago
Was this article helpful? Give it a like.
0 comments


