首页/新闻资讯/正文详情

60 天后端转 Agent【02】:Function Calling 到底是怎么落到代码里的?

发布时间:2026/9/27 4:13:09 来源:云帆数科 栏目:资讯中心
60 天后端转 Agent【02】:Function Calling 到底是怎么落到代码里的?
本篇定位这一篇承接上一篇对 LLM API、Messages、Tool Call 和 Agent Loop 的理解不再重复讨论“什么是 Agent”而是把 Tool Call 落地到程序执行层。文章以 Python 为主要示例同时给出 Java / Go 的等价抽象。一、拆解第一篇被折叠的执行链路上一篇我们看到模型可以返回一个工具调用请求。例如{ name: get_weather, arguments: {\city\:\北京\} }这里有一个非常容易忽略的细节在本文采用的 Chat Completions 风格示例中function.arguments 是 JSON 编码后的字符串而不是 Python 字典。程序不能直接把它拿去做关键字参数展开。raw_arguments tool_call.function.arguments args json.loads(raw_arguments)所以从模型输出进入程序之后第一条真正的执行链是Tool Call ↓ arguments 字符串 ↓ json.loads() ↓ Python dict ↓ 参数校验 ↓ 函数调用这一层非常像传统后端接收 HTTP JSON网络层拿到的是序列化数据真正执行业务前仍然需要解析、校验和路由。二、Function Calling 的本质一次动态路由如果把 Function Calling 理解成“大模型直接调用 Python 函数”很容易在后面形成错误的工程思维。更准确的说法是模型生成工具名称和参数宿主程序根据这些数据决定是否执行以及如何执行。对象负责什么Tool Call模型提出的一次结构化调用请求Tool Registry工具名称到 Handler / Function 的受控映射Dispatcher解析、查找、校验、执行并统一处理结果Tool真正访问数据库、API、文件系统或执行计算的业务逻辑LLM ↓ Tool Call ├── Tool Name └── Arguments ↓ Tool Dispatcher ↓ Tool Registry ↓ Handler / Function ↓ Tool Result ↓ LLM因此Function Calling 真正解决的问题不是“让模型执行代码”而是建立一条从“模型生成的结构化意图”到“受控程序执行”的桥梁。三、先把 Python 函数搞懂为什么 **kwargs 能接住模型参数第二篇从函数讲起不是因为 Agent 依赖 Python而是因为 Python 的函数对象和关键字参数机制能够非常直观地展示 Tool Dispatcher 的底层思想。1. 普通函数def get_weather(city: str) - str: return f{city}天气查询结果 result get_weather(北京)2. 位置参数与关键字参数get_weather(北京) get_weather(city北京)Agent 生成的参数天然更接近第二种形式一个“参数名 → 参数值”的映射。3. **kwargs把字典展开成关键字参数args { city: 北京 } get_weather(**args)它可以先理解为get_weather(city北京)所以 Agent 中常见的func(**args)真正表达的是从模型返回的参数字典中取出字段并按照函数的参数名称调用真实函数。4. 函数也是对象def calculator(expr: str) - str: return f计算{expr} f calculator result f(2 3)这里 f 保存的是函数对象本身而不是函数调用结果。正因为函数可以作为值保存我们才能建立 Tool Registry。四、Tool Registry为什么一定要有“工具注册表”假设我们现在有三个工具def get_weather(city: str): ... def calculator(expr: str): ... def search_order(order_id: str): ...模型返回的却只有一个字符串name get_weather程序需要解决的问题是这个字符串应该映射到哪段代码最简单、也最重要的答案就是受控注册表TOOL_MAP { get_weather: get_weather, calculator: calculator, search_order: search_order, }然后func TOOL_MAP.get(name)如果找到func 就是一个可调用对象如果找不到程序应该拒绝执行。为什么不直接根据字符串解释代码因为模型输出本质上是外部输入。Tool Registry 相当于给 Agent 的执行能力建立了一层白名单。模型返回工具名 ↓ 是否存在于受控 Registry ↓ 是 ↓ 找到 Handler ↓ 参数校验 ↓ 执行从更抽象的后端设计来看这与 Handler Mapping、RPC Method Registry、Command Pattern 中的“名称 → 执行器”思想是相通的。五、Tool Dispatcher真正把 Function Calling 接起来有了函数和 Tool Registry下一步就是把模型返回的 Tool Call 变成一次真正的工具调用。这个角色就是 Tool Dispatcher。一个最小版本可以这样写import json def dispatch_tool(name: str, raw_arguments: str, tool_map: dict) - str: func tool_map.get(name) if func is None: return f未知工具{name} try: args json.loads(raw_arguments) except json.JSONDecodeError as exc: return f参数 JSON 错误{exc.msg} try: result func(**args) return str(result) except TypeError as exc: return f参数错误{exc} except Exception as exc: return f工具执行失败{exc}这个版本虽然还不是生产级 Runtime但已经把最重要的职责分离出来查找工具、解析参数、执行函数、处理异常。一次调用逐行拆解假设模型返回name get_weather raw_arguments {city:北京}第一步工具查找。func tool_map.get(name)第二步JSON 反序列化。args json.loads(raw_arguments)第三步关键字参数展开。result func(**args)于是func get_weather args {city: 北京} func(**args) # 等价理解 get_weather(city北京)六、参数校验JSON 合法不代表参数合法这是 Tool Runtime 从 Demo 走向工程代码的第一个关键节点。json.loads() 只能回答“这是不是合法 JSON”不能回答“这些字段是否符合函数和业务的要求”。例如工具def get_weather(city: str): ...模型可能返回{}或者{ city: 北京, foo: bar }还可能返回类型不符合预期的数据。于是应当把流程拆成模型输出 ↓ JSON Parse ↓ 字段检查 ↓ 类型 / 必填项 / 范围 ↓ 权限与业务约束 ↓ Tool Execution注意Python 的类型注解本身不等价于完整的运行时参数校验。inspect.signature读取函数签名import inspect def search_order(order_id: str, limit: int 10): ... signature inspect.signature(search_order) print(signature) (order_id: str, limit: int 10)进一步可以使用 bind() 检查参数能否按照函数签名进行绑定signature.bind(order_id10001, limit5)在生产级 Python Agent Runtime 中如果工具数量增加、参数结构变复杂仅依赖 inspect.signature() 做绑定检查通常还不够。更常见的做法是把“工具参数”提升为明确的数据模型在进入工具执行前使用强类型约束进行自动化类型解析与校验并进一步叠加业务规则校验Python 工程中常见的方案就是 Pydantic BaseModel。例如可以使用 Pydantic 的 BaseModel 定义工具入参from pydantic import BaseModel, Field class WeatherArgs(BaseModel): city: str Field(min_length1) unit: str celsius args WeatherArgs.model_validate({ city: 北京, unit: celsius })这样做的价值在于JSON 解析、字段类型、默认值以及更复杂的字段约束可以从“手写 if/else”中进一步抽离出来。对于 Java / Go 开发者可以把它理解为更接近 DTO Validator 的思路而不是单纯依赖 Python 的动态参数绑定。因此可以把参数校验分成三个层次JSON Parse 负责“能不能解析”函数签名负责“能不能绑定”Pydantic / 业务 Validator 负责“数据是否满足类型与业务约束”。它非常适合帮助我们理解“工具接口定义”与“函数真实签名”之间的关系但它不是完整的业务安全校验。Tool Schema 与 Python FunctionPython Function ↓ 函数名 / 参数 / 类型 / 默认值 ↓ Tool Schema ↓ LLM ↓ Tool Call所以 Tool Schema 本质上可以理解为将程序函数的接口信息转换成模型能够理解的工具描述。七、最容易漏掉的协议细节tool_call_id 与消息顺序当模型发起一次 Tool Call 时调用本身需要有一个标识。例如id: call_123程序执行完工具后需要把结果与这次调用对应起来。在本文采用的 Chat Completions 风格流程中可以用 tool_call_id 关联assistant message └── tool_calls └── id call_123 ↓ tool message └── tool_call_id call_123消息历史应体现出“模型先提出调用、程序再返回结果”的顺序而不是只把一个孤立的 Tool Result 塞回去。完整的消息关系是User ↓ Assistant tool_calls ↓ Tool tool_call_id ↓ Assistant / Final Answer这个细节之所以重要是因为 Tool Result 必须能在上下文中明确对应到哪一次模型调用。多工具调用场景下这一点尤其重要。八、异常处理Tool 出错不等于 Agent 必须崩溃Agent Runtime 需要把“模型失败”和“工具失败”区分开。比如数据库超时不代表模型能力有问题一个未知工具也不代表整个用户请求必须直接让进程崩溃。失败位置示例典型处理Tool Lookup未知工具拒绝执行并记录JSON Parse非法 JSON返回明确解析错误Parameter Validation缺少必填参数不执行工具返回参数错误Tool ExecutionDB / RPC 超时按业务决定是否有限重试Permission无权执行直接拒绝Side Effect已下单 / 已扣款确认幂等性后再决定是否重试“把异常 catch 住”不是完整的异常处理。真正的工程问题是这个错误应该让谁知道是否可以重试是否需要降级是否已经产生副作用九、Java / Go / Python语言不同Tool Runtime 抽象不变如果你主要使用 Java 或 Go不需要把这篇文章当成 Python 入门课。重点是理解统一的抽象Tool Name ↓ Registry ↓ Handler / Function ↓ Arguments ↓ Execute ↓ ResultPythonTOOL_MAP { get_weather: get_weather, } func TOOL_MAP[get_weather] result func(city北京)JavaMapString, ToolHandler tools Map.of( get_weather, this::getWeather ); ToolHandler handler tools.get(get_weather); Object result handler.execute(args);Gotools : map[string]func(string) string{ get_weather: getWeather, } handler : tools[get_weather] result : handler(北京)你会发现三种语言最终都在解决同一个问题把“模型返回的字符串工具名”映射成一个受控的执行器。十、实战手写一个 Mini Tool Runtime这一篇不再直接上 LangChain。先用最少的代码自己把 Tool Runtime 跑通。项目结构mini-tool-runtime/ ├── main.py ├── tools.py ├── registry.py ├── dispatcher.py └── tests.py建议按四个 Level 完成。Level 1函数调用def get_weather(city: str) - str: return f{city}今天晴天 get_weather(北京)完成标准函数定义正确、参数能够传入、返回值能够拿到。常见坑把“函数对象”和“函数调用结果”混在一起把类型注解误认为运行时校验。Level 2Tool RegistryTOOL_MAP { get_weather: get_weather, } func TOOL_MAP[get_weather]完成标准能够从工具名称找到函数对象并解释 Registry 为什么是受控白名单。常见坑使用模型输出直接拼接代码或解释执行工具名与 Registry 中的名称不一致。Level 3JSON 参数解析与 Dispatchername get_weather arguments {city:北京} result dispatch_tool( name, arguments, TOOL_MAP )完成标准至少覆盖正常工具、未知工具、非法 JSON、缺失参数、多余参数、工具内部异常。常见坑把 JSON 字符串当 dict所有异常都被统一转成“失败”未知工具仍继续执行。Level 4接入真实 LLMUser ↓ LLM ↓ Tool Call ↓ Dispatcher ↓ Tool ↓ Tool Result ↓ LLM上一篇60 天后端转 Agent01别一上来就 LangChain先看懂一次真实的 Tool Call-CSDN博客系列【2026】后端开发怎么转 Agent 60天从入门到精通全网最详细收藏这篇就够了-CSDN博客

相关推荐

九种日光里的蓝牛仔与百褶裙:9组亚洲成年女性高清提示词
九种日光里的蓝牛仔与百褶裙:9组亚洲成年女性高清提示词

五套造型节选:完整穿搭与不同日光。 摘要| 从陶艺门口到书店窗边,用九种日光、九位虚构成年角色,拆解蓝色紧身牛仔裤与成年学院风百褶裙的真实摄影感。每张图都附可复制提示词与摄影变量。 ✦ ① 好看的日光,先有能解释… · 2026/9/27 4:13:09

解析 strands-agents Python SDK v0.1.9:从结构化输出到可观测性与 A2A 集成的版本演进
解析 strands-agents Python SDK v0.1.9:从结构化输出到可观测性与 A2A 集成的版本演进

人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务 【免费下载链接】harness-sdk Build an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python & TypeScript - any model, any cloud. 项目地址: https://… · 2026/9/27 4:13:03

3招搞定ui素材网站安全漏洞项目经理必看最佳实践
3招搞定ui素材网站安全漏洞项目经理必看最佳实践

3招搞定ui素材网站安全漏洞项目经理必看最佳实践 自己不会代码想做网站,但怕被黑客黑?别慌,我干了10年建站,见过太多项目经理因为不懂安全,把辛辛苦苦做出来的ui素材网站搞成提款机。今天不讲虚的,直接给你拆解那些让你半夜惊醒的安全坑,用阿里… · 2026/9/27 4:13:03

【领域篇14】金融科技与风控领域效能评估:100 个典型应用场景全景梳理(附分类体系)
【领域篇14】金融科技与风控领域效能评估:100 个典型应用场景全景梳理(附分类体系)

目录 一、为什么金融科技不能只评“模型准确率” 二、金融科技效能评估的 7 维分类体系 二、金融科技效能评估的 7 维分类体系 三、100 个典型应用场景全景图 第一类:信用评分与信贷审批(1–10) 第二类:交易反欺诈与支付风控… · 2026/9/27 5:39:49

LTX-2 量化感知蒸馏(QAD)实战:在原生 LTX 训练循环中用 Model Optimizer 融合 NVFP4 校准与知识蒸馏
LTX-2 量化感知蒸馏(QAD)实战:在原生 LTX 训练循环中用 Model Optimizer 融合 NVFP4 校准与知识蒸馏

人工智能大模型模型优化模型量化模型压缩 【免费下载链接】Model-Optimizer A unified library of SOTA model optimization techniques like quantization, distillation, pruning, neural architecture search, speculative decoding, etc. It compresses deep learning mode… · 2026/9/27 5:39:43

NetWatch深度包检测实战:15种L7协议解码器全解析,从SNI提取到QUIC/HTTP3重组
NetWatch深度包检测实战:15种L7协议解码器全解析,从SNI提取到QUIC/HTTP3重组

NetWatch深度包检测实战:15种L7协议解码器全解析,从SNI提取到QUIC/HTTP3重组 【免费下载链接】netwatch Real-time network diagnostics in your terminal. One command, zero config, instant visibility. 项目地址: https://gitcode.com/gh_mirrors/… · 2026/9/27 5:39:00

拒绝被坑:3步搞定wordpress形式官网,免费工具全揭秘
拒绝被坑:3步搞定wordpress形式官网,免费工具全揭秘

拒绝被坑:3步搞定wordpress形式官网,免费工具全揭秘 找建站公司怕被坑高价,是很多中小企业主的噩梦。市面上报价从几千到几万不等,交付周期拖沓,后期维护更是无底洞,让人避之不及。其实,用 wordpress形式 搭建官网,配合… · 2026/9/27 5:38:54

做国际英文网站别只拼价格,3个维度对比评测帮你省下10万设计费
做国际英文网站别只拼价格,3个维度对比评测帮你省下10万设计费

做国际英文网站别只拼价格,3个维度对比评测帮你省下10万设计费 做外贸站的老板们,是不是经常盯着那些几百块的模板网站直皱眉?页面排版挤得像早高峰的地铁,字体小得看不清,颜色花里胡哨却毫无逻辑,客户点开两秒就关掉了。 模板网站太丑不够用… · 2026/9/27 5:38:54

微波简答题实战指南:从电磁场到S参数的物理直觉构建
微波简答题实战指南:从电磁场到S参数的物理直觉构建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 5:38:36

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码