Sfruttare il Function Calling per creare applicazioni LLM più intelligenti
I modelli linguistici di grandi dimensioni (LLM) non si limitano più a generare testo; ora gestiscono attività più complesse e guidate dal contesto. Un progresso chiave in quest’area è la function calling, che consente agli LLM di interagire con strumenti esterni, database e API per eseguire operazioni dinamiche. Questo permette loro di andare oltre la generazione di testo e lavorare con dati e servizi del mondo reale.
In un recente Berlin Unstructured Data Meetup ospitato da Zilliz, Nikolai Danylchyk, customer engineer presso Google, ha discusso di come Gemini, un LLM moderno, utilizzi la function calling per estendere le proprie capacità. Questo blog riepilogherà i suoi spunti e dimostrerà come sfruttare questa potente funzionalità per creare applicazioni LLM avanzate. Se vuoi conoscere maggiori dettagli, ti consigliamo di guardare la replica dell’intervento di Nikolai su YouTube.
Comprendere la function calling avanzata negli LLM
Gli LLM si sono evoluti in modo significativo, ma il loro vero potenziale emerge quando interagiscono con sistemi esterni tramite chiamate di funzione. Questa capacità consente agli LLM di andare oltre i limiti dei loro dati di addestramento statici interrogando database live, eseguendo comandi o svolgendo calcoli in tempo reale. Integrando la function calling, gli LLM possono connettersi senza soluzione di continuità con altri sistemi per fornire risposte più accurate, attuali e dinamiche. Analizziamo come funziona la function calling usando Gemini come esempio.
Figura 1- Passaggi della function calling e componenti utilizzati in fase di esecuzione
Figura 1: Passaggi della function calling e componenti utilizzati in fase di esecuzione.
Il processo inizia quando un utente invia una richiesta all’API Gemini. A questo punto, lo sviluppatore ha già definito una o più dichiarazioni di funzione all’interno dello strumento, informando Gemini delle funzioni disponibili e di come eseguirle. Una volta ricevuto l’input dell’utente, l’API Gemini analizza il contenuto e il prompt, restituendo una risposta "Function Call". Questa risposta include dati strutturati, come il nome della funzione da chiamare e i parametri pertinenti.
Il passaggio successivo avviene al di fuori del sistema Gemini: l’applicazione utilizza il nome della funzione e i parametri dalla risposta di Gemini per effettuare una richiesta API a un servizio esterno. È qui che interviene lo sviluppatore, utilizzando strumenti come la libreria
requestsin Python per chiamare un’API REST o qualsiasi altra libreria client adatta alle proprie esigenze.Dopo che il sistema esterno restituisce la sua risposta, l’applicazione invia quei dati nuovamente a Gemini. Il modello utilizza quindi queste nuove informazioni per generare una risposta finale per l’utente. Se sono necessari dati aggiuntivi, Gemini può emettere un’altra chiamata di funzione, continuando il ciclo secondo necessità.
Per comprendere l’importanza di questa capacità avanzata, considera un LLM tradizionale senza la funzionalità di function calling. Le sue risposte vengono generate in base ai dati su cui è stato addestrato, che potrebbero essere obsoleti o limitati nell’ambito. Tuttavia, con le chiamate di funzione, un LLM può emettere comandi per recuperare informazioni in tempo reale da un database, aggiornare un record in un sistema di gestione delle relazioni con i clienti (CRM) o persino attivare azioni come prenotare un biglietto o effettuare un ordine. Questo approccio amplia l’usabilità del modello dalla semplice generazione di risposte all’esecuzione di attività.
In termini tecnici, una chiamata di funzione in un LLM comporta un’interazione strutturata tra il modello e un’API o un servizio esterno. Il modello identifica uno scenario adatto in cui è richiesta una chiamata di funzione, formula i parametri per la chiamata e la esegue.
Ad esempio, se un utente chiede: “Che tempo fa a Berlino?” La chiamata di funzione attiverebbe un’API meteo, recuperando dati in tempo reale per generare la risposta. In questo caso, l’LLM agisce come intermediario intelligente tra l’utente e il sistema esterno, orchestrando un’interazione più accurata e utile.
Ora che abbiamo esplorato il concetto di base della function calling, vediamo un’implementazione pratica usando Gemini per interagire con un’API del mondo reale: il recupero dei tassi di cambio valutari.
Esempio: utilizzo della Function Calling per il recupero dei tassi di cambio valutari
Vediamo come possiamo utilizzare un’API per i tassi di cambio valutari tramite la function calling di Gemini:
Installazione delle librerie necessarie e impostazione delle variabili di progetto
Iniziamo aggiornando e installando la libreria google-cloud-aiplatform, necessaria per interagire con la piattaforma Vertex AI di Google Cloud. Quindi, fornisci il tuo ID progetto e la posizione come variabili.
!pip3 install --upgrade --user --quiet google-cloud-aiplatform
PROJECT_ID = "[your-project-id]" # @param {type:"string"}
LOCATION = "us-central1" # @param {type:"string"}
Questi sono segnaposto per identificare il progetto e la regione di Google Cloud con cui stai lavorando.
Importazione dei moduli necessari e definizione del modello generativo
Quindi, importa i moduli richiesti per definire e lavorare con un modello generativo da Vertex AI. La libreria requests verrà utilizzata in seguito per recuperare dati da un’API esterna.
import requests
from vertexai.generative_models import (
Content,
FunctionDeclaration,
GenerativeModel,
Part,
Tool,
)
model = GenerativeModel("gemini-1.5-pro-001")
L’ultima riga inizializza un modello generativo, in questo caso, gemini-1.5-pro-001. In seguito utilizzerai il modello per generare risposte in base al prompt di input.
Definizione di una funzione per i tassi di cambio valutari e creazione di uno strumento
Successivamente, crea una funzione che descriva i parametri necessari per ottenere un tasso di cambio tra due valute e racchiudila in uno strumento.
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],
)
I parametri includono currency_date (in formato YYYY-MM-DD o la parola chiave latest), currency_from (il codice ISO 4217 della valuta da cui convertire) e currency_to (il codice ISO 4217 della valuta verso cui convertire). La sezione required specifica che currency_from e currency_date sono obbligatori. Definiamo quindi uno strumento chiamato exchange_rate_tool, che racchiude la dichiarazione della funzione get_exchange_rate. In seguito passeremo questo strumento al modello per gestire il recupero dei tassi di cambio.
Generazione di una risposta con il modello ed estrazione dei parametri dalla risposta
Ora invochiamo una risposta passando un prompt al modello. Ci aspettiamo che il modello produca una risposta contenente una chiamata di funzione con parametri.
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
Il codice sopra definisce un prompt che chiede il tasso di cambio tra dollari australiani e corone svedesi. Il modello viene quindi chiamato utilizzando generate_content, passando il prompt insieme a exchange_rate_tool. Il modello tenterà di generare una risposta.
La risposta viene quindi analizzata. Il dizionario params viene popolato iterando attraverso le chiavi e i valori di function_call.args e rimuovendo i primi 9 caratteri della chiave per corrispondere ai nomi dei parametri previsti.
Recuperare i tassi di cambio da un’API e fornire una risposta all’utente
Ora richiediamo la Frankfurter API (un’API gratuita per i tassi di cambio) utilizzando i parametri estratti dalla risposta precedente e generiamo una risposta per l’utente.
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
Nel codice sopra, una volta ottenuta una risposta dall’API dei tassi di cambio, chiamiamo di nuovo il metodo generate_content, questa volta passando più contenuti: uno dall’utente (che richiede passaggi dettagliati e contesto), una chiamata di funzione a get_exchange_rate e la risposta dalla Frankfurter API. Questa combinazione spinge il modello a fornire una risposta più approfondita, passo dopo passo. Infine stampiamo la parte di testo del contenuto generato dal modello. Questa è la risposta che restituiamo all’utente.
Ecco una risposta di esempio:
Figura 2- Output di un programma che mostra il tasso di cambio da dollari australiani a corone svedesi
Figura 2: Output di un programma che mostra il tasso di cambio da dollari australiani a corone svedesi
La risposta mostra che la chiamata di funzione ha funzionato e ci ha fornito il cambio attuale come indicato dalla Frankfurter API.
Finora abbiamo trattato la function calling, la funzionalità avanzata di Gemini e di molti altri LLM. Sebbene la sola function calling possa eseguire attività complesse come il recupero di valute, il suo vero potenziale si realizza quando viene combinata con altre tecniche potenti, come la Retrieval Augmented Generation (RAG).
Combinare la Function Calling con la Retrieval-Augmented Generation (RAG) per una maggiore interattività
Retrieval Augmented Generation (RAG) è diventata una delle tendenze più significative nell'elaborazione del linguaggio naturale (NLP). I sistemi RAG combinano le capacità generative degli LLM con l'efficienza dei sistemi di retrieval alimentati da database vettoriali come Milvus e Zilliz Cloud (il Milvus gestito). In particolare, in un sistema RAG, il database vettoriale recupera informazioni contestuali per l'LLM, e poi l'LLM genera una risposta più accurata basata sulle informazioni recuperate. La chiamata di funzioni migliora questo processo consentendo un'interazione più dinamica tra l'LLM e database o sistemi esterni. Con l'aggiunta delle chiamate di funzione, gli LLM possono estendere le proprie capacità non solo recuperando dati rilevanti, ma anche elaborandoli e interagendo con essi in tempo reale.
Ad esempio, in un'applicazione di assistenza clienti che utilizza sia RAG sia la chiamata di funzioni, l'LLM offre un'interazione più ricca e personalizzata. Quando un utente chiede: “Dov'è il mio ordine recente?” Il sistema impiega prima RAG per recuperare informazioni generali sull'elaborazione degli ordini dal database vettoriale Milvus, fornendo contesto. Ad esempio, l'informazione recuperata è“gli ordini in genere richiedono 3-5 giorni lavorativi per la consegna.” Contemporaneamente, tramite la chiamata di funzioni, accede a dati in tempo reale interrogando l'account del cliente. La risposta finale diventa: “Il tuo ordine #12345 è stato spedito il 10 settembre e dovrebbe arrivare il 15 settembre.”
Questa integrazione di RAG con la chiamata di funzioni crea un sistema dinamico che non solo genera risposte pertinenti e informative, ma interagisce anche attivamente con dati e servizi live portando una dimensione interattiva. Questa combinazione rende gli agenti intelligenti basati su LLM capaci di realizzare interazioni complesse nel mondo reale.
- Consulta questo tutorial per una guida passo passo su come sfruttare le capacità di chiamata di funzioni degli LLM per migliorare i sistemi RAG.
Casi d'uso della combinazione di RAG e chiamata di funzioni
Diamo un'occhiata a diverse di queste interazioni nel mondo reale.
Sanità: recupero delle cartelle cliniche e pianificazione degli appuntamenti
Nella sanità, RAG combinato con la chiamata di funzioni consente agli LLM di fornire supporto altamente personalizzato e basato sui dati sia ai pazienti sia agli operatori sanitari. Un medico potrebbe chiedere al sistema i dati storici di un paziente, mentre il sistema recupera le cartelle cliniche pertinenti utilizzando RAG da un database vettoriale come Milvus. Allo stesso tempo, tramite la chiamata di funzioni, l'LLM può interagire con sistemi ospedalieri esterni per pianificare appuntamenti di follow-up o recuperare dati diagnostici in tempo reale.
Esempio: Un medico chiede: “Qual è il risultato dell'ultimo test per il paziente X, e puoi prenotare un appuntamento di follow-up per la prossima settimana?” Il sistema interroga prima Milvus per recuperare documenti correlati dalla storia clinica del paziente, fornendo informazioni su tendenze e condizioni. Successivamente, utilizza la chiamata di funzioni per accedere all'API di pianificazione dell'ospedale e prenotare un appuntamento per il paziente.
Finanza: approfondimenti di investimento personalizzati e transazioni in tempo reale
Nel settore finanziario, RAG viene impiegato per recuperare informazioni di mercato rilevanti e dati finanziari storici archiviati in database vettoriali come Milvus. Associandolo alla chiamata di funzioni, un LLM può anche eseguire azioni in tempo reale come acquistare o vendere azioni, trasferire fondi o generare raccomandazioni di portafoglio personalizzate basate su dati live.
Esempio: Un utente chiede: “Come si è comportato il mio portafoglio negli ultimi sei mesi e puoi acquistare azioni Apple per un valore di 1000 dollari?” Il sistema utilizza prima RAG per recuperare la cronologia del portafoglio dell’utente da Milvus, fornendo un riepilogo delle performance passate. Poi, utilizzando la function calling, interagisce con un’API di trading per eseguire l’acquisto delle azioni e confermare la transazione all’utente.
E-Commerce: Raccomandazioni di prodotti e tracciamento degli ordini in tempo reale
Nell’e-commerce, RAG può aiutare a recuperare informazioni sui prodotti, recensioni o la cronologia dei clienti da Milvus per personalizzare l’esperienza di acquisto. Quando combinato con la function calling, il sistema può interagire con sistemi di inventario in tempo reale per fornire la disponibilità a magazzino, tracciare gli ordini in tempo reale o persino elaborare i pagamenti.
Esempio: Un cliente chiede, Puoi consigliarmi un laptop simile al mio ultimo acquisto e dirmi quando arriverà il mio ordine attuale? L’LLM recupera informazioni sugli acquisti precedenti del cliente da Milvus e consiglia un prodotto simile. La function calling viene poi utilizzata per interrogare l’API di tracciamento degli ordini e fornire aggiornamenti in tempo reale sullo stato di consegna dell’ordine attuale.
Viaggi: Suggerimenti per itinerari e gestione delle prenotazioni
Nel settore dei viaggi e dell’ospitalità, RAG può recuperare dettagli su destinazioni, hotel e itinerari di viaggio archiviati in un database vettoriale come Milvus. Abbinato alla function calling, il sistema può gestire prenotazioni, suggerire itinerari personalizzati o offrire aggiornamenti in tempo reale su voli e prenotazioni.
Esempio: Un viaggiatore chiede, Puoi suggerirmi un itinerario di 5 giorni in Italia e riprogrammare la mia prenotazione alberghiera per una data anticipata? Il sistema recupera prima suggerimenti di itinerario da Milvus in base alle preferenze e ai viaggi passati del viaggiatore. Poi, utilizza la function calling per interagire con il sistema di prenotazione dell’hotel, modificare la prenotazione e confermare la modifica all’utente.
Mentre vediamo come la function calling potenzi sistemi come RAG, è importante riconoscere le sfide pratiche e i vantaggi quando si implementano tali tecnologie in applicazioni reali.
Sfide e vantaggi della function calling nei casi d’uso del mondo reale
Sebbene il potenziale della function calling sia immenso, comporta una serie di sfide proprie. Una delle principali preoccupazioni è garantire la sicurezza e la privacy delle interazioni. Quando un LLM emette chiamate di funzione, può richiedere l’accesso a dati sensibili, come account utente o informazioni finanziarie. Garantire che queste transazioni siano sicure e conformi alle normative sulla privacy dei dati è fondamentale.
Inoltre, la complessità della gestione di più chiamate di funzione in un singolo flusso di lavoro può portare a problemi di latenza. Ad esempio, se un LLM emette diverse chiamate di funzione verso sistemi differenti, il tempo di risposta può aumentare, potenzialmente influenzando l’esperienza utente. Questo è particolarmente importante nelle applicazioni in tempo reale, dove la velocità è critica.
Sul lato positivo, la function calling offre diversi vantaggi, tra cui automazione avanzata delle attività, risposte in tempo reale più accurate e migliore interazione con l’utente. In settori come sanità, finanza e servizio clienti, la function calling può semplificare le operazioni automatizzando le attività di routine. Ad esempio, nella sanità, un LLM potrebbe recuperare le cartelle cliniche dei pazienti, programmare appuntamenti e inviare promemoria tramite chiamate di funzione, liberando tempo per i professionisti medici affinché possano concentrarsi su casi più complessi.
Oltre ai vantaggi e alle sfide pratiche, ci sono considerazioni etiche e tecniche che non devono essere trascurate, in particolare riguardo alla sicurezza dei dati e all’affidabilità del sistema.
Considerazioni etiche e tecniche
Da un punto di vista tecnico, noi sviluppatori dobbiamo gestire con attenzione il modo in cui le chiamate di funzioni vengono implementate per evitare potenziali insidie. Un problema comune è l’eccessiva dipendenza da sistemi esterni. Se un LLM emette costantemente chiamate di funzioni a servizi di terze parti, l’affidabilità del sistema diventa dipendente dalla disponibilità e dalle prestazioni di tali servizi. Devono essere predisposti una corretta gestione degli errori e meccanismi di fallback per garantire che il sistema continui a funzionare senza problemi, anche quando i servizi esterni non sono disponibili.
Dal punto di vista etico, la chiamata di funzioni solleva preoccupazioni riguardo alla trasparenza e al consenso dell’utente. Se un LLM prende decisioni o compie azioni per conto di un utente, è essenziale che l’utente sia pienamente consapevole di ciò che il sistema sta facendo. Per esempio, nei servizi finanziari, se un LLM esegue operazioni di trading o trasferisce fondi, gli utenti dovrebbero essere informati sulle azioni intraprese e dovrebbero avere la possibilità di intervenire se necessario. Una documentazione chiara e meccanismi di consenso dell’utente sono fondamentali per mantenere la fiducia in tali sistemi.
Un’altra preoccupazione etica riguarda l’uso dei dati. Quando le chiamate di funzioni accedono a dati personali o sensibili, devono essere in atto misure rigorose per proteggere la privacy dell’utente. Gli sviluppatori devono garantire che i dati siano gestiti in modo responsabile e che le chiamate di funzioni siano conformi alle normative sulla privacy come GDPR o HIPAA.
Conclusione
Nikolai ha svolto un lavoro fantastico nel fare luce su come la chiamata di funzioni offra un miglioramento fondamentale ai grandi modelli linguistici, consentendo loro di eseguire attività del mondo reale interagendo con sistemi e dati esterni. Che si tratti di recuperare tassi di cambio o di alimentare interazioni più complesse tramite Retrieval-Augmented Generation (RAG), la chiamata di funzioni amplia gli orizzonti di ciò che gli LLM possono realizzare.
Ulteriori letture
Continua a leggere

A Developer's Guide to Exploring Milvus 2.6 Features on Zilliz Cloud
Milvus 2.6 marks a shift from “vector search + glue code” to a more advanced retrieval engine, and it is now Generally Available (GA) on Zilliz Cloud (a managed Milvus service).

The Real Bottlenecks in Autonomous Driving — And How AI Infrastructure Can Solve Them
Autonomous driving faces a data bottleneck. Learn how AI-native vector databases like Zilliz solve scale, cost, and insight challenges across AV pipelines.

Zilliz Cloud Enterprise Vector Search Powers High-Performance AI on AWS
Zilliz Cloud on AWS powers secure, scalable, ultra-fast vector search for enterprise AI apps, with BYOC, sub-10ms latency, and zero-DevOps simplicity.


