兰 亭 墨 苑
期货 · 量化 · AI · 终身学习
首页
归档
编辑文章
标题 *
URL 别名 *
内容 *
(支持 Markdown 格式)
下面给你一份「从零开始」的 Google Gemini 函数调用(Function calling)使用笔记,以 Python 代码为主,涵盖最常用的「自动生成 JSON Schema→注册函数→让模型决定调不调用→把结果喂回去继续生成」四步流程。不管你用的是免费版 Gemini 1.5 Flash / Pro,还是 v1beta 新模型,流程都是一致的。 ──────────────────── 0. 前置准备 ──────────────────── pip install -q google-generativeai # 如果你在中国大陆,代理 / VPN 是必须条件。 export GOOGLE_API_KEY="你的KEY" ──────────────────── 1. 声明可被调用的函数 ──────────────────── 记住,Gemini 只负责「产生 JSON 调用参数」,真正的执行代码一定要由你在本地或云端跑。 下面例子写两个道具函数:实时查汇率、查当前天气。 ```python import google.generativeai as genai import datetime, requests genai.configure(api_key="你的KEY") # ------------ 函数1:汇率 ------------ def get_exchange_rate(base: str, target: str) -> float: """ 查询 base->target 的实时汇率(依赖免费 demo API) """ url = f"https://api.exchangerate.host/latest?base={base}" data = requests.get(url, timeout=5).json() return data["rates"].get(target.upper()) # ------------ 函数2:天气 ------------ def get_current_weather(location: str, unit="celsius") -> str: """ 伪·天气查询;真正生产环境应调用和风、OpenWeatherMap 等 """ mock_weather = { "北京": {"temp": 32, "unit": unit}, "上海": {"temp": 30, "unit": unit}, } info = mock_weather.get(location, {"temp": 22, "unit": unit}) return f"{location} 当前 {info['temp']}°{info['unit'][0].upper()}" ``` ──────────────────── 2. 写成 OpenAPI-like JSON Schema ──────────────────── 这是 2024 年 6 月新 API 的一致做法:把每个函数元数据写进 tools=[{"function_declarations": [...]}] 里即可。 ```python tools = [ { "function_declarations": [ { "name": "get_exchange_rate", "description": "查询两种货币之间的实时汇率。", "parameters": { "type": "object", "properties": { "base": {"type": "string", "description": "基准货币代码,如 USD、CNY"}, "target": {"type": "string", "description": "目标货币代码"} }, "required": ["base", "target"] } }, { "name": "get_current_weather", "description": "根据城市名称查询当前天气", "parameters": { "type": "object", "properties": { "location": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "default": "celsius"} }, "required": ["location"] } } ] } ] ``` ──────────────────── 3. 建立模型 & 聊天并“截获”调用意图 ──────────────────── 核心就是 loop: (1) 发用户问题 → (2) 收到 `function_call` → (3) 本地跑函数 → (4) 把函数结果以 `function_response` 形式再发回去 → (5) Gemini 基于返回值继续生成自然语言答案。 ```python model = genai.GenerativeModel( model_name="gemini-1.5-flash", tools=tools ) chat = model.start_chat(enable_automatic_function_calling=False) # 我们手动控制循环 user_message = "10 USD 能换多少人民币?顺便告诉我北京现在多少度?" # ---------- 第一回合 ---------- resp1 = chat.send_message(user_message) print("第一轮模型回复候选:", resp1.candidates[0].content.parts) # Gemini 可能一次就想调用多个函数,所以 parts 里会有多个 FunctionCall for part in resp1.candidates[0].content.parts: if fn_call := part.function_call: name = fn_call.name args = {k: v for k, v in fn_call.args.items()} print(f"模型想调用的函数:{name}({args})") # 真正在本地跑 if name == "get_exchange_rate": ret = get_exchange_rate(**args) elif name == "get_current_weather": ret = get_current_weather(**args) # 把结果封装成 function_response,发送回模型 chat.send_message( genai.protos.Content( parts=[genai.protos.Part( function_response=genai.protos.FunctionResponse( name=name, response={"result": ret} ) )] ) ) # ---------- 第二回合(自然语言回答) ---------- final = chat.send_message("请把上面结果用中文一句话总结。") print(final.text) ``` 运行示例输出: ``` 10 USD ≈ 72.4 CNY, 北京目前 32°C ``` ──────────────────── 4. 让模型“全自动”执行(可选) ──────────────────── 如果你不想手写循环,可以: ```python model = genai.GenerativeModel( model_name="gemini-1.5-flash", tools=tools ) chat = model.start_chat(enable_automatic_function_calling=True) # 让它自己循环! print(chat.send_message("同样的问题").text) ``` 只是要注意真正的函数还是在你本地/云函数里执行,自动模式也只是帮你把上面的四步隐藏掉而已。 ──────────────────── 5. 「工具链」小贴士 ──────────────────── - 当一次问题触发多个函数(上面示例就是 2 个),Gemini 1.5 Flash 已经支持并行 `function_call`。 - 如果模型对参数理解不对,你可以在 description 里加「**绝对不要使用简称,必须传完整参数名**」等提示词。 - 为了提升稳定性,强烈把「系统提示」写出来: ``` system_instruction="你是一个懂得在必要时调用工具提高准确度的助手。" ``` - token 额度:函数声明本身也会占输入 token(但不会占用 Assistant 轮次)。如果接口返回 429,适当减少参数数量、缩短 description。 - json 返回值尽量扁平,不要嵌套三层字典,否则长上下文里容易触发 MalformedFunctionResponse 报错。 ──────────────────── 一句话总结 ──────────────────── 写函数 → 配 JSON Schema → 让 Gemini 生成 FunctionCall → 你写代码执行 → 把返回值扔回聊天上下文。跑来跑去就这么 4 步,剩下的就是工程封装 & 错误兜底。祝你玩得开心!
配图 (可多选)
选择新图片文件或拖拽到此处
标签
更新文章
删除文章