原生 Function Calling 闭环原理
抛开三方框架的层层封装,通过最质朴的 Python 代码和原生 SDK。手把手解构大模型与本地系统深度交互的“大循环”运行核心机制,掌握拦截、寻址、执行、喂回的核心闭环。
以下 2 项原为《提示工程技术全景》中的空白项,现作为扩展承载补充至此,对应本节点的工具调用与本地执行能力。
扩展技术承载(弱覆盖)
弱 / 泛化ART (自动推理 + 工具)
在推理过程中自动决定调用外部工具(计算器、检索器、代码执行)获取中间事实,再继续推理,把『推理』与『工具使用』无缝交织。本节点原生 Function Calling 闭环正是 ART 的工程落地:模型决定调哪个工具,我们只在执行兜底。
- 把不可靠的心算/记忆替换为可验证工具结果
- 扩展模型能力边界
- 工具声明与参数拦截需谨慎
- 工具失败需自愈兜底
PAL (程序辅助推理)
让模型生成可执行程序(如 Python)来表达推理步骤,借助解释器运行得到精确答案,常用于数学/符号计算。本节点的『本地执行』环节即 PAL 思想:模型产出代码,运行时执行并把结果喂回。
- 数值与逻辑精确
- 可复用既有代码生态
- 代码需沙箱执行
- 错误处理较复杂
PAL 真演练场(强覆盖)
真实沙箱执行与上方承载卡不同,这里是 真·演练场: 选好问题后,下方的 JavaScript 会在浏览器 受限沙箱 中真实执行,结果由运行时计算得出(而非预写死的字符串)。这正是 PAL「用代码执行替代不可靠心算」的核心价值。
print(sum(range(1, 101))) # => 5050
PAL 论文中模型产出的是 Python;本演练场用等价的 JavaScript 在浏览器沙箱中真实运行, 思想完全一致——把推理步骤编码为可执行的程序。
点击上方按钮,代码将在此真实运行
ART 真演练场(强覆盖)
推理 × 工具交织与上方承载卡不同,这里是 真·演练场: ART 把「推理」与「工具调用」无缝交织——模型在思考中 真实决定何时调用工具, 工具(计算器 / 贷款计算) 真实执行并返回数值,模型再基于真实结果继续推理。 点「下一步」逐步展开,或「一键跑完全程」。
进度:0 / 5 步。注意交替出现的「Thought(推理)」与「Tool(真实执行)」。
点击「运行下一步」开始交织推理
{
"name": "get_weather",
"description": "获取指定城市的实时天气预报",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名称,例如北京、上海" }
},
"required": ["city"]
}
}# 准备就绪,请选择上方场景点击启动模拟 # 您也可以切换到上方【代码蓝图】标签,阅读无框架的完整可运行底层事件循环。
import os
from google import genai
from google.genai import types
# 1. 声明本地 Python 工具函数
def get_weather(city: str) -> str:
"""获取指定城市的实时天气预报"""
# 真实的本地函数,执行网络请求或数据库查询
if "北京" in city:
return "北京明日天气:晴转多云,22°C ~ 31°C,微风。"
return f"{city}明日天气状况良好。"
def calculate_tax(income: float, region: str) -> str:
"""计算中国不同地区的个人所得税"""
taxable = max(0.0, income - 60000)
tax = taxable * 0.1 - 2520
return f"针对{region}地区,年薪 {income} 元的个税计算结果为:实际应纳税额 {tax:.2f} 元。"
# 建立工具名称到函数的物理映射,供拦截后寻址
tool_map = {
"get_weather": get_weather,
"calculate_tax": calculate_tax
}
# 2. 初始化原生 SDK (未封装框架)
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
def run_pure_tool_loop(user_prompt: str):
print(f"User: {user_prompt}")
# 将真实的 Python 函数作为 tools 传入,SDK 会自动解析函数签名生成 JSON Schema 声明
# 对应的就是 [阶段 1: API Tool 声明]
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=user_prompt,
config=types.GenerateContentConfig(
tools=[get_weather, calculate_tax]
)
)
# 模拟手写运行时事件循环 (Event Loop)
chats = [{"role": "user", "parts": [user_prompt]}]
# [阶段 2: 拦截与识别 <tool_call>]
if response.function_calls:
print("\n🤖 模型生成了 Tool Call 申请!")
# 复制第一轮 assistant 响应到对话历史中
chats.append(response.candidates[0].content)
# 遍历所有的 tool_call 请求并依次在本地拦截执行
for call in response.function_calls:
print(f"📥 正在解析函数: {call.name}, 参数: {call.args}")
# [阶段 3: 本地运行时拦截寻址执行]
if call.name in tool_map:
# 动态执行本地函数并安全获取返回值
local_func = tool_map[call.name]
execution_result = local_func(**call.args)
print(f"🔌 本地执行结果: {execution_result}")
# [阶段 4: 结果喂回上下文]
# 构造符合规范的 'tool' 角色回复消息
tool_response = types.Part.from_function_response(
name=call.name,
response={"result": execution_result}
)
chats.append(types.Content(
role="tool",
parts=[tool_response]
))
# [阶段 5: 模型融合成最终回复]
# 将携带了 Tool 执行结果的完整会话上下文,重新喂回给大模型
final_response = client.models.generate_content(
model='gemini-2.5-flash',
contents=chats,
config=types.GenerateContentConfig(
tools=[get_weather, calculate_tax]
)
)
print(f"\n💬 Final Assistant: {final_response.text}")
else:
print(f"💬 Direct Assistant: {response.text}")
if __name__ == "__main__":
run_pure_tool_loop("查询北京明天的天气")
os.environ["GEMINI_API_KEY"] 设定为您在 AI Studio 的 API Key,并执行此脚本,您即可在终端内真实打印出以上 5 步闭环日志,感受到程序与模型深度融合的“手写”魅力!