1. Introduzione alla Chiamata di Funzione

Nel modello GPT, la Chiamata di Funzione si riferisce alla fornitura di funzioni descrittive al modello tramite un'API, consentendogli di selezionare e restituire in output un oggetto JSON contenente parametri per chiamare una o più funzioni in modo intelligente. È importante notare che l'API di Chat Completions non esegue direttamente le chiamate di funzione, ma genera piuttosto un JSON che può essere utilizzato per eseguire le funzioni nel codice.

In termini semplici, la funzionalità di Chiamata di Funzione coinvolge la fornitura di un insieme di definizioni di funzioni (inclusa la descrizione delle funzioni e dei parametri) al modello GPT. Il modello poi decide quale funzione chiamare in base alla richiesta dell'utente. Poiché il modello non può eseguire funzioni esterne, può solo rispondere con una richiesta di quale funzione chiamare (inclusi i parametri della chiamata della funzione). Dopo aver ricevuto il risultato della richiesta del modello, il nostro programma esegue la chiamata della funzione in locale. Il risultato della chiamata della funzione viene quindi concatenato con il prompt e inviato nuovamente al modello per ulteriore elaborazione prima di restituire il risultato finale all'utente.

2. Scenari di Applicazione della Chiamata di Funzione

Ecco alcuni esempi delle sue applicazioni pratiche:

  • Creazione di un'assistente per rispondere a domande chiamando API esterne, come ad esempio definire le funzioni come invia_email(destinatario: string, corpo: string) o ottieni_meteo_attuale(località: string, unità: 'celsius' | 'fahrenheit').
  • Convertire il linguaggio naturale in chiamate API, ad esempio tradurre "Chi sono i miei migliori clienti?" in ottieni_clienti(fatturato_min: int, creati_prima_di: string, limite: int) e quindi fare una chiamata API interna.
  • Estrarre dati strutturati dal testo, ad esempio definendo funzioni come estrai_dati(nome: string, compleanno: string) o query_sql(query: string).

Utilizzando la funzionalità di Chiamata di Funzione, possiamo implementare agenti AI che interagiscono con i nostri sistemi e database locali, ad esempio facendo sì che l'AI controlli le previsioni del tempo più recenti, verifichi i prezzi delle azioni, ordini da asporto o prenoti voli.

3. Modelli che Supportano la Chiamata di Funzione

Non tutte le versioni del modello sono state addestrate con dati di chiamata di funzione. Attualmente, i modelli che supportano la chiamata di funzione sono: gpt-4, gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview, gpt-4-0613, gpt-3.5-turbo, gpt-3.5-turbo-1106 e gpt-3.5-turbo-0613.

Inoltre, i modelli gpt-4-turbo-preview, gpt-4-0125-preview, gpt-4-1106-preview e gpt-3.5-turbo-1106 supportano la chiamata di funzioni parallele, consentendo loro di eseguire più chiamate di funzione contemporaneamente e gestire tali chiamate di funzione in modo da produrre risultati efficaci ed efficienti.

Nota: Il rischio potenziale associato alla funzionalità di Chiamata di Funzione è che potrebbe portare il modello a produrre parametri errati (ad esempio, parametri fantasma). Pertanto, prima di intraprendere azioni che influenzano il mondo reale (come inviare email, pubblicare online, effettuare acquisti, ecc.), è consigliabile incorporare un processo di conferma dell'utente a livello di prodotto, garantendo che le funzioni vengano eseguite solo dopo conferma dell'utente.

4. Esempi di Chiamata di Funzione

4.1 Esempio Python

Implementare la Chiamata di Funzione sulla piattaforma OpenAI di solito segue i passaggi di base descritti di seguito. Di seguito verrà illustrato l'intero processo utilizzando un esempio di codice Python, concentrandosi sulla query del meteo.

Passaggio 1: Preparare funzioni chiamabili e definizioni di funzioni per il modello

Prima di tutto, è necessario definire una funzione che può essere chiamata dal modello GPT. Ciò significa tipicamente preparare la nostra stessa funzione che può eseguire determinate operazioni in base ai parametri di input, come ad esempio comunicare con un'API di terze parti.

import json

def ottieni_meteo_attuale(località, unità="fahrenheit"):
    return json.dumps({
        "località": località, 
        "temperatura": "18", 
        "unità": unità
    })

Passo 2: Chiamata al modello in base alla query e al parametro degli strumenti

Successivamente, è necessario chiamare il modello GPT tramite l'API di completamento della chat e passare la query dell'utente (ad esempio "Qual è il meteo attuale") nonché il parametro tools, che include la descrizione della funzione get_current_weather che abbiamo appena definita.

from openai import OpenAI

client = OpenAI()

tools = [{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "Ottieni il meteo attuale per una determinata posizione",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "Nome della città, ad esempio: 'San Francisco, CA'"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"]
                }
            },
            "required": ["location"]
        }
    }
}]

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Qual è il meteo attuale a San Francisco?"}],
    tools=tools
)

Passo 3: Esegui la funzione in locale

Il risultato restituito dal modello includerà informazioni sulla funzione che il modello desidera chiamare, tipicamente contenute nel parametro di risposta tool_calls. Possiamo quindi eseguire localmente la chiamata di funzione corrispondente basata sulle informazioni di chiamata di funzione descritte nel parametro tool_calls.

tool_calls = response.choices[0].message.tool_calls

if tool_calls:
    arguments = json.loads(tool_calls[0].function.arguments)
    weather_info = get_current_weather(**arguments)
    print(weather_info) # Qui possiamo vedere le informazioni meteo interrogate dalla chiamata di funzione

Passo 4: Chiamata al modello nuovamente con il risultato di ritorno della funzione

Ora possiamo inviare il risultato di ritorno della funzione come nuovo messaggio al modello, in modo che il modello possa elaborare questi risultati e generare una risposta su misura per l'utente.

follow_up_response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": "Qual è il meteo attuale a San Francisco?"},
        {"role": "function", "name": "get_current_weather", "content": weather_info}
    ],
    tools=tools
)

Spiegazione: Nell'esempio sopra, il contenuto di ritorno della funzione viene inviato al modello GPT tramite il messaggio di funzione come segue:

{"role": "function", "name": "get_current_weather", "content": weather_info}

In pratica, è anche possibile semplicemente inserire il contenuto di ritorno della funzione come riferimento nel prompt del messaggio di sistema affinché l'IA possa farvi riferimento quando risponde alle domande.

Passo 5: Ottenere la risposta finale dal modello

Infine, possiamo ottenere la risposta finale del modello e fornirla all'utente. In questo passaggio, il modello genererà una risposta amichevole basata sulle informazioni meteo che abbiamo fornito.

final_output = follow_up_response.choices[0].message.content
print(final_output) # Questo output è l'informazione meteo che desideriamo mostrare all'utente

Seguendo i passaggi sopra, abbiamo completato un esempio completo di interrogazione del meteo utilizzando il modello GPT e le chiamate di funzione.

4.2. Spiegazione della definizione della funzione di chiamata della funzione

4.2.1 Significato dei Campi del Parametro 'Strumenti'

Quando si effettua una chiamata di funzione, è necessario definire le informazioni rilevanti della funzione nel parametro tools. Il parametro tools è un array che contiene diverse definizioni di funzioni, e ogni definizione di funzione include i seguenti campi:

  1. type: Questo campo rappresenta il tipo dello strumento. In una chiamata di funzione, questo campo dovrebbe essere impostato su "function".
  2. function: Questo campo contiene informazioni dettagliate sulla funzione ed è un oggetto con i seguenti campi specifici:
    • name: Il nome della funzione, che è una stringa.
    • description: Una descrizione dello scopo della funzione, che può aiutare il modello a generare parametri che soddisfano le aspettative dell'utente.
    • parameters: Descrive le definizioni dei parametri della funzione ed è un oggetto che contiene i seguenti sotto-campi:
      • type: Definisce il tipo del parametro, che dovrebbe essere principalmente impostato su "object".
      • properties: Le definizioni specifiche di ciascun parametro della funzione, dove ciascuna definizione del parametro è generalmente un oggetto che contiene i seguenti sotto-campi:
        • type: Il tipo di dati del parametro (come "string", "integer", "boolean", ecc.).
        • description: La descrizione del parametro per aiutare il modello a comprendere il suo scopo.
        • enum (opzionale): Quando type è "string", il campo enum può specificare un array di stringhe che rappresentano l'insieme di valori validi.
      • required: Un array di stringhe che contiene i nomi dei parametri richiesti.

4.2.2 Esempi di Definizione degli Strumenti

Ora forniamo alcuni esempi di definizioni di tools per aiutare a capire come viene utilizzato ciascun campo.

Esempio 1: Ottenere Informazioni Meteo Attuali

{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "Ottieni informazioni meteo attuali per la località specificata",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "La città per la quale è necessario interrogare il meteo, ad esempio 'San Francisco, CA'"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Unità di temperatura, 'celsius' per Celsius, 'fahrenheit' per Fahrenheit"
                }
            },
            "required": ["location", "unit"]
        }
    }
}

Nell'esempio sopra, abbiamo definito una funzione chiamata get_current_weather per ottenere il meteo attuale di una località specificata. I parametri includono location e unit, dove unit ha due valori validi: "celsius" (Celsius) e "fahrenheit" (Fahrenheit).

Esempio 2: Trovare Album di un Artista Specifico

{
    "type": "function",
    "function": {
        "name": "find_artist_albums",
        "description": "Trova tutti gli album di un artista specifico",
        "parameters": {
            "type": "object",
            "properties": {
                "artist_name": {
                    "type": "string",
                    "description": "Il nome dell'artista"
                }
            },
            "required": ["artist_name"]
        }
    }
}

In questo esempio, abbiamo creato una funzione chiamata find_artist_albums per trovare tutti gli album di un artista specifico. Questa funzione richiede solo un parametro: artist_name (il nome dell'artista).

4.3. Esempio di una Chiamata di Funzione di Richiesta HTTP

OpenAI fornisce un'API accessibile attraverso il protocollo HTTP. Di seguito, spiegheremo come utilizzare la funzionalità di chiamata di funzione tramite l'API HTTP. Gli sviluppatori di altri linguaggi di programmazione possono fare riferimento a questo esempio.

4.3.1. Passaggio 1: Chiamata al Modello con Query dell'Utente e Dichiarazione della Funzione

Per prima cosa, è necessario inviare la query dell'utente e l'elenco delle funzioni supportate al modello GPT, in modo che il modello possa analizzare automaticamente quale funzione chiamare per rispondere alla query dell'utente in base alla domanda dell'utente.

Nell'esempio seguente, informiamo GPT che abbiamo una funzione get_current_weather che può essere utilizzata per interrogare le informazioni meteorologiche per una città specificata.

curl --location 'https://api.aiproxy.io/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {OPENAI_KEY}' \
--data '{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "user",
            "content": "Com'è il tempo a Shanghai oggi?"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "Ottieni le informazioni meteo attuali per la posizione specificata",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "La città per la quale si desidera conoscere il meteo, ad es. 'San Francisco, CA'"
                        },
                        "unit": {
                            "type": "string",
                            "enum": [
                                "celsius",
                                "fahrenheit"
                            ],
                            "description": "Unità di temperatura, 'celsius' per Celsius, 'fahrenheit' per Fahrenheit"
                        }
                    },
                    "required": [
                        "location",
                        "unit"
                    ]
                }
            }
        }
    ]
}'

Spiegazione dei parametri della richiesta:

{
    "model": "gpt-3.5-turbo", // Il modello GPT da chiamare
    "messages": [ // Questo è l'elenco di messaggi per GPT, inclusa la query dell'utente
        {
            "role": "user",
            "content": "Com'è il tempo a Shanghai oggi?"
        }
    ],
    "tools": [
	  // Questa è la definizione delle tue funzioni, informando GPT delle funzioni disponibili
    ]
}

Fa riferimento alla sezione 4.2.2 per la definizione del parametro tools.

Nel normale processo del modello GPT, riceverai una risposta API simile a quanto segue:

{
    "model": "gpt-3.5-turbo-0613",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 122,
        "completion_tokens": 27,
        "total_tokens": 149
    },
    "id": "chatcmpl-8mL4hS4zNMocyR2ajKyAvSTcbNaao",
    "created": 1706531447,
    "choices": [
        {
            "index": 0,
            "delta": null,
            "message": {
                "role": "assistant",
                "tool_calls": [ // Il parametro tool_calls rappresenta l'elenco delle funzioni che GPT desidera chiamare
                    {
                        "id": "call_1iF09ttX1R9ESR18Ul2nLe1R",
                        "type": "function",
                        "function": {
                            "name": "get_current_weather",  // Indica che GPT desidera rispondere alla query dell'utente chiamando la funzione get_current_weather
                            "arguments": "{\n  \"location\": \"Shanghai, China\",\n  \"unit\": \"celsius\"\n}" // Questo è il parametro di input per chiamare la funzione get_current_weather
                        }
                    }
                ]
            },
            "finish_reason": "tool_calls"
        }
    ]
}

4.3.2. Passaggio 2: Esecuzione della Chiamata Locale alla Funzione

Poiché il modello GPT stesso non può eseguire chiamate specifiche alla funzione e ci informa solo quale funzione desidera chiamare, il nostro programma locale deve eseguire la chiamata alla funzione specifica in base al parametro tool_calls restituito dal modello. Il modo di eseguire le funzioni locali varia a seconda dei linguaggi di programmazione. Ad esempio, in Python, puoi fare riferimento alla sezione precedente.

4.3.3. Passaggio 3: Richiamare Ancora il Modello con il Risultato della Funzione

Poiché la chiamata della funzione viene eseguita in locale, è necessario passare il risultato dell'esecuzione della funzione e la domanda dell'utente di nuovo al modello GPT per ottenere la risposta finale.

curl --location 'https://api.aiproxy.io/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk-Roc5MX1zEuVxiuaMaETV6wZ2jXcCehjUCzwP9AcNErUiwppQ' \
--data '{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "user",
            "content": "Com'è il tempo a Shanghai oggi?"
        },
        {
            "role": "function",
            "name": "get_current_weather",
            "content": "{\"city\":\"Shanghai\", \"temperature\":\"25 gradi Celsius\"}"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "Ottieni le informazioni meteorologiche attuali per la località specificata",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "La città per cui effettuare la query del meteo, ad esempio 'San Francisco, CA'"
                        },
                        "unit": {
                            "type": "string",
                            "enum": [
                                "celsius",
                                "fahrenheit"
                            ],
                            "description": "L'unità di misura della temperatura, 'celsius' per Celsius, 'fahrenheit' per Fahrenheit"
                        }
                    },
                    "required": [
                        "location",
                        "unit"
                    ]
                }
            }
        }
    ]
}'

Nota: La richiesta sopra include un messaggio di funzione aggiuntivo per informare il modello GPT del valore restituito dalla funzione. GPT risponderà direttamente alla domanda dell'utente in base alle informazioni restituite dalla funzione e non richiamerà nuovamente la funzione.

Il messaggio di funzione rappresenta il valore restituito dalla funzione e segue il formato seguente:

{
    "role": "function", // Il tipo di messaggio è function, indicando il valore restituito dalla funzione
    "name": "get_current_weather", // Informa GPT che il messaggio corrente è il valore restituito dalla funzione get_current_weather
    "content": "{\"city\":\"Shanghai\", \"temperature\":\"25 gradi Celsius\"}" // Contenuto restituito dalla funzione, può essere in formato JSON o altro contenuto testuale.
}

Di seguito è riportata la risposta finale generata da GPT:

{
    "model": "gpt-3.5-turbo-0613",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 144,
        "completion_tokens": 17,
        "total_tokens": 161
    },
    "id": "chatcmpl-8mLmvvKAjSql7rGF8fvQeddKhWYvr",
    "created": 1706534189,
    "choices": [
        {
            "index": 0,
            "delta": null,
            "message": {
                "role": "assistant",
                "content": "Il tempo a Shanghai oggi è di 25 gradi Celsius."
            },
            "finish_reason": "stop"
        }
    ]
}