Chiamate a funzioni e output JSON strutturati con Ollama
Il function calling permette a un LLM di decidere autonomamente di chiamare una funzione del tuo codice — consultare il meteo, interrogare un database, inviare un'email — restituendo gli argomenti nel formato corretto. Il function calling con Ollama si basa su due componenti: il parametro format per garantire un JSON valido e il campo tools dell'API per dichiarare le funzioni disponibili. Questa guida mostra entrambi in Python, quali modelli locali sono davvero affidabili e come rendere il tutto robusto con la validazione dello schema e i tentativi di ripetizione in caso di errore.
#Perché il function calling in locale
Un LLM genera testo, non azioni. Il function calling riempie questo vuoto: invece di rispondere in prosa, il modello restituisce un oggetto strutturato che dice « chiama la funzione get_meteo con la città Parigi ». Il tuo codice esegue la funzione, ottiene il risultato reale, poi lo restituisce al modello che scrive la risposta finale. Questo è il meccanismo di base degli agenti e degli assistenti che interagiscono con il mondo esterno.
In locale, la sfida è duplice. Innanzitutto garantire che l'output sia un JSON analizzabile al 100% — un modello prolisso che aggiunge «Ecco il JSON:» compromette tutta la tua pipeline. Poi assicurarsi che il modello scelga la funzione giusta con gli argomenti corretti, cosa che diventa delicata con i modelli piccoli. Ollama gestisce entrambi gli aspetti tramite la sua API, ma con misure di salvaguardia da conoscere.
- Output JSON garantiti
- Il parametro format vincola la decodifica: il modello può produrre solo JSON sintatticamente valido, e persino conforme a uno schema preciso.
- Chiamata di funzione
- Il campo tools dichiara funzioni nel formato OpenAI; il modello restituisce tool_calls con gli argomenti da passare.
- 100 % locale
- Tutto funziona sulla tua macchina attraverso il daemon Ollama su http://localhost:11434, senza chiave API né fughe di dati.
#Prerequisiti e modelli supportati
Questa guida ti porta al modello. Il kit ti porta al copilota che scrive codice nel tuo editor.
- Spazio online a vita
- PDF + file
- Aggiornamenti a vita
La modalità JSON (parametro format) funziona con qualsiasi modello. Il function calling tramite tools, invece, richiede un modello addestrato all'uso degli strumenti — altrimenti il campo tool_calls rimane vuoto. Non tutti i modelli si equivalgono: un 3B «compatibile» sulla carta sbaglia spesso gli argomenti, mentre un 14B+ se la cava bene con schemi semplici.
- Ollama installato
- Daemon avviato e raggiungibile su http://localhost:11434. Verifica con ollama list.
- SDK Python
- pip install ollama pydantic — le client officiel plus Pydantic pour la validation.
- Modello affidabile per l'uso di strumenti
- qwen3.5:9b, mistral-small (24B) e gpt-oss:20b sono eccellenti punti di partenza nel 2026. In Q4: Qwen 3.5 9B ≈ 6,6 GB, un 24B ≈ 14 GB di VRAM.
- GPU consigliato
- Una RTX 3060 da 12 GB fa girare comodamente Qwen 3.5 9B; punta a un modello da 20-24B (RTX 4070/4080 da 16 GB) per un uso davvero affidabile degli strumenti.
#Forzare un JSON valido con il parametro format
Il caso più semplice: vuoi che il modello risponda sempre in JSON, mai in testo libero. Passa format: 'json' alla chiamata chat. Ollama vincola quindi la decodifica token per token per produrre un oggetto sintatticamente valido. Importante: mantieni un'istruzione esplicita nel prompt che descriva i campi attesi, altrimenti il modello inventa una struttura.
#JSON strutturato secondo uno schema (structured outputs)
Da fine 2024, Ollama accetta anche uno schema JSON completo in format (non solo la stringa 'json'). La decodifica è quindi vincolata a rispettare lo schema: tipi, campi obbligatori, enumerazioni. È molto più robusto della sola stringa 'json', perché il modello non può strutturalmente produrre un oggetto non conforme. Con Pydantic, lo schema viene generato automaticamente.
Qui la decodifica è vincolata alla struttura di Personne e model_validate_json esegue un ulteriore controllo di validazione in Python. Doppia rete di sicurezza: l'output è garantito analizzabile dal parser E conforme ai tipi dichiarati. È il pattern consigliato per qualsiasi estrazione di dati in produzione locale.
#L'API tools passo passo in Python
Passiamo al vero function calling. Si dichiarano le funzioni nel campo tools nel formato OpenAI (name, description, parameters in JSON Schema). Il modello legge queste definizioni e, se ritiene utile chiamare una funzione, restituisce uno o più tool_calls al posto di un messaggio testuale. Spetta a te eseguire la funzione e restituire il risultato.
- 01Descrivere le funzioniPer ogni funzione, fornisci un name chiaro, una descrizione precisa (il modello la usa per scegliere) e un campo parameters in formato JSON Schema che elenchi gli argomenti e indichi quali sono required.
- 02Inviare la chiamata con toolsPassa la lista tools a ollama.chat. Il modello decide da solo se chiamare una funzione o rispondere direttamente.
- 03Leggere le tool_callsControlla resp['message'].get('tool_calls'). Se è presente, il modello vuole chiamare una funzione con gli argomenti forniti.
- 04Eseguire e restituire il risultatoChiama la vera funzione Python, poi rimanda il suo risultato al modello in un messaggio con role 'tool', affinché rediga la risposta finale.
#Il ciclo chiamata → esecuzione → risposta
Il function calling è uno scambio di andata e ritorno. Prima chiamata: il modello restituisce un tool_call. Esegui la funzione. Seconda chiamata: invii al modello il risultato e il modello scrive la risposta in linguaggio naturale. Ecco il ciclo completo, riutilizzabile per più funzioni.
#Validazione dello schema e dei pattern di retry
In locale, i piccoli modelli a volte sbagliano: argomenti mancanti, tipo errato, funzione inesistente. Non fidarti mai dell'output grezzo. Sottoponi ogni tool_call a una validazione con Pydantic e, se la validazione fallisce, riprova inserendo il messaggio di errore nel contesto: spesso il modello si corregge al secondo tentativo.
- Validare prima di eseguire
- Un modello Pydantic per funzione rileva gli argomenti mancanti o di tipo errato prima che raggiungano il tuo codice.
- Riprova con feedback
- Riinserire il messaggio di errore nel contesto guida il modello verso la correzione. 2-3 tentativi sono sufficienti quasi sempre.
- Elenco delle funzioni consentite
- Rifiuta qualsiasi nome di funzione non presente nel dispatch. È sia una misura di sicurezza sia una protezione contro le allucinazioni.
- Fallback controllato
- Dopo N fallimenti, rispondi all'utente con un messaggio chiaro anziché andare in crash — soprattutto con un modello piccolo.
#Le insidie dei piccoli modelli nell'uso degli strumenti
L'uso di strumenti è cognitivamente impegnativo: il modello deve comprendere l'intenzione, scegliere la funzione corretta, mappare gli argomenti e rispettare il formato. Al di sotto dei 7B, i risultati sono fragili. Ecco cosa si rompe più spesso in locale e come risolverlo.
- tool_calls vuoto
- Il modello risponde con testo invece di chiamare la funzione. Spesso un modello non addestrato all'uso degli strumenti o una descrizione della funzione troppo vaga. Passa a Qwen 3.5 o Mistral Small e cura le descrizioni.
- Argomenti errati
- Il modello inventa o dimentica campi. Impostali come required nello schema, riduci il numero di funzioni esposte contemporaneamente ed esegui sempre la validazione.
- Funzione inventata dal modello
- Il modello chiama una funzione che non esiste. È obbligatorio avere una lista bianca dal lato del dispatch.
- JSON sporco
- Senza formato, un modello piccolo aggiunge testo intorno al JSON. Usa sempre format='json' o uno schema per l'estrazione pura.
- Troppe funzioni
- Oltre 5-6 strumenti, i modelli piccoli si perdono. Suddividi per sottoattività oppure effettua il routing in due fasi.
#Per approfondire
Il function calling è la base degli agenti e delle integrazioni avanzate. Queste guide del sito approfondiscono gli argomenti trattati in questa guida:
- Integrare Ollama tramite API REST in Python
- L'endpoint compatibile con OpenAI sulla porta :11434, lo streaming e la modalità JSON in una vera app FastAPI/Flask.
- Creare un agente IA locale con LangChain e Ollama
- Passare dal function calling di base a un agente completo che concatena strumenti, memoria e ragionamento.
- MCP e LLM locale: collegare server MCP a Ollama
- Standardizzare l’accesso agli strumenti (file, web, database) tramite Model Context Protocol invece di definire ogni funzione a mano.
Un feedback, un errore, una precisazione? Facci sapere, così la guida migliora per tutti.