如何在 Gemini 中使用函式呼叫與 API 互動

1. 總覽

Gemini 中的函式呼叫是什麼?

Vertex AI Gemini API 是由 Google DeepMind 開發的一系列生成式 AI 模型,專為多模態用途而設計。函式呼叫是 Gemini 模型的一項功能,可讓開發人員更輕鬆地從生成式模型取得結構化資料輸出內容。

開發人員可以使用這些輸出內容呼叫其他 API,並將相關的回應資料傳回至模型。換句話說,函式呼叫可協助您將生成式模型連結至外部系統,進而在產生內容中加入最新且準確的資訊。

函式呼叫的運作方式

函式是以函式宣告描述,可協助生成式模型瞭解函式中的用途和參數。您將查詢中的函式宣告傳遞至生成式模型後,模型會傳回結構化物件,其中包含根據使用者查詢內容的相關函式名稱及其引數。請注意,使用函式呼叫時,模型實際上不會呼叫函式,您可改用傳回的函式和參數,以您想要的任何語言、程式庫或架構呼叫函式!

API 介面

建構項目

在本程式碼研究室中,您將使用 Vertex AI Gemini API 和 Python 建構生成式 AI 管線。使用者可透過您的應用程式詢問匯率,系統就會從外部 API 擷取最新的資料,然後回覆使用者。

課程內容

  • 如何使用 Python 用戶端程式庫與 Gemini 模型互動
  • 如何定義函式宣告並註冊為工具
  • 如何呼叫 Gemini 並取得函式呼叫回覆
  • 如何將函式回覆傳回 Gemini 並回覆使用者

軟硬體需求

2. 設定和需求

您必須先啟用 Vertex AI API,並安裝最新版本的 Vertex AI Python 用戶端程式庫,才能開始在 Gemini 中使用函式呼叫。

啟用 Vertex AI API

如要啟用 Vertex AI API,請按照下列步驟操作:

  1. 在瀏覽器中前往 Vertex AI API 服務詳細資料頁面
  2. 按一下「啟用」按鈕,在 Google Cloud 專案中啟用 Vertex AI API。

安裝 Vertex AI 適用的 Python 用戶端程式庫

如要安裝 Vertex AI 適用的 Python 用戶端程式庫,請按照下列步驟操作:

  1. 在開發環境中開啟終端機。
  2. 確認您具備有效的 Python 開發環境,並視需要參閱這些指南
  3. 執行下列指令,安裝 Vertex AI 的 Python 用戶端程式庫:
    pip install --upgrade google-cloud-aiplatform
    
  4. 如果是在筆記本環境中執行,可能要重新啟動執行階段/核心,才能使用新安裝的套件。

您現在可以使用 Vertex AI API 了!

3. 瞭解問題

您是否曾與大型語言模型或生成式 AI 模型互動,並詢問即時或目前資訊,但卻只想收到包含過時資訊或錯誤資訊的回覆?

現在就來試試看吧!首先,我們會匯入相關的 Python 套件,並初始化 Gemini 模型。您可以在 ColabColab Enterprise 等 Python 開發環境中執行下列程式碼,方法是安裝最新版的 Python 適用的 Vertex AI SDK

import vertexai
from vertexai.generative_models import GenerativeModel
model = GenerativeModel("gemini-1.5-pro-001")

現在,讓我們詢問不同貨幣匯率的問題:

response = model.generate_content(
    "What's the exchange rate for euros to dollars today?"
)
print(response.text)

模型應該會產生限縮或過時的回應,如下所示:

As an AI language model, I don't have access to real-time currency exchange
rates. However, as of my last update in September 2021, the approximate exchange
rate between euros (EUR) and US dollars (USD) was:

1 EUR ≈ 1.18 USD

Please note that currency exchange rates constantly fluctuate and can vary
depending on various factors such as economic conditions, supply and demand,
political events, and more. To obtain the most up-to-date and accurate exchange
rate, I recommend using a reliable currency converter or financial website that
provides live rates.

[...]

如果使用者收到這類回應,就必須切換內容來查詢感興趣的貨幣、擷取最新的匯率,並自行執行任何轉換。

在理想情況下,生成式模型管道可以為使用者處理部分或所有工作。下一節將介紹一些常見解決方法,讓您從生成式模型取得結構化回應,進而呼叫外部系統。

4. 試試常見的解決方法

使用生成式模型時,如果您需要從外部來源取得最新資訊或資料,可以呼叫外部 API,再將結果傳回生成式模型,以便在回應中使用。

在呼叫外部系統前,您必須先決定要使用的正確函式、擷取使用者的相關參數,並將參數放入結構化資料物件。這通常涉及完整的提示工程,讓生成式模型強制輸出有效的結構化資料。

讓我們回顧上一節提出的問題,並為這個模型新增一些額外指示。請嘗試將下列要求傳送至 Gemini 模型:

user_prompt = "What's the exchange rate from euros to US dollars today?"

response = model.generate_content("""
Your task is to extract parameters from the user's input and return it as a
structured JSON payload. The user will ask about the exchange rate and which
currency they are converting from and converting to.

User input: {user_prompt}

Please extract the currencies as parameters and put them in a JSON object.
""".format(user_prompt=user_prompt))
print(response.text)

這個結果是下列文字回應,但 JSON 格式無效,我們無法處理:

```json
{
  "currency_from": "euros",
  "currency_to": "US dollars"
}
```

具體來說,文字回應的第一行和最後一行包含倒引號來分隔程式碼區塊,第一行包含語言指定碼,而 JSON 物件中的值不是貨幣交換 API 預期做為輸入參數的標準三字母貨幣縮寫。

我們可以嘗試使用 Python 將這段文字以下處理為有效的 JSON 和字典、在提示中加入更多指示、提供一或多個想要的輸出內容範例、微調模型,或再次呼叫生成式模型,要求清理 JSON。

但還有更確切的方法!我們會介紹如何運用 Gemini 函式呼叫查詢外部服務中的資訊,並向使用者傳回相關回覆。

5. 函式呼叫的運作方式

開始使用參數擷取和函式呼叫之前,讓我們先逐步介紹函式呼叫的步驟,以及執行階段使用的元件。

Gemini 函式呼叫總覽

使用者輸入到 Gemini API 的內容

使用者輸入的提示會傳送至 Gemini API,而在向 Gemini 模型發出 API 呼叫時,開發人員已在工具中定義一或多個函式宣告,讓 Gemini 模型知道可以呼叫哪些函式,以及如何呼叫函式。

Gemini API 會傳回函式呼叫

Gemini 會根據使用者輸入的內容和提示,傳回函式呼叫回應,其中包含結構化資料,包括要呼叫的函式名稱和要使用的對應參數。

提出 API 要求

接下來,您會使用函式名稱和參數提出 API 要求,從外部系統或 API 擷取資訊。這類 API 要求和回應是由開發人員在應用程式程式碼中導入,在 Gemini API 和 SDK 的範圍外。舉例來說,您可以使用 Python 中的 requests 程式庫呼叫 REST API 並接收 JSON 回應。或者,您也可以使用偏好的方法和用戶端程式庫來呼叫函式。

將 API 回覆傳回 Gemini

最後,將 API 回應傳回給 Gemini 模型,讓模型根據使用者的初始提示產生回覆,或是在 Gemini 模型判定需要額外資訊時,叫用其他函式呼叫回應。

6. 選擇 API

現在您已瞭解函式呼叫的整體流程和具體步驟,接下來您將建構生成式 AI 管道,用於擷取最新的貨幣匯率。首先,需要選取要做為資訊來源的 API。

針對貨幣兌換應用程式,我們會使用 REST API (網址:https://www.frankfurter.app/) 擷取全球匯率的最新資訊。

如要與這個 REST API 互動,我們可能會依照下列方式,使用 Python 中的 requests 發出 REST API 呼叫:

import requests
url = "https://api.frankfurter.app/latest"
response = requests.get(url)
response.text

cURL 要求,如:

curl https://api.frankfurter.app/latest

這樣會傳回類似以下的回應:

{
  "amount": 1,
  "base": "EUR",
  "date": "2023-12-20",
  "rates": {
    "AUD": 1.6186, "BGN": 1.9558, "BRL": 5.3287,
    "CAD": 1.4609, "CHF": 0.946, "CNY": 7.8121,
    "CZK": 24.538, "DKK": 7.4565, "GBP": 0.86555,
    "HKD": 8.5439, "HUF": 385.23, "IDR": 16994,
    "ILS": 3.9983, "INR": 91.06, "ISK": 150.3,
    "JPY": 157.12, "KRW": 1425.62, "MXN": 18.6867,
    "MYR": 5.0977, "NOK": 11.2895, "NZD": 1.7421,
    "PHP": 60.991, "PLN": 4.3413, "RON": 4.9699,
    "SEK": 11.129, "SGD": 1.4562, "THB": 38.252,
    "TRY": 31.883, "USD": 1.0944, "ZAR": 20.111
  }
}

Gemini 函式呼叫實際上不會為您發出外部 API 呼叫,因此您使用的 API 類型將不受此限制!您可以使用 Cloud Run 服務、Cloud 函式、傳送至 Google Cloud 服務的 API 要求,或任何外部 REST API。

7. 定義函式和工具

您已選取要使用的 REST API,現在我們可以定義 API 規格,並在工具中註冊該函式。

確認您已安裝最新版的 Python 適用的 Vertex AI SDK

接著,從 Python SDK 匯入必要的模組,並初始化 Gemini 模型:

from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerativeModel,
    Part,
    Tool,
)

model = GenerativeModel("gemini-1.5-pro-001")

回到 https://api.frankfurter.app/ 的 REST API,我們可以看到該 API 接受下列輸入參數:

參數

類型

說明

from

字串

要轉換的貨幣

to

字串

要轉換的幣別

date

字串

擷取匯率的日期

使用這些參數後,這個 REST API 的部分 OpenAPI 規格 (YAML 格式) 看起來會像這樣:

openapi: 3.0.0
info:
  title: Frankfurter Exchange Rate API
  description: This API provides current and historical exchange rates
  version: 1.0.0
servers:
  - url: https://api.frankfurter.app
paths:
  /{date}:
    get:
      summary: Get the latest currency exchange rates.
      parameters:
        - name: date
          in: path
          description: Get currency rates for a specific date or 'latest' if a date is not specified
          required: true
          schema:
            type: string
        - name: from
          in: query
          description: The currency to convert from.
          required: true
          schema:
            type: string
        - name: to
          in: query
          description: The currency to convert to.
          schema:
            type: string

現在,讓我們使用 Gemini 適用的 Python SDK,將此程式碼註冊為 FunctionDeclaration

get_exchange_rate_func = FunctionDeclaration(
    name="get_exchange_rate",
    description="Get the exchange rate for currencies between countries",
    parameters={
    "type": "object",
    "properties": {
        "currency_date": {
            "type": "string",
            "description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
        },
        "currency_from": {
            "type": "string",
            "description": "The currency to convert from in ISO 4217 format"
        },
        "currency_to": {
            "type": "string",
            "description": "The currency to convert to in ISO 4217 format"
        }
    },
         "required": [
            "currency_from",
            "currency_date",
      ]
  },
)

生成式模型會依據這項資訊,判斷要選取的函式,以及如何在函式呼叫中填入參數,因此在函式和參數說明中請盡可能提供詳細資訊。

最後,請定義包含函式宣告的 Tool

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

您在這裡使用工具中的一個函式宣告,但請注意,您可以在工具中註冊一或多個函式宣告,模型會在執行階段選取適當的函式。如要進一步瞭解 FunctionDeclarationTool 以及 Python 專用 Gemini SDK 中的相關類別,請參閱 Gemini API 中的函式呼叫說明文件。

您已完成函式和工具定義的設定。在下一節中,我們會使用這項工具呼叫生成式模型,並取回可用來呼叫 REST API 的函式呼叫。

8. 生成函式呼叫

現在,您可以提示生成式模型並加入您定義的 tool

prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""

response = model.generate_content(
    prompt,
    tools=[exchange_rate_tool],
)

讓我們看看回應物件:

print(response.candidates[0].content)

role: "model"
parts {
  function_call {
    name: "get_exchange_rate"
    args {
      fields {
        key: "currency_to"
        value {
          string_value: "SEK"
        }
      }
      fields {
        key: "currency_from"
        value {
          string_value: "AUD"
        }
      }
      fields {
        key: "currency_date"
        value {
          string_value: "latest"
        }
      }
    }
  }
}

看來模型選取了一個可用的函式,並傳回對 get_exchange_rate 函式及參數的函式呼叫。參數也使用我們想要的正確格式。很高興能夠從生成式模型取得結構化回應!

在下一節中,您將使用回應中的資訊提出 API 要求。

9. 提出 API 要求

還記得,Gemini 函式呼叫實際上不會為您發出外部 API 呼叫。而且您可以自由使用任何語言、程式庫或架構!

您將在此處使用 Python 中的 requests 程式庫,呼叫匯率 REST API。

讓我們將回應解壓縮為 Python 字典:

params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
    params[key[9:]] = value
params

現在,我們可以呼叫 requests 或任何其他方法:

import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text

會產生類似以下的回應:

'{"amount":1.0,"base":"AUD","date":"2024-01-16","rates":{"SEK":6.8682}}'

我們也收到 REST API 的回應,其中包含今天的最新匯率資訊。在下一節中,我們會將此資訊傳回模型,以便模型為使用者產生相關回應。

10. 生成回覆

最後,讓我們在下個對話回合中,回傳函式回應給模型,為使用者產生回應:

response = model.generate_content(
    [
    Content(role="user", parts=[
        Part.from_text(prompt + """Give your answer in steps with lots of detail
            and context, including the exchange rate and date."""),
    ]),
    Content(role="function", parts=[
        Part.from_dict({
            "function_call": {
                "name": "get_exchange_rate",
            }
        })
    ]),
    Content(role="function", parts=[
        Part.from_function_response(
            name="get_exchange_rate",
            response={
                "content": api_response.text,
            }
        )
    ]),
    ],
    tools=[exchange_rate_tool],
)


response.candidates[0].content.parts[0].text

我們將函式回應傳回模型後,它會回應使用者的提示,以及來自 API 回應的相關資訊。

The exchange rate from Australian dollars to Swedish krona on January 16, 2024,
is 1 Australian dollar is equal to 6.8663 Swedish krona.

So, 500 Australian dollars would be worth 500 * 6.8663 = 3,433.15 Swedish krona.

11. 查看完整程式碼範例

此時,您可以使用 Cloud Run 服務、Cloud 函式或其他 Cloud 服務,將 Python 程式碼放入後端 API,並部署使用這個後端 API 執行模型查詢和 API 呼叫的前端應用程式。

以下是最終解決方案的完整程式碼範例:

import requests
from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerativeModel,
    Part,
    Tool,
)

model = GenerativeModel("gemini-1.5-pro-001")

get_exchange_rate_func = FunctionDeclaration(
    name="get_exchange_rate",
    description="Get the exchange rate for currencies between countries",
    parameters={
    "type": "object",
    "properties": {
        "currency_date": {
            "type": "string",
            "description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
        },
        "currency_from": {
            "type": "string",
            "description": "The currency to convert from in ISO 4217 format"
        },
        "currency_to": {
            "type": "string",
            "description": "The currency to convert to in ISO 4217 format"
        }
    },
         "required": [
            "currency_from",
            "currency_date",
      ]
  },
)

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""

response = model.generate_content(
    prompt,
    tools=[exchange_rate_tool],
)

response.candidates[0].content

params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
    params[key[9:]] = value
params

import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text

response = model.generate_content(
    [
    Content(role="user", parts=[
        Part.from_text(prompt + """Give your answer in steps with lots of detail
            and context, including the exchange rate and date."""),
    ]),
    Content(role="function", parts=[
        Part.from_dict({
            "function_call": {
                "name": "get_exchange_rate",
            }
        })
    ]),
    Content(role="function", parts=[
        Part.from_function_response(
            name="get_exchange_rate",
            response={
                "content": api_response.text,
            }
        )
    ]),
    ],
    tools=[exchange_rate_tool],
)


response.candidates[0].content.parts[0].text

在這個實作項目中,我們向生成式模型使用了兩項要求,一項是產生函式呼叫,另一項要求則是傳回函式回應。請注意,這只是透過 Gemini 處理函式呼叫和函式回應的一種方法。您也可以發出額外的函式呼叫來取得查詢的詳細資訊,或搭配即時通訊和非同步方法使用函式呼叫。

如需其他程式碼範例,請參閱在 Gemini 中用於函式呼叫的筆記本範例

12. 恭喜

使用 Gemini 函式呼叫之後,您已成功透過 Vertex AI Gemini API 和 Python 建構生成式 AI 管線!使用者詢問匯率後,系統就會從外部 API 擷取最新資料,並傳回答案。

收到使用者的提示後,Gemini 中的函式呼叫會完成以下工作:選取適當函式、從提示中擷取參數,以及傳回結構化資料物件,以供您執行外部 API 呼叫。

Gemini 函式呼叫的設計旨在提供兩邊優勢,以便確定擷取參數,同時將摘要和內容創作交由生成式模型處理。您可以在管道中試用其他 API 和提示,並探索 Vertex AI Gemini API 的其他可用功能。

API 介面

清除

您可以執行以下清除作業,以免系統向您的 Google Cloud 帳戶收取這個程式碼研究室中所用資源的費用:

瞭解詳情

透過下列指南和資源,繼續瞭解對話式 AI 和生成式 AI:

授權

這項內容採用的是創用 CC 姓名標示 2.0 通用授權。