Come interagire con le API utilizzando la chiamata di funzione in Gemini

1. Panoramica

Cosa sono le chiamate di funzione in Gemini?

L'API Vertex AI Gemini è una famiglia di modelli di IA generativa sviluppati da Google DeepMind progettati per casi d'uso multimodali. La chiamata di funzione è una funzionalità dei modelli Gemini che semplifica per gli sviluppatori ottenere output di dati strutturati dai modelli generativi.

Gli sviluppatori possono quindi utilizzare questi output per chiamare altre API e restituire i dati di risposta pertinenti al modello. In altre parole, le chiamate di funzione ti aiutano a collegare i tuoi modelli generativi a sistemi esterni in modo che i contenuti generati includano le informazioni più aggiornate e accurate.

Come funzionano le chiamate di funzione

Le funzioni vengono descritte utilizzando le dichiarazioni di funzione, che aiutano il modello generativo a comprendere lo scopo e i parametri all'interno di una funzione. Dopo aver passato le dichiarazioni di funzione in una query a un modello generativo, il modello restituisce un oggetto strutturato che include i nomi delle funzioni pertinenti e i relativi argomenti in base alla query dell'utente. Tieni presente che con la chiamata di funzione, il modello non chiama effettivamente la funzione. Puoi invece utilizzare la funzione e i parametri restituiti per richiamare la funzione in qualsiasi linguaggio, libreria o framework desideri.

Interfaccia API

Cosa creerai

In questo codelab, creerai una pipeline di AI generativa con l'API Gemini di Vertex AI e Python. Utilizzando la tua app, gli utenti possono chiedere informazioni sui tassi di cambio e il sistema recupererà i dati più recenti da un'API esterna e risponderà all'utente fornendo la risposta.

Obiettivi didattici

  • Interagire con il modello Gemini utilizzando la libreria client Python
  • Come definire una dichiarazione di funzione e registrarla come strumento
  • Come chiamare Gemini e ottenere una risposta a una chiamata di funzione
  • Come restituire la risposta di funzione a Gemini e rispondere all'utente

Che cosa ti serve

2. Configurazione e requisiti

Prima di poter iniziare a utilizzare le chiamate di funzione in Gemini, devi abilitare l'API Vertex AI e installare l'ultima versione della libreria client Python di Vertex AI.

Abilita API Vertex AI

Per abilitare l'API Vertex AI, segui questi passaggi:

  1. Nel browser, vai alla pagina dei dettagli del servizio API Vertex AI.
  2. Fai clic sul pulsante Abilita per abilitare l'API Vertex AI nel tuo progetto Google Cloud.

Installa la libreria client Python per Vertex AI

Per installare le librerie client Python per Vertex AI, segui questi passaggi:

  1. Apri un terminale nel tuo ambiente di sviluppo.
  2. Verifica di disporre di un ambiente di sviluppo Python valido e fai riferimento a queste linee guida, se necessario.
  3. Esegui questo comando per installare la libreria client Python per Vertex AI:
    pip install --upgrade google-cloud-aiplatform
    
  4. Se è in esecuzione in un ambiente blocco note, potrebbe essere necessario riavviare il runtime o il kernel per utilizzare i pacchetti appena installati.

Ora è tutto pronto per utilizzare l'API Vertex AI.

3. Comprendi il problema

Hai mai interagito con un modello linguistico di grandi dimensioni (LLM) o con un modello di IA generativa, chiedendo informazioni in tempo reale o attuali, per poi ricevere una risposta con informazioni obsolete o imprecise?

Proviamo ora! Per prima cosa, importeremo i pacchetti Python pertinenti e inizializzare il modello Gemini. Puoi eseguire il codice seguente in un ambiente di sviluppo Python come Colab o Colab Enterprise e installando la versione più recente dell'SDK Vertex AI per Python:

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

Ora facciamo una domanda sul tasso di cambio per le diverse valute:

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

Il modello dovrebbe generare una risposta limitata o obsoleta simile a:

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.

[...]

Se un utente finale riceve questo tipo di risposta, deve cambiare contesto per cercare le valute di suo interesse, recuperare il tasso di cambio più recente ed eseguire le conversioni autonomamente.

Idealmente, una pipeline di modelli generativi potrebbe gestire alcune o tutte di queste attività per l'utente. Nella sezione successiva, proveremo alcune soluzioni alternative comuni per ottenere risposte strutturate da modelli generativi in modo da poter chiamare sistemi esterni.

4. Prova le soluzioni alternative più comuni

Quando lavori con modelli generativi in scenari in cui hai bisogno di informazioni o dati aggiornati da fonti esterne, puoi chiamare un'API esterna e poi fornire i risultati al modello generativo affinché possa utilizzarlo nella sua risposta.

Prima di chiamare un sistema esterno, devi determinare la funzione corretta da utilizzare, estrarre i parametri pertinenti dall'utente e inserirli in un oggetto di dati strutturati. Ciò di solito comporta un prompt engineering esaustivo per costringere il modello generativo a produrre dati strutturati validi.

Rivediamo la domanda che abbiamo posto nella sezione precedente e aggiungiamo alcune istruzioni aggiuntive per il modello. Prova a inviare la seguente richiesta al modello 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)

Il risultato è la seguente risposta testuale, che non è in formato JSON valido e con cui sarà difficile lavorare:

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

In particolare, la prima e l'ultima riga della risposta di testo includono apici inversi per delimitare il blocco di codice, la prima riga include un indicatore di lingua e i valori nell'oggetto JSON non sono le abbreviazioni standard di tre lettere della valuta che un'API di cambio di valuta si aspetta come parametri di input.

Potremmo provare a utilizzare Python per post-elaborare questo testo in un file JSON valido e in un dizionario, aggiungere altre istruzioni al prompt, fornire uno o più esempi dell'output desiderato, ottimizzare il modello o effettuare un'altra chiamata al modello generativo chiedendogli di pulire il codice JSON.

Ma c'è un modo più deterministico! Impareremo come utilizzare le chiamate di funzione in Gemini per eseguire query su servizi esterni e restituire risposte pertinenti agli utenti finali.

5. Come funzionano le chiamate di funzione

Prima di iniziare a utilizzare l'estrazione di parametri e la chiamata di funzione, esaminiamo i passaggi della chiamata di funzione e i componenti utilizzati durante il runtime.

Panoramica delle chiamate di funzione in Gemini

Input utente all'API Gemini

Il prompt dell'utente viene inviato all'API Gemini e, nella chiamata API al modello Gemini, lo sviluppatore ha definito una o più dichiarazioni di funzione all'interno di uno strumento, in modo che il modello Gemini sappia quali funzioni può chiamare e come chiamarle.

L'API Gemini restituisce una chiamata di funzione

In base ai contenuti dell'input e del prompt dell'utente, Gemini restituirà una risposta di chiamata di funzione con dati strutturati che includono il nome della funzione da chiamare e i parametri corrispondenti da utilizzare.

Effettua una richiesta API

Successivamente, utilizzerai il nome della funzione e i parametri per effettuare una richiesta API e recuperare informazioni da un sistema esterno o da un'API. Questa richiesta e risposta API sono implementate dallo sviluppatore nel codice dell'applicazione e avvengono al di fuori dell'ambito dell'API e dell'SDK Gemini. Ad esempio, potresti utilizzare la libreria requests in Python per chiamare un'API REST e ricevere una risposta in formato JSON. In alternativa, puoi chiamare la funzione utilizzando l'approccio che preferisci e la libreria client.

Restituire la risposta dell'API a Gemini

Infine, passerai la risposta dell'API al modello Gemini in modo che possa generare una risposta al prompt iniziale dell'utente finale o richiamare un'altra risposta di chiamata di funzione se il modello Gemini stabilisce che ha bisogno di informazioni aggiuntive.

6. Scegli l'API

Ora che hai compreso il flusso complessivo e i passaggi specifici nelle chiamate di funzione, creerai una pipeline di IA generativa per recuperare i tassi di cambio delle valute più recenti. Per prima cosa, dobbiamo selezionare l'API da utilizzare come fonte di informazioni.

Per la nostra app di cambio di valute, utilizzeremo l'API REST all'indirizzo https://www.frankfurter.app/ per recuperare le informazioni più recenti sui tassi di cambio globali.

Per interagire con questa API REST, potremmo effettuare una chiamata API REST con requests in Python come:

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

o una richiesta cURL come:

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

che restituisce una risposta simile a:

{
  "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
  }
}

Poiché le chiamate di funzione in Gemini non effettuano effettivamente la chiamata API esterna per conto tuo, non ci sono queste restrizioni sul tipo di API che utilizzi. Puoi utilizzare un servizio Cloud Run, una funzione Cloud Functions, una richiesta API a un servizio Google Cloud o qualsiasi API REST esterna.

7. Definisci una funzione e uno strumento

Ora che hai selezionato un'API REST da utilizzare, possiamo definire una specifica dell'API e registrare la funzione in uno strumento.

Assicurati di aver installato la versione più recente dell'SDK Vertex AI per Python.

Quindi, importa i moduli necessari dall'SDK Python e inizializza il modello Gemini:

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

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

Facendo riferimento all'API REST all'indirizzo https://api.frankfurter.app/, possiamo notare che accetta i seguenti parametri di input:

Parametro

Tipo

Descrizione

from

Stringa

Valuta da cui eseguire la conversione

to

Stringa

Valuta in cui convertire

date

Stringa

Data per il recupero del tasso di cambio

Con questi parametri, una specifica OpenAPI parziale per questa API REST in formato YAML ha il seguente aspetto:

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

Ora registriamolo come FunctionDeclaration utilizzando l'SDK Python per Gemini:

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",
      ]
  },
)

Assicurati di utilizzare il maggior numero possibile di dettagli nelle descrizioni delle funzioni e dei parametri, poiché il modello generativo utilizzerà queste informazioni per determinare quale funzione selezionare e come riempire i parametri nella chiamata di funzione.

Infine, definirai un valore Tool che includa la dichiarazione di funzione:

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

In questo caso utilizzi una dichiarazione di funzione all'interno di uno strumento, ma tieni presente che puoi registrare una o più dichiarazioni di funzione in uno strumento e il modello selezionerà la funzione appropriata da utilizzare in fase di runtime. Per maggiori dettagli su FunctionDeclaration, Tool e sulle classi correlate nell'SDK Gemini per Python, consulta la documentazione relativa alle chiamate di funzione nell'API Gemini.

Hai completato la configurazione delle definizioni delle funzioni e degli strumenti. Nella sezione successiva, chiameremo il modello generativo con questo strumento e riceveremo una chiamata di funzione da utilizzare per chiamare l'API REST.

8. Genera una chiamata di funzione

Ora puoi inviare un prompt al modello generativo e includere il valore tool che hai definito:

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],
)

Vediamo l'oggetto della risposta:

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"
        }
      }
    }
  }
}

Sembra che il modello abbia selezionato l'unica funzione disponibile e abbia restituito una chiamata di funzione per la funzione get_exchange_rate insieme ai parametri. e che i parametri siano nel formato corretto. Evviva, hai ottenuto risposte strutturate da modelli generativi!

Nella sezione successiva, utilizzerai le informazioni nella risposta per effettuare una richiesta API.

9. Effettua una richiesta API

Ricorda che la chiamata di funzione in Gemini in realtà non esegue la chiamata API esterna al posto tuo. Puoi invece usare qualsiasi linguaggio, libreria o framework desideri.

Qui utilizzerai la libreria requests in Python per chiamare l'API REST del tasso di cambio.

Esploriamo la risposta in un dizionario Python:

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

Ora possiamo chiamare requests o qualsiasi altro metodo:

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

Il che genera una risposta simile a:

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

Abbiamo anche ricevuto la risposta dall'API REST con le informazioni più recenti sui tassi di cambio di oggi. Nella sezione successiva, ritrasmetteremo queste informazioni al modello in modo che possa generare una risposta pertinente per l'utente.

10. Genera una risposta

Infine, generiamo una risposta per l'utente trasmettendo la risposta di funzione al modello nel prossimo turno di conversazione:

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

Una volta trasmessa la risposta di funzione al modello, questo risponderà al prompt dell'utente insieme alle informazioni pertinenti della risposta dell'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. Visualizza l'esempio di codice completo

A questo punto, puoi inserire il tuo codice Python in un'API di backend utilizzando un servizio Cloud Run, una funzione Cloud Functions o un altro servizio Cloud ed eseguire il deployment di un'app di frontend che utilizza questa API backend per eseguire query sul modello e chiamate API.

Ecco l'esempio di codice completo della nostra soluzione finale:

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

In questa implementazione, abbiamo utilizzato due richieste al modello generativo: una richiesta per generare una chiamata di funzione e un'altra richiesta per restituire la risposta di funzione. Tieni presente che questo è solo un metodo per gestire le chiamate di funzione e le risposte di funzione con Gemini. Puoi anche effettuare chiamate di funzione aggiuntive per ottenere ulteriori informazioni sulla query o utilizzare le chiamate di funzione con la chat e i metodi asincroni.

Per ulteriori esempi di codice, consulta il blocco note di esempio per le chiamate di funzione in Gemini.

12. Complimenti

Utilizzando le chiamate di funzione in Gemini, hai creato correttamente una pipeline di IA generativa che si avvale dell'API Gemini di Vertex AI e di Python. Gli utenti possono chiedere informazioni sui tassi di cambio e il sistema recupererà i dati più recenti da un'API esterna e risponderà con una risposta.

Data un prompt da un utente finale, le chiamate di funzione in Gemini si occupano di selezionare la funzione appropriata, estrarre i parametri dal prompt e restituire un oggetto di dati strutturati per consentirti di effettuare una chiamata API esterna.

La progettazione delle chiamate di funzione in Gemini ha lo scopo di offrirti il meglio di entrambi i mondi per l'estrazione deterministica dei parametri, lasciando il riassunto e la creazione di contenuti al modello generativo. Non esitare a provare altre API e altri prompt nella tua pipeline ed esplorare le altre funzionalità disponibili correlate all'API Vertex AI Gemini.

Interfaccia API

Esegui la pulizia

Puoi eseguire la pulizia seguente per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo codelab:

Scopri di più

Continua a imparare l'IA conversazionale e l'IA generativa con queste guide e risorse:

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.