三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

智能体面试准备(十八):Function Calling 全链路——Agent 真正动手的最后一公里

智能体面试准备(十八):Function Calling 全链路——Agent 真正动手的最后一公里

智能体面试准备(十八):Function Calling 全链路——Agent 真正"动手"的最后一公里

前面讲了单 Agent(ReAct)、多 Agent(B15)、安全(B16)、规划(B17)。但所有这些要"落地",都绕不开一个最基础也最关键的能力:Function Calling(函数调用)——让 LLM 决定"调哪个工具、传什么参数"。这一篇把全链路从定义到生产跑通:工具 schema 设计 → 模型决策 → 参数解析 → 执行 → 结果回填 → 并行调用与错误处理。每节给:原理 → 代码 → 面试速答 + 高频追问。配合 B14(MCP)看,刚好从"单进程工具"走到"跨进程协议"。


一、Function Calling 在 Agent 链路里的位置

它是 LLM 与外部世界之间的"接口层":

用户意图 │ ▼ ┌─────────┐ ① 选工具+填参 ③ 回填结果 │ LLM │◀────────────────┐ └────┬────┘ │ │ ② tool_call(JSON) │ ▼ │ ┌─────────┐ │ │ 执行器 │──▶ 真实工具/API │ └─────────┘ │ │ ④ observation │ └─────────────────────┘

没它,LLM 只能"说";有它,LLM 才能"做"。


二、工具 Schema:怎么告诉模型有哪些工具

用 JSON Schema 描述每个工具的元信息,喂给模型:

{"name":"get_weather","description":"查询指定城市当前天气","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名,如 '北京'"},"unit":{"type":"string","enum":["celsius","fahrenheit"],"default":"celsius"}},"required":["city"]}}

关键原则:description 写清楚"什么时候用、参数怎么填",模型靠它选工具。描述含糊会导致选错工具或漏填参数。


三、模型决策与参数解析

主流模型(GPT-4o、Qwen、GLM 等)原生支持 function calling,返回结构化的 tool_calls:

importopenai,jsontools=[get_weather_schema,search_schema]# 上面的 JSON Schema 列表resp=openai.chat.completions.create(model="gpt-4o",messages=[{"role":"user","content":"北京今天天气咋样?"}],tools=tools,tool_choice="auto",# auto=模型自选;也可强制指定)msg=resp.choices[0].messageifmsg.tool_calls:forcallinmsg.tool_calls:name=call.function.nameargs=json.loads(call.function.arguments)# 模型填的参数print(name,args)# get_weather {'city':'北京'}

面试速答:tool_choice="auto" 和强制指定有什么区别?auto 让模型自己判断是否调用、调哪个;强制(如 {"type":"function","function":{"name":"x"}})则模型必须调用指定工具,常用于固定流程。


四、执行器:调用真实工具并回填

把模型给的调用转成真实执行,再把结果作为新消息回传给模型:

defdispatch(name,args):ifname=="get_weather":returnreal_weather_api(args["city"])ifname=="search":returnreal_search(args["query"])raiseValueError(f"unknown tool{name}")# 把 assistant 的 tool_call 和 tool 结果都加入上下文messages=[{"role":"user","content":"北京今天天气咋样?"}]resp=openai.chat.completions.create(model="gpt-4o",messages=messages,tools=tools)msg=resp.choices[0].messagemessages.append(msg)# 必须保留带 tool_calls 的 assistant 消息forcallinmsg.tool_calls:result=dispatch(call.function.name,json.loads(call.function.arguments))messages.append({"role":"tool","tool_call_id":call.id,"content":str(result)})final=openai.chat.completions.create(model="gpt-4o",messages=messages,tools=tools)print(final.choices[0].message.content)# 自然语言回答

注意:tool 消息必须带 tool_call_id 且对应 assistant 的 call,否则 API 报错。


五、并行调用与错误处理(生产必备)

5.1 并行调用

模型可以在一次回复里返回多个 tool_call(如"查北京和上海天气"):

calls=msg.tool_callsor[]results=[dispatch(c.function.name,json.loads(c.function.arguments))forcincalls]# 用线程池并发执行真实工具,缩短延迟fromconcurrent.futuresimportThreadPoolExecutorwithThreadPoolExecutor()asex:results=list(ex.map(lambdac:dispatch(c.function.name,json.loads(c.function.arguments)),calls))

5.2 错误处理与兜底

defsafe_dispatch(call):try:returndispatch(call.function.name,json.loads(call.function.arguments))exceptExceptionase:# 把错误作为 observation 回传,让模型自我修正(如换参数/换工具)returnf"ERROR:{type(e).__name__}:{e}。请修正参数或换工具重试。"

把错误回传而非中断,模型往往能纠错(例如把城市名拼写改对)。


六、常见坑与最佳实践

现象对策
参数 JSON 不合法arguments 不是合法 JSON用 json.loads 容错 + 让模型重生成
工具描述含糊选错工具/漏必填写清 description + required
上下文丢 tool_call_idAPI 报不一致严格保留 assistant+tool 消息对
工具执行慢/超时整轮卡住超时熔断 + 并行 + 降级
工具返回过大撑爆上下文截断/摘要后再回填

面试速答:为什么要把工具结果"回填"给模型而不是只执行?因为 LLM 是无状态的,它需要根据工具真实返回继续推理(例如"天气是雨,建议带伞"),不回填模型就不知道结果、无法生成最终回答。


七、面试速答 + 高频追问清单(汇总)

速答 TOP 8:
1. Function Calling 是 LLM 调外部工具的接口层,含 schema→决策→解析→执行→回填。
2. 工具用 JSON Schema 描述,description 决定模型会不会选对。
3. 模型返回 tool_calls(name + arguments JSON)。
4. 执行后必须以 role=tool 且带 tool_call_id 回填上下文。
5. 并行调用:一次返回多个 call,用线程池并发。
6. 错误应回传 observation 让模型自我修正,而非直接中断。
7. tool_choice=auto 让模型自选,也可强制指定。
8. 坑:JSON 不合法、描述含糊、丢 id、返回过大。

追问清单:
- 模型有时不按 schema 填参、编造字段,怎么约束?
- 几十上百个工具时,全塞进 context 会爆,怎么裁剪(tool retrieval)?
- Function Calling 与 MCP(B14)的关系?MCP 解决了什么?
- 流式(streaming)场景下 tool_call 怎么逐步拼装?
- 如何防止模型陷入"反复调用同一工具"的死循环?


八、下一篇预告

Function Calling 讲完"动手的最后一公里",Agent 基础能力(感知-规划-行动-工具-安全)基本闭环。后续可进入B19 RAG 评估B20 可观测性( tracing/logging/评测),把 Agent 从"能跑"推向"可运维"。评论区告诉我优先级。

← 返回列表