📍 无忆研习社 › 开源解码 › Function Gemma 深度解析:仅 270M 参数的轻量模型,如何打造你的本地私人 AI Agent

Function Gemma 深度解析:仅 270M 参数的轻量模型,如何打造你的本地私人 AI Agent

摘要:Google发布仅2.7亿参数的Function Gemma,专精于工具调用,能以小博大指挥大模型和外部工具完成复杂任务。本文深度解析其技术原理,并手把手教你本地部署私人AI Agent,实现高效、低成本、隐私安全的智能调度。
字号 100%
行距 2.05
当前可见 60% 的内容
本文由无忆研习社原创首发,站长莫潇羽倾心整理。当大家都在追逐动辄数百亿参数的大模型时,Google 悄然发布了一个仅有 2.7 亿参数的"小家伙"——Function Gemma。它不走寻常路,专精于工具调用领域,却能以四两拨千斤之势,指挥各种大模型和外部工具完成复杂任务。今天,我就带大家深入了解这个轻量级模型的技术原理,并手把手教你如何在本地部署属于自己的私人 AI Agent。

一、前言:AI Agent 的新范式

在 AI 领域,我们常常陷入一个误区:认为模型越大、参数越多就越强大。但实际上,真正的智能不在于"体量",而在于"效率"。一个能精准理解你意图、快速调度各种工具的小模型,往往比一个只会海量输出文本的大模型更具实用价值。

想象一下这样的场景:你对着电脑说"帮我查一下今天的天气,然后总结一下这篇网页的内容"。传统的大模型可能会给你一段看似合理但实际上是"编造"的回答。而一个真正的 AI Agent,应该能够理解你的意图,调用天气 API 获取真实数据,使用爬虫工具抓取网页内容,最后再生成一份精准的总结报告。

这,就是 Function Gemma 要解决的问题。

作为无忆研习社的技术负责人,莫潇羽在深入研究了 Function Gemma 后发现,这个模型代表了 AI 应用开发的一个重要趋势——专精化、轻量化、可组合。下面,让我们一起深入探索这个 Google 开源的技术利器。


二、Function Gemma 的技术背景与定位

2.1 Gemma 家族谱系

在正式介绍 Function Gemma 之前,我们需要先了解它的"家族背景"。大家都知道,Google 有一个超强的闭源模型叫 Gemini,那是运行在云端的超级大脑。但为了让开发者能在本地设备上用上顶尖的 AI 技术,Google 基于 Gemini 的同源技术,打造了一个开源模型家族,取名为 Gemma(拉丁语中意为"宝石")。

Gemma 家族是一套能在本地运行的"特种部队",且分工非常明确:

模型名称

参数规模

核心能力

典型应用场景

Gemma 3

1B / 4B / 12B / 27B

通用文本生成,支持图像输入

聊天对话、内容创作

CodeGemma

2B / 7B

代码补全与生成

编程助手、代码审查

PaliGemma

3B

视觉语言理解

图像描述、视觉问答

RecurrentGemma

2B / 9B

长序列高效推理

长文本处理

MedGemma

4B / 27B

医疗健康领域

医学咨询、健康分析

Function Gemma

270M

工具调用与函数执行

AI Agent 开发

从上表可以看出,Function Gemma 是整个家族中参数量最小的成员,但它的定位却极其特殊——它不是用来聊天的,而是用来"干活"的。

2.2 Function Gemma 是什么

Function Gemma 是 Google DeepMind 团队在 2025 年 12 月发布的一个专精于工具调用(Function Calling / Tool Use)的指令微调模型。它基于 Gemma 3 的 270M 参数版本进行了专门的训练优化。

用通俗的话来说,你可以把 Function Gemma 理解为给你的电脑装上了一个"精明的调度员"。这个调度员不擅长长篇大论,但它特别擅长一件事:听懂你说的话,然后找到合适的工具去执行。

它与传统聊天模型的核心区别在于:

  • 传统聊天模型:接收文本输入 → 生成文本输出
  • Function Gemma:接收自然语言指令 → 输出结构化的函数调用指令(JSON 格式)

举个例子,当你说"查询北京今天的天气"时:

  • 传统模型可能会回复:"北京今天的天气是晴天,温度在 15-25 度之间。"(这很可能是"编造"的)
  • Function Gemma 则会输出:{"name": "get_weather", "parameters": {"city": "北京"}}

后者输出的是一个结构化的指令,可以直接被程序解析并调用真实的天气 API 获取准确数据。

2.3 为什么需要专门的工具调用模型

你可能会问:现在很多大模型都支持 Function Calling 了,为什么还需要一个专门的模型?

这是一个非常好的问题。无忆研习社的莫潇羽认为,答案在于"效率"和"成本"两个维度。

首先是效率问题。大模型虽然功能强大,但它们的推理速度相对较慢,且需要大量的计算资源。在实际应用中,很多场景只需要判断"用户想调用哪个工具",并不需要大模型那么强的语言理解能力。用 270M 参数的小模型来完成这个判断,响应时间可以从数秒缩短到毫秒级别。

其次是成本问题。无论是部署本地大模型还是调用云端 API,都需要不小的开销。如果每次用户输入都要经过大模型处理,成本会非常高昂。而 Function Gemma 可以作为一个"前置路由器",先判断用户意图,只在需要深度理解或生成长文本时才调用大模型,从而大大降低整体成本。

第三是隐私问题。Function Gemma 可以完全在本地运行,意味着敏感数据不需要上传到云端。对于企业级应用来说,这一点尤为重要。


三、Function Gemma 的技术原理深度剖析

3.1 架构设计

Function Gemma 基于 Gemma 3 的基础架构,采用了 Decoder-only 的 Transformer 设计。虽然它与 Gemma 3 共享相同的底层架构,但在以下几个方面进行了专门优化:

  1. 专用的聊天格式(Chat Format):Function Gemma 使用了与标准 Gemma 不同的对话模板,专门为工具调用场景设计。
  2. 特殊的控制标记(Control Tokens):引入了如 <start_function_call>、<end_function_call> 等特殊标记,用于明确标识函数调用的边界。
  3. 结构化输出训练:模型在训练时大量接触了将自然语言转换为 JSON 格式函数调用的数据。

让我们用一个流程图来理解 Function Gemma 的工作机制:

用户输入(自然语言)
       ↓
  Function Gemma 处理
       ↓
  意图识别与解析
       ↓
  ┌────────────────────────┐
  │ 是否需要调用工具?      │
  └────────────────────────┘
       ↓是              ↓否
 输出 JSON 格式       直接回复
 的函数调用指令       (简单应答)
       ↓
  程序解析并执行
  相应的工具函数
       ↓
  获取执行结果
       ↓
 (可选)将结果交给
  大模型进行润色总结
       ↓
  最终回复用户

3.2 工具调用的格式规范

Function Gemma 使用特定的格式来处理工具调用。理解这些格式规范是成功使用该模型的关键。

工具定义格式

当你向 Function Gemma 提供可用工具时,需要使用 JSON Schema 格式来描述每个工具:

{
  "type": "function",
  "function": {
    "name": "get_current_weather",
    "description": "获取指定城市的当前天气信息,包括温度、湿度、天气状况等",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "城市名称,例如:北京、上海"
        },
        "unit": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"],
          "description": "温度单位"
        }
      },
      "required": ["city"]
    }
  }
}

函数调用输出格式

当 Function Gemma 判断需要调用某个工具时,它会输出如下格式的内容:

<start_function_call>call:get_current_weather{city:<escape>北京<escape>,unit:<escape>celsius<escape>}<end_function_call>

这种格式的设计有几个优点:

  • 使用特殊标记明确划定函数调用的边界
  • 参数值使用 <escape> 标记进行包裹,避免与其他文本混淆
  • 格式简洁,易于程序解析

3.3 支持的调用模式

Function Gemma 经过训练,主要支持以下两种调用模式:

1. 单轮调用(Single Turn)

这是最基础的模式。用户提出一个问题,模型选择一个合适的工具来处理。

用户:查询上海现在的天气
模型:<start_function_call>call:get_weather{city:<escape>上海<escape>}<end_function_call>

2. 并行调用(Parallel Calling)

当用户的请求包含多个独立的任务时,模型可以同时输出多个函数调用。

用户:帮我查一下北京和上海的天气
模型:<start_function_call>call:get_weather{city:<escape>北京<escape>}<end_function_call>
      <start_function_call>call:get_weather{city:<escape>上海<escape>}<end_function_call>

需要注意的是,Function Gemma 目前没有针对以下场景进行专门训练(但通过微调可以支持):

  • 多步调用(Multi-Step):一个工具的输出作为另一个工具的输入
  • 多轮对话(Multi-Turn):需要在多轮对话中维护上下文状态

3.4 大小模型混合架构

这是 Function Gemma 最具创新价值的应用模式之一。无忆研习社的莫潇羽在实践中发现,单独使用 Function Gemma 虽然能完成工具调用,但回复往往比较生硬。将它与大模型组合使用,可以实现"1 + 1 > 2"的效果。

这种混合架构的核心思想是:

  • Function Gemma 做"大脑":负责快速判断用户意图、选择合适的工具、生成函数调用指令
  • Python/程序代码做"手脚":负责实际执行函数调用,如发送 API 请求、读取数据库、操作系统等
  • 大模型做"嘴巴":负责对执行结果进行深度分析、总结润色,生成用户友好的回复
用户请求 → Function Gemma(意图判断)→ 工具执行 → 大模型(结果润色)→ 最终回复

这种架构的优势非常明显:

  1. 极速响应:Function Gemma 的推理速度极快,用户几乎感受不到等待
  2. 成本可控:只有在需要润色输出时才调用大模型,减少不必要的 API 调用
  3. 隐私保护:敏感的意图判断在本地完成,只有脱敏后的公开信息才可能发送给云端
  4. 灵活可扩展:可以根据需求替换不同的大模型作为"嘴巴"

四、环境搭建与本地部署详解

理论讲得再多,不如动手实践。接下来,莫潇羽将带大家一步步完成 Function Gemma 的本地部署。

4.1 硬件要求

Function Gemma 的一大优势就是对硬件要求极低。以下是推荐配置:

配置项

最低要求

推荐配置

CPU

4核心

8核心以上

内存

4GB

8GB 以上

显卡

无(CPU 即可运行)

支持 CUDA 的 NVIDIA 显卡

存储

2GB 可用空间

5GB 以上

操作系统

Windows / Linux / macOS

Ubuntu 22.04 / 24.04

是的,你没看错。这个模型可以在普通的笔记本电脑上运行,甚至可以部署到树莓派这样的边缘设备上。这正是"轻量化"理念的体现。

4.2 软件环境准备

步骤 1:安装 Python 环境

推荐使用 Conda 创建一个独立的 Python 环境,避免与系统其他项目产生冲突。

# 如果还没有安装 Conda,可以先安装 Miniconda
# 下载地址:https://docs.conda.io/en/latest/miniconda.html

# 创建名为 functiongemma 的虚拟环境,指定 Python 版本为 3.10
conda create -n functiongemma python=3.10 -y

# 激活环境
conda activate functiongemma

为什么选择 Python 3.10?这是因为目前主流的 AI 框架对 3.10 版本的支持最为稳定,既有较新的语法特性,又能兼容大多数依赖包。

步骤 2:创建项目目录

# 创建项目目录
mkdir ~/functiongemma_demo
cd ~/functiongemma_demo

# 创建必要的子目录
mkdir -p checkpoints  # 存放模型文件
mkdir -p tools        # 存放自定义工具代码
mkdir -p logs         # 存放日志文件

步骤 3:安装核心依赖

# 安装 PyTorch(根据你的硬件选择合适的版本)
# 如果有 NVIDIA 显卡且安装了 CUDA 12.1
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# 如果使用 CPU 运行
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

# 安装 Hugging Face Transformers 和 Accelerate
pip install transformers>=4.51.3
pip install accelerate

# 安装其他常用工具
pip install gradio         # Web 界面框架
pip install requests       # HTTP 请求库
pip install beautifulsoup4 # 网页解析
pip install lxml           # XML 解析

4.3 下载 Function Gemma 模型

Function Gemma 模型托管在 Hugging Face Hub 上,下载前需要先获取访问权限。

步骤 1:注册 Hugging Face 账号

访问 https://huggingface.co 注册账号(如果已有账号则跳过此步)。

步骤 2:接受模型使用协议

访问 https://huggingface.co/google/functiongemma-270m-it ,点击页面上的"Agree and access repository"按钮,接受 Google 的模型使用许可协议。

步骤 3:生成访问令牌

  1. 登录后,点击右上角头像 → Settings → Access Tokens
  2. 点击"New token"创建新令牌
  3. 选择"Write"权限(如果后续要上传微调模型)或"Read"权限
  4. 复制生成的令牌,妥善保存

步骤 4:配置本地认证

# 安装 Hugging Face CLI
pip install huggingface_hub

# 登录(会提示输入令牌)
huggingface-cli login

步骤 5:下载模型

有两种方式下载模型:

方式一:使用 Python 代码下载(推荐)

创建一个 download_model.py 文件:

from huggingface_hub import snapshot_download

# 下载模型到指定目录
snapshot_download(
    repo_id="google/functiongemma-270m-it",
    local_dir="./checkpoints/functiongemma-270m-it",
    local_dir_use_symlinks=False  # 使用实际文件而非符号链接
)

print("模型下载完成!")

运行脚本:

python download_model.py

方式二:使用命令行下载

huggingface-cli download google/functiongemma-270m-it --local-dir ./checkpoints/functiongemma-270m-it

下载完成后,checkpoints 目录下应该包含以下文件:

  • config.json - 模型配置
  • model.safetensors - 模型权重
  • tokenizer.json - 分词器配置
  • 其他配置文件

4.4 基础使用示例

现在,让我们编写一个简单的测试脚本来验证模型是否正常工作。

创建 test_basic.py 文件:

import torch
from transformers import AutoProcessor, AutoModelForCausalLM

# 指定模型路径
MODEL_PATH = "./checkpoints/functiongemma-270m-it"
# 或者直接使用 Hugging Face 模型 ID
# MODEL_PATH = "google/functiongemma-270m-it"

print("正在加载模型...")

# 加载 processor 和模型
processor = AutoProcessor.from_pretrained(MODEL_PATH)
model = AutoModelForCausalLM.from_pretrained(
    MODEL_PATH,
    torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
    device_map="auto"
)

print("模型加载完成!")

# 定义一个天气查询工具
weather_tool = {
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "获取指定城市的当前天气信息",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "城市名称"
                }
            },
            "required": ["city"]
        }
    }
}

# 构建对话消息
messages = [
    {
        "role": "developer",
        "content": "You are a model that can do function calling with the following functions"
    },
    {
        "role": "user",
        "content": "请帮我查询北京今天的天气"
    }
]

# 应用聊天模板
inputs = processor.apply_chat_template(
    messages,
    tools=[weather_tool],
    add_generation_prompt=True,
    return_dict=True,
    return_tensors="pt"
)

# 将输入移动到模型所在设备
inputs = {k: v.to(model.device) for k, v in inputs.items()}

# 生成输出
print("正在生成回复...")
outputs = model.generate(
    inputs,
    max_new_tokens=128,
    pad_token_id=processor.tokenizer.eos_token_id
)

# 解码输出
# 只取新生成的部分
response = processor.decode(
    outputs[0][inputs["input_ids"].shape[1]:],
    skip_special_tokens=True
)

print("\n" + "="*50)
print("模型输出:")
print(response)
print("="*50)

运行测试:

python test_basic.py

如果一切正常,你应该能看到类似这样的输出:

正在加载模型...
模型加载完成!
正在生成回复...

==================================================
模型输出:
<start_function_call>call:get_weather{city:<escape>北京<escape>}<end_function_call>
==================================================

恭喜你!Function Gemma 已经在你的电脑上成功运行了。


五、构建完整的 AI Agent 系统

仅仅能运行模型还不够,我们需要将它整合成一个完整的 AI Agent 系统。无忆研习社的莫潇羽为大家设计了一个包含多个工具的演示系统。

5.1 系统架构设计

我们的演示系统将包含以下组件:

┌─────────────────────────────────────────────────────────────┐
│                      Web 用户界面                            │
│                    (Gradio 框架)                           │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                   意图识别引擎                               │
│              (Function Gemma 模型)                         │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                     工具调度层                               │
│           (解析 JSON、调用对应工具函数)                      │
└───────┬─────────────┬─────────────┬─────────────────────────┘
        │             │             │
    ┌───▼───┐     ┌───▼───┐     ┌───▼───┐
    │天气查询│     │网页抓取│     │系统信息│    ... 更多工具
    │ 工具  │     │ 工具  │     │ 工具  │
    └───────┘     └───────┘     └───────┘

5.2 定义工具函数

首先,让我们创建几个实用的工具函数。创建 tools/my_tools.py 文件:

"""
无忆研习社 - Function Gemma 工具函数集
作者:莫潇羽
"""

import json
import datetime
import subprocess
import requests
from typing import Optional

class ToolBox:
    """工具函数集合类"""

    @staticmethod
    def get_current_date() -> str:
        """
        获取当前日期和时间

        Returns:
            包含当前日期时间信息的 JSON 字符串
        """
        now = datetime.datetime.now()
        result = {
            "date": now.strftime("%Y-%m-%d"),
            "time": now.strftime("%H:%M:%S"),
            "weekday": ["周一", "周二", "周三", "周四", "周五", "周六", "周日"][now.weekday()],
            "timestamp": int(now.timestamp())
        }
        return json.dumps(result, ensure_ascii=False)

    @staticmethod
    def get_gpu_info() -> str:
        """
        获取 GPU 显卡配置信息

        Returns:
            包含 GPU 信息的 JSON 字符串
        """
        try:
            # 使用 nvidia-smi 命令获取显卡信息
            result = subprocess.run(
                ["nvidia-smi", "--query-gpu=name,memory.total,memory.used,memory.free,utilization.gpu,temperature.gpu", 
                 "--format=csv,noheader,nounits"],
                capture_output=True,
                text=True,
                timeout=10
            )

            if result.returncode == 0:
                lines = result.stdout.strip().split('\n')
                gpus = []
                for i, line in enumerate(lines):
                    parts = [p.strip() for p in line.split(',')]
                    if len(parts) >= 6:
                        gpus.append({
                            "gpu_id": i,
                            "name": parts[0],
                            "memory_total_mb": int(parts[1]),
                            "memory_used_mb": int(parts[2]),
                            "memory_free_mb": int(parts[3]),
                            "utilization_percent": int(parts[4]),
                            "temperature_celsius": int(parts[5])
                        })
                return json.dumps({"gpus": gpus, "count": len(gpus)}, ensure_ascii=False)
            else:
                return json.dumps({"error": "无法获取 GPU 信息,可能未安装 NVIDIA 显卡或驱动"})

        except FileNotFoundError:
            return json.dumps({"error": "nvidia-smi 命令不存在,请确认已安装 NVIDIA 驱动"})
        except subprocess.TimeoutExpired:
            return json.dumps({"error": "获取 GPU 信息超时"})
        except Exception as e:
            return json.dumps({"error": f"获取 GPU 信息时发生错误:{str(e)}"})

    @staticmethod
    def fetch_webpage(url: str, max_length: int = 5000) -> str:
        """
        抓取网页内容

        Args:
            url: 要抓取的网页 URL
            max_length: 返回内容的最大字符数

        Returns:
            包含网页内容的 JSON 字符串
        """
        try:
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            }

            response = requests.get(url, headers=headers, timeout=15)
            response.encoding = response.apparent_encoding

            if response.status_code == 200:
                from bs4 import BeautifulSoup
                soup = BeautifulSoup(response.text, 'lxml')

                # 移除脚本和样式标签
                for tag in soup(['script', 'style', 'nav', 'footer', 'header']):
                    tag.decompose()

                # 获取页面标题
                title = soup.title.string if soup.title else "无标题"

                # 获取正文内容
                text = soup.get_text(separator='\n', strip=True)

                # 截断过长的内容
                if len(text) > max_length:
                    text = text[:max_length] + "...[内容已截断]"

                return json.dumps({
                    "success": True,
                    "url": url,
                    "title": title,
                    "content": text,
                    "content_length": len(text)
                }, ensure_ascii=False)
            else:
                return json.dumps({
                    "success": False,
                    "error": f"HTTP 状态码:{response.status_code}"
                })

        except requests.Timeout:
            return json.dumps({"success": False, "error": "请求超时"})
        except requests.RequestException as e:
            return json.dumps({"success": False, "error": f"请求失败:{str(e)}"})
        except Exception as e:
            return json.dumps({"success": False, "error": f"抓取网页时发生错误:{str(e)}"})

    @staticmethod
    def calculate(expression: str) -> str:
        """
        执行数学计算

        Args:
            expression: 数学表达式,如 "2 + 3 * 4"

        Returns:
            计算结果的 JSON 字符串
        """
        try:
            # 安全检查:只允许基本的数学运算
            allowed_chars = set('0123456789+-*/().% ')
            if not all(c in allowed_chars for c in expression):
                return json.dumps({"error": "表达式包含非法字符"})

            # 计算结果
            result = eval(expression)
            return json.dumps({
                "expression": expression,
                "result": result
            })
        except ZeroDivisionError:
            return json.dumps({"error": "除数不能为零"})
        except Exception as e:
            return json.dumps({"error": f"计算错误:{str(e)}"})

# 工具定义(用于 Function Gemma)
TOOL_DEFINITIONS = [
    {
        "type": "function",
        "function": {
            "name": "get_current_date",
            "description": "获取当前的日期、时间和星期信息",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_gpu_info",
            "description": "获取电脑的 GPU 显卡配置信息,包括显卡型号、显存大小、使用率和温度等",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "fetch_webpage",
            "description": "抓取指定网页的文本内容,用于获取网页信息或进行内容总结",
            "parameters": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "description": "要抓取的网页 URL 地址"
                    }
                },
                "required": ["url"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "执行数学计算,支持加减乘除和括号",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,如:2 + 3 * 4"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

# 工具名称到函数的映射
TOOL_FUNCTIONS = {
    "get_current_date": ToolBox.get_current_date,
    "get_gpu_info": ToolBox.get_gpu_info,
    "fetch_webpage": ToolBox.fetch_webpage,
    "calculate": ToolBox.calculate
}

5.3 构建函数调用解析器

Function Gemma 的输出需要被解析和执行。创建 tools/parser.py 文件:

"""
无忆研习社 - Function Gemma 输出解析器
作者:莫潇羽
"""

import re
import json
from typing import Optional, Dict, Any, List, Tuple

class FunctionCallParser:
    """解析 Function Gemma 的函数调用输出"""

    # 匹配函数调用的正则表达式
    CALL_PATTERN = re.compile(
        r'<start_function_call>call:(\w+)\{(.*?)\}<end_function_call>',
        re.DOTALL
    )

    # 匹配参数的正则表达式
    PARAM_PATTERN = re.compile(
        r'(\w+):<escape>(.*?)<escape>',
        re.DOTALL
    )

    @classmethod
    def parse(cls, output: str) -> List[Dict[str, Any]]:
        """
        解析模型输出,提取所有函数调用

        Args:
            output: Function Gemma 的原始输出文本

        Returns:
            函数调用列表,每个元素包含 name 和 parameters
        """
        calls = []

        # 查找所有函数调用
        for match in cls.CALL_PATTERN.finditer(output):
            function_name = match.group(1)
            params_str = match.group(2)

            # 解析参数
            parameters = {}
            for param_match in cls.PARAM_PATTERN.finditer(params_str):
                param_name = param_match.group(1)
                param_value = param_match.group(2)
                parameters[param_name] = param_value

            calls.append({
                "name": function_name,
                "parameters": parameters
            })

        return calls

    @classmethod
    def has_function_call(cls, output: str) -> bool:
        """检查输出中是否包含函数调用"""
        return bool(cls.CALL_PATTERN.search(output))

    @classmethod
    def extract_text_response(cls, output: str) -> str:
        """提取非函数调用的文本部分"""
        # 移除所有函数调用
        text = cls.CALL_PATTERN.sub('', output)
        return text.strip()

def execute_function_calls(
    calls: List[Dict[str, Any]], 
    tool_functions: Dict[str, callable]
) -> List[Dict[str, Any]]:
    """
    执行解析出的函数调用

    Args:
        calls: 解析出的函数调用列表
        tool_functions: 工具名称到函数的映射

    Returns:
        执行结果列表
    """
    results = []

    for call in calls:
        function_name = call["name"]
        parameters = call["parameters"]

        if function_name in tool_functions:
            try:
                # 调用对应的工具函数
                func = tool_functions[function_name]
                result = func(parameters)
                results.append({
                    "function": function_name,
                    "parameters": parameters,
                    "success": True,
                    "result": result
                })
            except Exception as e:
                results.append({
                    "function": function_name,
                    "parameters": parameters,
                    "success": False,
                    "error": str(e)
                })
        else:
            results.append({
                "function": function_name,
                "parameters": parameters,
                "success": False,
                "error": f"未知的工具函数:{function_name}"
            })

    return results

5.4 创建 Web 演示界面

最后,我们使用 Gradio 创建一个直观的 Web 界面。创建 app.py 文件:

"""
无忆研习社 - Function Gemma AI Agent 演示系统
作者:莫潇羽

启动方式:python app.py
"""

import gradio as gr
import torch
from transformers import AutoProcessor, AutoModelForCausalLM
import json

# 导入自定义模块
from tools.my_tools import TOOL_DEFINITIONS, TOOL_FUNCTIONS, ToolBox
from tools.parser import FunctionCallParser, execute_function_calls

# ==================== 全局配置 ====================
MODEL_PATH = "./checkpoints/functiongemma-270m-it"
🔒
该内容仅对更高等级社区用户开放
请谨慎解锁时效性强且发布日期较早的文章
单篇解锁后若未显示全文请刷新页面
您当前:游客 · 可见 60% 内容 · 升级至 注册用户 可见 70%
👀
游客
可见 60%
✓ 当前
注册用户
注册用户
可见 70%
社区精英
社区精英
可见 100%
社区守护
社区守护
可见 100%
仅解锁本文,永久有效。如需PDF珍藏版,请联系站长获取。 当前单篇价格 ¥9.9
✏️ 发表评论

请先登录后发表评论

前往登录
📊 站点统计
今日发布0 篇
文章总数1107 篇
昨日发布1 篇
本月发布31 篇
建站时间456 天
🔍 搜索
站长微语

联系站长

QQ:2805463528
AIGC 技术社区
致力于解码 AI前沿技术 与经验分享
纯粹的技术应用社区

💡 欢迎您的建议与反馈,让社区变得更好

快速通道
联系站长
站长QQ二维码
AI交流群
AI交流群
仍在路上

那些寒夜里追赶过的方向

那些冷眼下没放弃的理想

一篇一篇写到现在

仍在路上

"不羁放纵爱自由"

—— 致敬 Beyond
持续创作中 莫潇羽 · 无忆研习社
▲