FunctionGemma工作流实战

我们都有过与本地LLM相关的特定挫败点。聊天很有趣。总结很有用。但最终,你希望模型实际上做点什么。你希望它获取数据、运行计算或查询数据库——而不会出现语法幻觉。

长期以来,可靠的“函数调用”一直是大型封闭源代码模型(如GPT-4)的专属领域。如果你试图强迫一个标准的7B模型输出严格的JSON用于函数调用,你经常会得到损坏的括号或混合了对话填充的代码。

进入 FunctionGemma

谷歌发布了这些专门的Gemma变体,明确训练用于工具使用。当与 Ollama 配对时,你可以构建一个本地代理,能够以惊人的可靠性处理复杂、多部分的查询,在一次操作中完成。

在这篇指南中,我将向你展示如何构建一个脚本,处理复杂的请求——检查天气、股票价格和计算健康指标——全部在一个过程中完成,完全在你的机器上运行。

1、为什么FunctionGemma是游戏规则改变者

如果你尝试过使用标准模型(如Llama 3或Mistral)构建代理,你就会知道其中的挣扎。你必须强烈地进行提示工程: “请仅输出JSON。不要说话。” 而且一半的时间,它们仍然失败。

FunctionGemma解决了这个问题,但好处不仅限于可靠性:

  1. 计算效率(不需要GPU农场): 你不需要用大锤子砸坚果。FunctionGemma有轻量级的尺寸(如2B和9B)。因为这些模型是专门为工具使用而不是“知道宇宙中的一切”而设计的,它们在消费级硬件上运行得非常快——即使是在标准CPU上。你可以在MacBook Air或Raspberry Pi上运行高频代理循环,而不会出现70B参数模型的延迟。
  2. 成本效益(零API费用): 在OpenAI或Anthropic上构建代理会很快变得昂贵。代理工作流程通常需要“思考”和“反思”,这会消耗大量token。在开发和测试阶段,你可能需要运行脚本500次来修复一个bug,云成本会迅速增加。FunctionGemma在本地免费运行。你可以每小时向模型发送数千个请求,而你的唯一成本是电力。
  3. 并行执行: 如果你问两个不同的问题,标准模型往往会冻结或依次回答。FunctionGemma可以同时触发多个工具调用,大大减少用户等待答案的总时间。
  4. 严格类型: 它比大多数通用模型更好地尊重你Python函数中的类型提示(字符串、浮点数、布尔值),这意味着当你的代码尝试解析参数时,出现的运行时错误更少。

2、环境搭建

你需要安装Python并在你的机器上运行Ollama。

  1. 拉取模型: 打开终端并获取模型(它轻量且高效):
ollama pull functiongemma

2. 安装依赖项: 我们使用标准的Ollama库和rich用于可读的终端输出。

pip install ollama rich

3、实现代码

这是完整的实现。我将其结构化为模块化,以便以后可以替换你自己的API。

3.1 定义工具

这里最关键的部分是文档字符串。LLM通过文档字符串来理解何时使用该工具以及参数的含义。

import json  
from rich import print  
from ollama import chat  

# 专为工具使用优化的特定模型变体  
model = 'functiongemma'  

# --- 工具 ---  

def get_weather(city: str) -> str:  
  """  
  获取城市的当前天气。  
  参数:  
    city: 城市名称  
  """  
  # 演示用的模拟数据  
  return json.dumps({  
      'city': city,   
      'temperature': 22,   
      'unit': 'celsius',   
      'condition': 'sunny'  
  })  

def calculate_bmi(weight: float, height: float) -> str:  
  """  
  计算身体质量指数(BMI)。  
  参数:  
    weight: 千克(kg)  
    height: 米(m)  
  """  
  bmi = weight / (height * height)  
  return json.dumps({  
      'bmi': round(bmi, 2),   
      'status': 'Normal' if 18.5 <= bmi <= 24.9 else 'Check Chart'  
  })  

def get_stock_price(ticker: str) -> str:  
  """  
  获取给定股票代码的当前股价。  
  参数:  
    ticker: 股票符号(例如,AAPL,MSFT)  
  """  
  # 模拟数据  
  prices = {'AAPL': 150.00, 'GOOGL': 2800.00, 'MSFT': 400.00}  
  price = prices.get(ticker.upper(), 0.00)  
  return json.dumps({'ticker': ticker, 'price': price, 'currency': 'USD'})

3.2 执行循环

这是代理的“大脑”。我们定义可用的工具,将它们传递给Ollama,并处理响应。

请注意我使用的输入提示:它干净、直接,并包含三个不同的意图,以压力测试模型的并行能力。

# 将字符串名称映射到实际函数以执行  
available_tools = {  
    'get_weather': get_weather,  
    'calculate_bmi': calculate_bmi,  
    'get_stock_price': get_stock_price  
}  

# 一个复杂、多意图的提示  
user_prompt = (  
    "班加罗尔的当前天气是什么? "  
    "另外,检查微软的股票价格,并 "  
    "计算体重70公斤、身高1.75米的人的BMI。"  
)  

messages = [{'role': 'user', 'content': user_prompt}]  
print(f"[bold yellow]提示:[/bold yellow] {messages[0]['content']}")  

# 1. 将查询发送给Ollama并定义工具  
response = chat(  
    model,   
    messages=messages,   
    tools=[get_weather, calculate_bmi, get_stock_price]  
)  

if response.message.tool_calls:  
  # 2. 遍历工具调用(FunctionGemma支持并行调用)  
  for tool in response.message.tool_calls:  
    print(f'\n🔹 模型请求了工具: [bold cyan]{tool.function.name}[/bold cyan]')  
    print(f'   参数: {tool.function.arguments}')  

    # 3. 查找并执行  
    function_to_call = available_tools.get(tool.function.name)  

    if function_to_call:  
      # 解包参数 (**kwargs) 并运行  
      result = function_to_call(**tool.function.arguments)  
      print(f'   结果: [green]{result}[/green]')  

      # 4. 添加历史记录  
      # 我们将模型的请求和工具的输出添加到历史记录中  
      messages.append(response.message)  
      messages.append({'role': 'tool', 'content': result})  
    else:  
      print(f"[red]错误: 函数 {tool.function.name} 未找到[/red]")  

  # 5. 最终综合  
  # 将所有工具输出返回给模型以生成自然语言摘要  
  final = chat(model, messages=messages)  
  print('\n[bold]最终响应:[/bold]', final.message.content)  

else:  
  # 标准聊天的备用方案  
  print('响应:', response.message.content)

4、输出

当你运行这个脚本时,你不会得到一个“这里是如何做到的”的通用回答。你会得到实际的执行。

模型解析自然语言,意识到它需要三个不同的工具,并并行发出调用:

  1. 提取位置: “班加罗尔”用于 get_weather
  2. 识别实体: “微软”(映射到上下文)用于 get_stock_price
  3. 解析指标: 70和1.75用于 calculate_bmi

最终响应无缝地将这些不同的数据点结合在一起:

“班加罗尔目前天气晴朗,温度为22°C。微软(MSFT)的交易价格为400.00美元。对于体重70公斤、身高1.75米的人来说,BMI为22.86,属于正常范围。”

5、结束语

本地代理不再是科学实验。有了像 functiongemma 和 Ollama 这样的模型和运行器,你可以构建可靠、私有且快速的自动化工具。

你获得了结构化API的可靠性,同时又具备LLM的灵活性,而且全部在你自己的硬件上免费运行。下一次你构建CLI工具或个人助手时,跳过正则表达式,让模型处理逻辑吧。


原文链接:Local AI Agents: Multi-Step Workflows with Ollama and FunctionGemma

汇智网翻译整理,转载请标明出处