> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# FunctionGemma工作流实战
- URL: https://www.hubwiz.com/blog/functiongemma-workflow-in-practice/
- Published: 2025-12-30T04:47:16.000Z
- Updated: 2025-12-30T04:47:16.000Z
- Description: 停止编写正则表达式来解析您的LLM输出。本文介绍如何使用Ollama和FunctionGemma在本地运行确定性、并行工具执行的方法。
- Author: admin
- Tags: AGENT, FUNCTIONGEMMA, #Import 2026-10-14 14:41

我们都有过与本地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](https://abhisheknabhi.medium.com/local-ai-agents-multi-step-workflows-with-ollama-and-functiongemma-a8d18bef53a9?ref=hubwiz.com)

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