教程:使用 Gemini API 进行函数调用


借助函数调用,您可以更轻松地从生成模型中获取结构化数据输出。然后,您可以使用这些输出调用其他 API,并将相关响应数据返回给模型。换言之,函数调用可帮助您将生成模型连接到外部系统,以使生成的内容包含最新且准确的信息。

您可以为 Gemini 模型提供函数说明。这些函数是使用应用的语言编写的(即,它们不是 Google Cloud Functions)。模型可能会要求您调用一个函数并发回结果,以帮助模型处理您的查询。

请参阅函数调用简介了解详情(如果您尚未这样做)。

设置项目

在调用 Gemini API 之前,您需要设置项目,包括设置 API 密钥、安装 SDK 软件包以及初始化模型。

设置函数调用

在本教程中,您将让模型与支持以下参数的假设货币交易所 API 进行交互:

参数 类型 必需 说明
currencyDate 字符串 获取
汇率的日期(必须始终采用 YYYY-MM-DD 格式,如果未指定时间段,则采用值 latest
currencyFrom string 要换算的币种
currencyTo string 要换算成的币种

API 请求示例

{
  "currencyDate": "2024-04-17",
  "currencyFrom": "USD",
  "currencyTo": "SEK"
}

API 响应示例

{
  "base": "USD",
  "date": "2024-04-17",
  "rates": {"SEK": 0.091}
}

第 1 步:创建用于发出 API 请求的函数

如果尚未创建用于发出 API 请求的函数,请先创建。

在本教程中出于演示目的,您不会发送实际 API 请求,而是以与实际 API 返回的格式相同的格式返回硬编码值。

func exchangeRate(currencyDate string,
    currencyFrom string, currencyTo string) map[string]any {
    // This hypothetical API returns a JSON such as:
    // {"base":"USD","date":"2024-04-17","rates":{"SEK": 0.091}}
    return map[string]any{
        "base":  currencyFrom,
        "date":  currencyDate,
        "rates": map[string]any{currencyTo: 0.091}}
}

第 2 步:创建函数声明

创建要传递给生成模型的函数声明(本教程的下一步)。

在函数和参数说明中添加尽可能多的详细信息。 生成模型使用这些信息来确定选择哪个函数,以及如何为函数调用中的形参提供值。

currencyExchangeTool := &genai.Tool{
    FunctionDeclarations: []*genai.FunctionDeclaration{{
        Name:        "exchangeRate",
        Description: "Lookup currency exchange rates by date",
        Parameters: &genai.Schema{
            Type: genai.TypeObject,
            Properties: map[string]*genai.Schema{
                "currencyDate": {
                    Type:        genai.TypeString,
                    Description: "A date that must always be in YYYY-MM-DD format" +
                        " or the value 'latest' if a time period is not specified",
                },
                "currencyFrom": {
                    Type:        genai.TypeString,
                    Description: "Currency to convert from",
                },
                "currencyTo": {
                    Type:        genai.TypeString,
                    Description: "Currency to convert to",
                },
            },
            Required: []string{"currencyDate", "currencyFrom"},
        },
    }},
}

第 3 步:在模型初始化期间指定函数声明

在初始化生成模型时,通过将函数声明传递到模型的 Tools 参数来指定函数声明:

// ...

currencyExchangeTool := &genai.Tool{
  // ...
}

// Use a model that supports function calling, like a Gemini 1.5 model
model := client.GenerativeModel("gemini-1.5-flash")

// Specify the function declaration.
model.Tools = []*genai.Tool{currencyExchangeTool}

第 4 步:生成函数调用

现在,您可以使用定义的函数向模型发出提示。

建议使用聊天界面使用函数调用,因为函数调用非常适合聊天的多轮结构。

// Start new chat session.
session := model.StartChat()

prompt := "How much is 50 US dollars worth in Swedish krona?"

// Send the message to the generative model.
resp, err := session.SendMessage(ctx, genai.Text(prompt))
if err != nil {
    log.Fatalf("Error sending message: %v\n", err)
}

// Check that you got the expected function call back.
part := resp.Candidates[0].Content.Parts[0]
funcall, ok := part.(genai.FunctionCall)
if !ok {
    log.Fatalf("Expected type FunctionCall, got %T", part)
}
if g, e := funcall.Name, currencyExchangeTool.FunctionDeclarations[0].Name; g != e {
    log.Fatalf("Expected FunctionCall.Name %q, got %q", e, g)
}
fmt.Printf("Received function call response:\n%q\n\n", part)

apiResult := map[string]any{
    "base":  "USD",
    "date":  "2024-04-17",
    "rates": map[string]any{"SEK": 0.091}}

// Send the hypothetical API result back to the generative model.
fmt.Printf("Sending API result:\n%q\n\n", apiResult)
resp, err = session.SendMessage(ctx, genai.FunctionResponse{
    Name:     currencyExchangeTool.FunctionDeclarations[0].Name,
    Response: apiResult,
})
if err != nil {
    log.Fatalf("Error sending message: %v\n", err)
}

// Show the model's response, which is expected to be text.
for _, part := range resp.Candidates[0].Content.Parts {
    fmt.Printf("%v\n", part)
}