La novità del "function calling" di OpenAI per l'intelligenza artificiale

Posted by danieleperugini on Thursday, June 15, 2023

La novità del “function calling” di OpenAI per l’intelligenza artificiale

Negli ultimi tempi, OpenAI, l’azienda di ricerca sull’intelligenza artificiale (IA) e che tutti conosciamo per ChatGPT, ha annunciato un’innovativa funzionalità chiamata “function calling” all’interno della sua API. Questa nuova caratteristica consente ai modelli di IA di OpenAI, come GPT-4 e GPT-3.5-turbo, di chiamare funzioni esterne o API per completare compiti specifici e fornire risposte ancora più dettagliate e accurate. In questo articolo, esploreremo il concetto di “function calling”, i suoi vantaggi per gli sviluppatori e gli utenti, nonché un esempio pratico di utilizzo in Python.

Cos’è esattamente il “function calling”?

Il “function calling” è una capacità che consente ai modelli generativi di testo di OpenAI di identificare quando è necessario richiamare funzioni esterne o API per ottenere informazioni o eseguire operazioni specifiche. Ad esempio, se un utente pone una domanda come “Qual è il tempo a Roma oggi?”, il modello può chiamare una funzione (preventivamente notificata e descritta al modello), ad esempio “get_current_weather”, con gli argomenti necessari, come la posizione e l’unità di misura desiderate, per ottenere una risposta accurata. Questa funzionalità permette quindi al modello di combinare le sue abilità linguistiche con informazioni provenienti da fonti esterne, come database, servizi web o applicazioni.

Come utilizzare il “function calling” di OpenAI?

Per utilizzare il “function calling” di OpenAI, gli sviluppatori devono definire le funzioni che desiderano rendere disponibili al modello tramite uno schema JSON. Inoltre, possono specificare quale funzione richiamare al modello attraverso i nuovi parametri “functions” e “function_call” dell’endpoint “/v1/chat/completions” dell’API di OpenAI. Questo permette ai modelli di IA di OpenAI di accedere a funzionalità esterne e fornire dati strutturati anziché testo libero, migliorando l’affidabilità, la flessibilità e la personalizzazione delle risposte.

La cosa interessante è che in base alla descrizione che si farà della funzione e dei suoi parametri (questo è il nodo cruciale), il modello deciderà SE è il caso di invocare la funzione descritta (e con quali parametri) per dare risposta al prompt dell’utente.

Quindi la descrizione di una o più funzioni non è garanzia di utilizzo! Ma servirà al modello per capire quanto il risultato descritto della funzione si avvicina a quanto richiesto dall’utente (mi ricorda tanto gli embeddings e la similarità vettoriale…).

Le possibilità offerte da questa nuova funzionalità

L’introduzione del “function calling” apporta numerosi vantaggi sia per gli sviluppatori che per gli utenti che utilizzano le API di OpenAI. Ecco alcuni dei principali vantaggi:

  1. Maggiore affidabilità: Grazie al “function calling”, i modelli di IA possono restituire dati strutturati invece di testo libero. E questo è fondamentale! E’ questa la vera killer feature! Ciò semplifica l’integrazione con altri sistemi e riduce il rischio di errori o ambiguità nelle risposte fornite.

  2. Maggiore flessibilità: La capacità di richiamare funzioni esterne consente ai modelli di IA di OpenAI di accedere a una vasta gamma di fonti di informazione e funzionalità esterne. Questo amplia notevolmente il dominio di applicazione dei modelli e ne aumenta l’utilità in diversi contesti.

  3. Maggiore personalizzazione: Il “function calling” permette ai modelli di IA di adattarsi alle preferenze e alle esigenze degli utenti. Il modello può richiamare le funzioni più adeguate in base al contesto e agli input, fornendo risposte più pertinenti e personalizzate.

Esempio pratico di “function calling” in Python

Per comprendere meglio come funziona il “function calling”, consideriamo un esempio pratico di implementazione in Python. Supponiamo di voler creare un chatbot in grado di rispondere alle domande degli utenti sull’orario dei treni in Italia. Per realizzare ciò, possiamo utilizzare l’API di Trenitalia per ottenere le informazioni sui treni disponibili tra due stazioni specifiche. Definiamo quindi una funzione chiamata “get_train_schedule” che accetta come argomenti le due stazioni e restituisce un oggetto JSON contenente i dettagli dei treni trovati. In questo modo, il modello di IA può richiamare questa funzione per fornire risposte accurate sulle informazioni sui treni richieste dagli utenti.

ATTENZIONE! Il modo in cui si descrive la funzione è VITALE! Ho infatti provato ad usare un prompt leggermente diverso chiedendo i voli, e non i treni. E l’api ha comunque chiamato la funzione relativa ai treni. Quindi va calibrato davvero bene! In un altro tentativo, sempre passando la funzione per i treni, ho chiesto che tempo facesse oggi. E giustamente la risposta non ha minimamente preso in considerazione la funzione passata!

import openai
import requests
import datetime
openai.api_key = "<openai api key>"

# Funzione get_train_station_object e get_train_schedule per ottenere gli orari tra due stazioni
def get_train_station_object(station):
  url = f"https://www.lefrecce.it/Channels.Website.BFF.WEB/website/locations/search?name={station}&limit=10"
  try:
      response = requests.get(url)
      response.raise_for_status()
      data = response.json()
      return data
  except requests.exceptions.RequestException as e:
      print("Error retrieving train schedule:", e)
      return None

def get_train_schedule(from_station_desc, to_station_desc):
  from_station = get_train_station_object(from_station_desc)
  to_station = get_train_station_object(to_station_desc)
  departure_date_time = datetime.datetime.now().isoformat()
  print(departure_date_time)
  payload = {
      "departureLocationId": from_station[0]["id"],
      "arrivalLocationId": to_station[0]["id"],
      "departureTime": departure_date_time,
      "adults": 1,
      "children": 0
  }

  url = "https://www.lefrecce.it/Channels.Website.BFF.WEB/website/ticket/solutions"

  try:
      response = requests.post(url, json=payload)
      response.raise_for_status()
      data = response.json()
      return data
  except requests.exceptions.RequestException as e:
      print("Error retrieving train schedule:", e)
      return None
      
# descrizione della funzione "get_train_schedule" da passare ad openai: è solo un json per etichettare l'oggetto
function = {
  "name": "get_train_schedule",
  "description": "Ottieni gli orari dei treni tra due stazioni in Italia",
  "parameters": {
      "type": "object",
      "properties": {
        "from_station": {
          "type": "string",
          "description": "La stazione di partenza"
        },
        "to_station": {
          "type": "string",
          "description": "La stazione di arrivo"
        }
      },
      "required": ["from_station", "to_station"]
  }
}

# questo è il prompt che vogliamo passare all'api di openai
message = {
  "role": "assistant",
  "content": "Quali sono i treni da Milano a Roma oggi?"
}

# chiamata ad openai
response = openai.ChatCompletion.create(
  model="gpt-3.5-turbo-0613",
  functions=[function],
  messages=[message])
  
# esempio di risultato: utile per capire la potenza dei dati strutturati ritornati
# come si vede, open ai pensa di dover chiamare la funzione e ne struttura i parametri
"""
{
  "id": "chatcmpl-7RcWecYXY2hT5w7j3ULITEhZTSEdJ",
  "object": "chat.completion",
  "created": 1686817304,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "function_call": {
          "name": "get_train_schedule",
          "arguments": "{\n  \"from_station\": \"Milano\",\n  \"to_station\": \"Roma\"\n}"
        }
      },
      "finish_reason": "function_call"
    }
  ],
  "usage": {
    "prompt_tokens": 90,
    "completion_tokens": 27,
    "total_tokens": 117
  }
}
"""

# a questo punto si esegue il parsing e si invoca la funzione
import json

# accesso all'oggetto function_call (se openai ritiene di doverlo chiamare)
function_call = response["choices"][0]["message"]["function_call"]

# ottiene i parametri STRUTTURATI
f_name = function_call["name"]
f_args = json.loads(function_call["arguments"])
from_station = f_args["from_station"]
to_station = f_args["to_station"]

print(f_name, from_station, to_station)

# chiamata alla function
data = get_train_schedule(from_station, to_station)

# stampa risultati
solutions = data["solutions"]
i = 1
for s in solutions:
  origin = s["solution"]["origin"]
  destitination = s["solution"]["destination"]
  departure_time = s["solution"]["departureTime"]
  departure_time_obj = datetime.datetime.fromisoformat(departure_time)
  human_readable_departure_time = departure_time_obj.strftime("%Y-%m-%d %H:%M:%S")

  arrival_time = s["solution"]["arrivalTime"]
  arrival_time_obj = datetime.datetime.fromisoformat(arrival_time)
  human_readable_arrival_time = arrival_time_obj.strftime("%Y-%m-%d %H:%M:%S")

  duration = s["solution"]["duration"]
  msg = f"SOLUZIONE {i}: da {origin} a {destitination} alle ore {human_readable_departure_time}. Arrivo previsto alle {human_readable_arrival_time}."
  print(msg)
  i += 1

L’intelligenza artificiale è un valido aiuto, con alcuni “ma”…

Ho letto tantissime opinioni, ed al momento dire che l’intelligenza artificiale possa sostituire del tutto alcuni task è forse prematuro. Secondo me ovviamente.

Tuttavia questa nuova funzione è secondo me davvero interessante. Perché racchiude a mio parere la chiave di volta per l’interfaccia tra linguaggio umano ed i sistemi informatici.

Il bello di avere un sistema che traduce il linguaggio naturale in dati strutturati è qualcosa di davvero utile, che può fare la differenza nelle aziende che vogliono integrare l’ia nei propri processi.

Si pensi a poter rispondere a domande sull’analisi dei dati che invocano funzioni di sistemi proprietari.

Ed attenzione! Questo non significa esporre il proprio software ad OpenAI. Al modello viene solo notificate che si è in possesso di una funzione che fa alcune cose. E la risposta del modello, completamente disaccoppiata dai sistemi aziendali, suggerirà se invocare tale funzione o meno.

Geniale. Per me è geniale.

E questo va di pari passo con il cloud, fonte di dati di inestimabile valore.

Se vuoi valutare senza impegno le possibilità offerte da questa tecnologia, non esitare a contattarmi per una consulenza gratuita che servirà per darti idee e spunti su come cloud, dati ed intelligenza artificiale possono incrementare le prestazioni della tua azienda!

Alla prossima informazione!

PS: Se hai letto fino a qui, voglio proprio ringraziarti con un piccolo bonus: qui trovi un colab condiviso con il mio codice riportato nell’articolo!


IL MIO LIBRO: WHY YOUR DATA MATTER

Il libro dedicato ai manager e CIO che hanno a cuore i dati della propria azienda e vogliono avere sonni tranquilli (anticipando problematiche poco piacevoli legate al recupero, alla gestione o alla sicurezza dei dati)

Leggi il libro

REGISTRATI ALLA NEWSLETTER

Una piccola newsletter su data, azure e AI.

Dicono di me

Ricordo ancora bene cosa mi spinse a coinvolgerlo per la prima volta. Oltre che a trasmettermi competenza ed affidabilità, Daniele mi è sembrato fin da subito propenso a mettersi in gioco e a fare squadra con Fapim. Ho percepito in maniera marcata che questa persona avrebbe fatto suo il problema e avrebbe cercato di risolverlo concretamente.

(Leggi la testimonianza completa)

Fapim S.p.a.Ombretta Pacini, responsabile comunicazione e immagine aziendale
È orbitando nell’area Microsoft che abbiamo conosciuto Daniele. Abbiamo iniziato a collaborarci nel 2016 in un momento nel quale, dopo aver introdotto in azienda la metodologia di Agile grazie ad un lungo periodo di formazione interna su questo argomento, iniziavamo a metterla in pratica su nuovi progetti e necessitavamo di Project Manager e Team Leader con esperienza.

(Leggi la testimonianza completa)

Vivido S.r.l.Claudio Menzani, Paolo Ciccioni
Ho conosciuto Daniele grazie ad una sua ex collega che mi ha parlato molto bene di lui e dei suoi servizi di consulenza e collaborazione nel campo della consulenza. Mi ha spinta a rivolgermi a Daniele la sua preparazione, professionalità e disponibilità.

(Leggi la testimonianza completa)