Corso
Mistral ha rilasciato la Agents API, un framework che facilita lo sviluppo di agenti AI intelligenti e autonomi, in grado di svolgere compiti complessi e multi-step. Va oltre i tradizionali modelli linguistici integrando l’uso di strumenti, memoria persistente e capacità di orchestrazione.
In questo tutorial ti mostrerò come usare la Agents API di Mistral per costruire assistenti intelligenti in grado di:
- Usare strumenti come ricerca web, esecuzione di codice e generazione di immagini
- Mantenere la memoria lungo conversazioni estese per preservare il contesto
- Delegare compiti tra più agenti
Imparerai i concetti alla base del framework agentico di Mistral, esplorerai i connettori integrati e le funzionalità di orchestrazione e costruirai un assistente multi-agente funzionante.
Teniamo i nostri lettori aggiornati sulle ultime novità dell’AI con The Median, la nostra newsletter gratuita del venerdì che riassume le notizie chiave della settimana. Iscriviti e resta sul pezzo in pochi minuti a settimana:
Che cos’è la Agents API di Mistral?
La Agents API di Mistral è un framework che consente ai large language model di effettuare azioni multi-step, usare strumenti esterni e mantenere la memoria tra le interazioni. Diversamente dalle semplici API di chat, dà agli agenti AI la possibilità di:
- Accedere al web, eseguire codice, generare immagini o recuperare documenti
- Coordinarsi con altri agenti tramite orchestrazione
- Mantenere conversazioni persistenti con memoria a lungo termine
Attualmente sono supportati solo mistral-medium-latest (noto anche come mistral-medium-2505) e mistral-large-latest, ma presto potrebbero essere supportati nuovi modelli.
Concetti chiave spiegati
Prima di passare alla parte pratica, è utile chiarire i concetti fondamentali della Agents API.

Fonte: Mistral AI
Agenti
Gli agenti in Mistral sono personae guidate dal modello, arricchite con istruzioni predefinite, accesso a strumenti e stato della conversazione:
- Le istruzioni guidano il comportamento dell’agente (ad es. “Sei un coach nutrizionale che registra i pasti”).
- Strumenti come
web_searchoimage_generationpermettono agli agenti di compiere azioni nel mondo reale. - La memoria consente agli agenti di tenere traccia dei messaggi precedenti e degli output degli strumenti nei vari turni, supportando il ragionamento contestuale.
Questa astrazione trasforma un modello di chat di base in un assistente multifunzionale capace di gestire workflow complessi.
Conversazioni
Ogni interazione tra un utente e un agente fa parte di una conversazione, che memorizza:
- Messaggi passati e risposte dell’assistente
- Chiamate agli strumenti e risultati
- Metadati di streaming per visibilità a livello di token (opzionale)
Queste conversazioni persistenti permettono agli agenti di svolgere compiti multi-turn come pianificazione, revisione o apprendimento dagli input precedenti.
Connettori e supporto per strumenti personalizzati
Mistral consente un’integrazione semplice degli strumenti tramite:
- Connettori: strumenti preintegrati come
web_search,code_execution,image_generation,document_libraryche funzionano subito. - Strumenti MCP: permettono API personalizzate ospitate dagli sviluppatori, richiamabili come strumenti nel workflow dell’agente.
Pensa ai connettori come ad app integrate e agli strumenti MCP come a plugin che scrivi tu. Insieme, consentono agli agenti di accedere sia a capacità integrate sia a endpoint definiti dallo sviluppatore per logiche personalizzate.

Fonte: Mistral AI
Voci ed handoff
Mistral traccia tutte le azioni in una conversazione come “Voci” strutturate, abilitando tracciabilità e controllo sugli scambi di messaggi e sulle esecuzioni degli strumenti.
Gli handoff tra agenti sono quelli in cui un agente delega il controllo a un altro per modularizzare i workflow.

Fonte: Mistral AI
Questa architettura di orchestrazione rende semplice comporre e gestire sistemi multi-agente complessi senza perdere trasparenza o controllo.
Configurare la Mistral API
Iniziamo configurando Mistral. Partiremo creando una chiave API per il progetto. Ecco i passaggi da seguire:
- Per iniziare, crea un account Mistral o accedi su console.mistral.ai.

- Poi vai su Workspace Settings (freccia a discesa vicino al tuo nome — angolo in alto a sinistra) e fai clic su Billing per aggiungere i dati di pagamento e attivare i pagamenti sul tuo account.

- Fai clic su Add credits e compila i dati di fatturazione nel modulo. Poi inserisci il numero di crediti desiderati. Nota: devi aggiungere almeno 10 crediti.

- Quindi, nella scheda a sinistra, fai clic su API keys e crea una nuova chiave API con Create new key. Assicurati di copiare la chiave, salvarla in modo sicuro e non condividerla con nessuno.
Ora hai una chiave API valida per interagire con i modelli Mistral e costruire agenti intelligenti.
Panoramica del progetto: Nutrition Coach con Mistral Agents
In questo progetto costruiremo un Nutrition Coach basato su AI usando la Agents API di Mistral. Ecco il flusso utente:
- L’utente invia un pasto appena consumato (es. "insalata di pollo con condimento all’olio d’oliva").
- Un agente di ricerca web usa il connettore integrato per stimare le calorie del pasto.
- Un agente di logging registra questa voce con nome utente e timestamp.
- Infine, un agente di generazione immagini suggerisce un pasto successivo salutare, restituendo sia un’immagine sia una descrizione e ricetta.
Per offrire un’interfaccia web con cui gli utenti possano interagire con il nutrizionista, useremo Gradio.
Step 1: Prerequisiti
Prima di iniziare, assicurati di avere installato:
- Python 3.8+
- Tutti i pacchetti richiesti elencati in
requirements.txt
python-dotenv==1.1.0
mistralai==0.0.7
typing-extensions==4.12.2
requests==2.31.0
gradio==4.34.0
Inoltre, configura un file .env che contenga la tua chiave API di Mistral. Questo approccio mantiene sicure le chiavi API e consente a membri del team o ambienti di deploy diversi di usare credenziali differenti senza modificare il codice sorgente.
MISTRAL_API_KEY=YOUR_API_KEY
Nota: è consigliato installare queste dipendenze in un ambiente isolato come conda, venv o uv per evitare conflitti di versione con altri progetti Python.
Ecco i comandi per configurare diversi ambienti:
Con venv
python -m venv mistral_env
source mistral_env/bin/activate # On Windows: mistral_env\Scripts\activate
Con Conda
conda create -n mistral_env python=3.10
conda activate mistral_env
Con uv
Se non hai ancora uv:
pip install uv
Poi:
uv venv mistral_env
source mistral_env/bin/activate
Per installare tutte le dipendenze sopra menzionate, esegui il seguente comando nel terminale:
pip install -r requirements.txt
Nota: se riscontri errori relativi a mistralai usando un qualsiasi agente o connettore, esegui il seguente comando:
pip install –upgrade mistralai
Questo aggiornerà la libreria mistralai alla versione più recente.
Step 2: Configurare gli strumenti di Mistral
In questa sezione prepareremo i nostri strumenti e la configurazione del client per l’interazione con la Agents API di Mistral. Definiremo gli schemi degli strumenti, inizializzeremo il client e verificheremo l’autenticazione. Questi strumenti verranno poi richiamati quando imposteremo agenti specifici come stimatori di calorie o generatori di immagini.
Step 2.1: Registro strumenti e inizializzazione
Per prima cosa, definiamo gli schemi dei nostri strumenti, la selezione del modello e l’istanza del client. Poi costruiamo metodi di supporto come create_chat_completion() e check_client(). Il codice seguente va nel file configs.py dentro la cartella tools:
#Configuration file
from mistralai import Mistral, UserMessage, SystemMessage
from dotenv import load_dotenv
import os
load_dotenv()
# Mistral model
mistral_model = "mistral-large-latest"
client = Mistral(api_key=os.environ.get("MISTRAL_API_KEY"))
# Agent IDs
web_search_id = "web_search_agent"
food_logger_id = "food_logger_agent"
user_assistant_id = "user_assistant_agent"
image_generator_id = "image_generator_agent"
# Tool definitions
tools = {
"log_meal": {
"name": "log_meal",
"description": "Log a user's meal with calorie count",
"input_schema": {
"type": "object",
"properties": {
"username": {"type": "string"},
"meal": {"type": "string"},
"calories": {"type": "number"},
"timestamp": {"type": "string", "format": "date-time"}
},
"required": ["username", "meal", "calories", "timestamp"]
}
},
"web_search": {
"name": "web_search",
"description": "Search the web for information about a meal",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"}
},
"required": ["query"]
}
}
}
Iniziamo importando dotenv per caricare variabili sensibili come la chiave API di Mistral da un file .env locale nell’ambiente Python. Questo mantiene le credenziali al sicuro e fuori dal codice sorgente. Quindi selezioniamo il modello predefinito mistral-large-latest e istanziamo un client Mistral usando la chiave API.
Successivamente, definiamo specifiche interne degli strumenti (schemi) usando il formato JSON Schema. Aiutano a:
- Simulare il comportamento degli strumenti MCP (anche se non sono registrati tramite la libreria McpTool)
- Descrivere gli input attesi come "username", "meal" e "calories"
- Garantire una formattazione coerente degli input tra i moduli
Ora aggiungiamo i metodi di supporto che creano le chat completion, registrano strumenti e agenti e inizializzano il client.
def create_chat_completion(messages, model=mistral_model):
# Convert messages to new format
formatted_messages = []
for msg in messages:
if msg["role"] == "system":
formatted_messages.append(SystemMessage(content=msg["content"]))
else:
formatted_messages.append(UserMessage(content=msg["content"]))
return client.chat.complete(
model=model,
messages=formatted_messages
)
# Register tools
def register_tools():
for tool_name, tool in tools.items():
print(f"Registered tool: {tool_name}")
# Register agents
def register_agents():
print("Registered User Assistant Agent")
print("Registered Web Search Agent")
print("Registered Food Logger Agent")
# Initialize everything
def initialize():
register_tools()
register_agents()
check_client()
# Check if the client is initialized
def is_client_initialized():
return client is not None and os.environ.get("MISTRAL_API_KEY") is not None
def check_client():
if not is_client_initialized():
print("Mistral client is not initialized. Please check your API key.")
return False
print("Mistral client is initialized.")
return True
initialize()
La funzione create_chat_completion() incapsula una chiamata al metodo client.chat.complete(), parte dell’SDK Mistral, per inviare messaggi al modello.
- Riformatta i messaggi in dizionario in oggetti
UserMessageeSystemMessagerichiesti dall’SDK Mistral. - È utile anche per uniformare le completion in tutta l’app.
Le funzioni register_tools() e register_agents() aiutano durante lo sviluppo locale registrando quali strumenti e agenti sono attivi nel sistema. Nel frattempo, le funzioni check_client() e is_client_initialized() garantiscono che il client Mistral sia stato correttamente istanziato e che la chiave API sia disponibile, aiutando a evitare errori a runtime durante l’esecuzione degli agenti.
Step 2.2: Stimare le calorie con l’agente di ricerca web
Ora che abbiamo inizializzato gli strumenti di base e il client, costruiamo un Nutrition Web Search Agent dedicato. Questo agente usa il connettore web_search di Mistral per cercare in tempo reale stime caloriche dei pasti. Questo codice si trova nel file web_search.py dentro la cartella tools.
# Web search tool
import re
from mistralai import Mistral, UserMessage, SystemMessage
from tools.configs import client
def search_calories(meal_desc):
try:
# Web search agent
websearch_agent = client.beta.agents.create(
model="mistral-medium-latest",
description="Agent able to search for nutritional information and calorie content of meals",
name="Nutrition Search Agent",
instructions="You have the ability to perform web searches with web_search to find accurate calorie information. Return ONLY a single number representing total calories.",
tools=[{"type": "web_search"}],
completion_args={
"temperature": 0.3,
"top_p": 0.95,
}
)
response = client.beta.conversations.start(
agent_id=websearch_agent.id,
inputs=f"What are the total calories in {meal_desc}?"
)
print("Raw response:", response)
# Extract the number from the response
if hasattr(response, 'outputs'):
for output in response.outputs:
if hasattr(output, 'content'):
if isinstance(output.content, str):
numbers = re.findall(r'\d+', output.content)
if numbers:
return int(numbers[0])
elif isinstance(output.content, list):
for chunk in output.content:
if hasattr(chunk, 'text'):
numbers = re.findall(r'\d+', chunk.text)
if numbers:
return int(numbers[0])
print("No calorie information found in web search response")
return 0
except Exception as e:
print(f"Error during web search: {str(e)}")
return 0
Nel codice sopra, la funzione search_calories() usa il connettore integrato per la ricerca web della Agents API di Mistral, che consente agli agenti di effettuare query live sul web come la stima delle calorie, superando i limiti dell’addestramento statico del modello. Ecco come funziona:
- Creazione dell’agente: crea innanzitutto un “Nutrition Search Agent” usando il modello
mistral-medium-latest, dotato dello strumentoweb_searche istruito a restituire solo le calorie. - Esecuzione della query: l’agente viene poi usato per avviare una conversazione in cui gli si chiede il totale delle calorie nella descrizione del pasto fornita.
- Parsing della risposta: la risposta dell’agente viene analizzata con espressioni regolari per estrarre il primo valore numerico (che dovrebbe corrispondere al conteggio calorico).
- Fallback: se non viene trovato alcun numero valido o si verifica un errore, la funzione registra il problema e restituisce zero come fallback.
Senza web_search, la maggior parte dei modelli non può rispondere su eventi recenti o pasti specifici di dominio non visti in fase di training. Con esso, possiamo interrogare in tempo reale informazioni nutrizionali, menù di ristoranti o articoli di cronaca.
Esistono due varianti della ricerca web:
web_search: un connettore di ricerca generale e leggero (usato nel nostro progetto).web_search_premium: una versione avanzata che include verifica dei provider di notizie e una raccolta di contesto più ampia.
A seguire, esploreremo una stima calorica di fallback basata solo su prompt.
Step 2.3: Stima, logging e suggerimento del pasto
In questa sezione implementiamo tre funzioni essenziali che agiscono da fallback o potenziamenti. Il codice seguente si trova nel file next.py nella cartella tools.
#Meal suggestions
from datetime import datetime
from tools.configs import client, create_chat_completion
from mistralai import SystemMessage, UserMessage
import re
def estimate_calories(meal_desc):
try:
# Messages for calorie estimation
messages = [
SystemMessage(content="You are a nutrition expert. Estimate calories in meals. Return ONLY a single number representing total calories."),
UserMessage(content=f"Estimate calories in: {meal_desc}")
]
response = client.chat.complete(
model="mistral-small-latest", # Using smaller model to avoid rate limits
messages=messages,
temperature=0.1,
max_tokens=50
)
content = response.choices[0].message.content
numbers = re.findall(r'\d+', content)
if numbers:
return int(numbers[0])
return 0
except Exception as e:
print(f"Error during calorie estimation: {str(e)}")
return 0
def log_meal(username, meal, calories):
try:
# Messages for meal logging
messages = [
SystemMessage(content="You are a meal logging assistant. Log the user's meal with calories."),
UserMessage(content=f"Log this meal: {meal} with {calories} calories for user {username} at {datetime.utcnow().isoformat()}")
]
response = client.chat.complete(
model="mistral-small-latest", # Using smaller model to avoid rate limits
messages=messages,
temperature=0.1,
max_tokens=100
)
return response.choices[0].message.content.strip()
except Exception as e:
print(f"Error during meal logging: {str(e)}")
return f"Logged {meal} ({calories} calories) for {username}"
def suggest_next_meal(calories, dietary_preference):
try:
# Messages for meal suggestion
messages = [
SystemMessage(content="You are a nutrition expert. Suggest healthy meals based on calorie intake and dietary preferences."),
UserMessage(content=f"Suggest a {dietary_preference} meal that would be a good next meal after consuming {calories} calories. Make it specific and appetizing.")
]
response = client.chat.complete(
model="mistral-small-latest",
messages=messages,
temperature=0.7
)
return response.choices[0].message.content.strip()
except Exception as e:
print(f"Error during meal suggestion: {str(e)}")
return "Unable to suggest next meal at this time."
Questo script definisce le funzioni backend principali che alimentano il nostro workflow nutrizionale (dalla stima calorica alla pianificazione del pasto successivo). Queste funzioni usano modelli Mistral leggeri e chat completion standard, senza richiedere la creazione di agenti o l’uso di connettori quando la ricerca web non è disponibile o per evitare errori di rate limit. Ecco cosa fa ciascuna funzione:
estimate_calories(): viene usata come fallback se il connettoreweb_searchfallisce o non è disponibile.- Invia un messaggio di sistema con il ruolo dell’assistente come esperto di nutrizione insieme al prompt dell’utente che include il pasto da registrare.
- Il modello viene usato con
temperature=0.1per un output deterministico. Ciò significa che il modello produrrà risposte coerenti e ripetibili per gli stessi input in compiti come stima delle calorie e logging, dove si preferiscono output stabili e fattuali rispetto alla creatività. - Analizza il primo numero (via regex) dalla risposta del modello.
log_meal(): registra il pasto dell’utente, incluso un timestamp.- Usa una chat completion con l’istruzione e restituisce il messaggio di conferma formattato dall’assistente.
- Consente un logging interno leggero senza richiedere un database backend dedicato.
suggest_next_meal(): raccomanda il pasto successivo in base alle calorie assunte e al profilo dietetico.- Il modello è invocato con
temperature=0.7per incoraggiare suggerimenti più creativi. - La risposta viene ripulita e restituita come idea per il prossimo pasto.
Insieme, queste funzioni consentono stima calorica, conferma di registrazione e raccomandazioni salutari senza bisogno di API esterne. Nel prossimo step, visualizzeremo i suggerimenti con il connettore di generazione immagini di Mistral.
Step 2.4: Generare visual con il connettore di generazione immagini
Aggiungiamo ora uno strato visivo al nostro assistente. In questo step useremo il connettore integrato image_generation di Mistral per generare un’immagine appetitosa del prossimo pasto suggerito.
#Image generation tool
import os
import re
from mistralai import Mistral, UserMessage, SystemMessage
from mistralai.models import ToolFileChunk
from tools.configs import client
from datetime import datetime
def generate_food_image(meal_description):
try:
print(f"Starting image generation for: {meal_description}")
# Image generation agent
image_agent = client.beta.agents.create(
model="mistral-medium-latest",
name="Food Image Generation Agent",
description="Agent used to generate food images.",
instructions="Use the image generation tool to create appetizing food images. Generate realistic and appetizing images of meals.",
tools=[{"type": "image_generation"}],
completion_args={
"temperature": 0.3,
"top_p": 0.95,
}
)
print("Created image generation agent")
response = client.beta.conversations.start(
agent_id=image_agent.id,
inputs=f"Generate an appetizing image of: {meal_description}",
stream=False
)
print("Got response from image generation")
os.makedirs("generated_images", exist_ok=True)
# Process the response and save images
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
image_paths = []
if hasattr(response, 'outputs'):
print(f"Processing {len(response.outputs)} outputs")
for output in response.outputs:
if hasattr(output, 'content'):
print(f"Processing content of type: {type(output.content)}")
if isinstance(output.content, list):
for i, chunk in enumerate(output.content):
print(f"Processing chunk {i} of type: {type(chunk)}")
if isinstance(chunk, ToolFileChunk):
print(f"Found ToolFileChunk with file_id: {chunk.file_id}")
try:
# Download the image
file_bytes = client.files.download(file_id=chunk.file_id).read()
# Save the image
image_path = f"generated_images/meal_{timestamp}_{i}.png"
with open(image_path, "wb") as file:
file.write(file_bytes)
image_paths.append(image_path)
print(f"Successfully saved image to: {image_path}")
except Exception as e:
print(f"Error processing image chunk: {str(e)}")
else:
print(f"Content is not a list: {output.content}")
if image_paths:
print(f"Successfully generated {len(image_paths)} images")
return image_paths[0] # Return the first image path
else:
print("No images were generated")
return "No image was generated”
except Exception as e:
print(f"Error during image generation: {str(e)}")
if hasattr(e, '__dict__'):
print(f"Error details: {e.__dict__}")
return f"Error generating image: {str(e)}"
La funzione generate_food_image() genera una rappresentazione visiva di un pasto usando lo strumento integrato image_generation di Mistral. Ecco cosa fa ciascuna parte:
- Creazione dell’agente: un nuovo agente è istruito a creare visual di cibo realistici e appetitosi.
- Avvio conversazione: viene inviato un prompt chiedendo di generare un’immagine della
meal_descriptionfornita dal next meal agent. - Gestione della risposta: la funzione verifica se la risposta contiene blocchi immagine. In caso affermativo, scarica ciascuna immagine tramite il metodo
files.download()del client Mistral. Le immagini sono salvate localmente nella cartellagenerated_images/con nomi file timestampati. - Output: restituisce il percorso della prima immagine salvata con successo, o un messaggio di errore di fallback se la generazione fallisce.
Questo strumento aggiunge uno strato visivo al nostro coach nutrizionale, rendendo i suggerimenti più coinvolgenti e realistici.
Step 3: Pipeline completa del nutrizionista
Ora che abbiamo costruito gli strumenti e le capacità degli agenti, è il momento di unirli in un’unica pipeline. Questo step mette insieme tutto in un assistente funzionante che gestisce:
- Ricerca calorie (via web o stima)
- Logging (utente, pasto, calorie, timestamp)
- Suggerimento di un pasto successivo
- Visualizzazione del pasto con un’immagine
Tutti questi passaggi sono gestiti chiamando nell’ordine giusto ciascuna funzione dei file precedenti. Il codice per questa pipeline si trova fuori dalla cartella tools, nel file agent.py.
# Pipeline logic file
from tools import estimate_calories, log_meal, suggest_next_meal, search_calories
from tools.image_gen import generate_food_image
from datetime import datetime
import time
def run_nutritionist_pipeline(username, meal_desc, dietary_preference):
tools_used = set()
print(f"Searching for calories for: {meal_desc}")
calories_text = search_calories(meal_desc)
tools_used.add("Web Search")
# If web search fails, fall back to estimation
if calories_text == 0:
print("Web search failed, falling back to estimation...")
time.sleep(1) # Add delay to avoid rate limits
calories_text = estimate_calories(meal_desc)
tools_used.add("Calorie Estimation")
estimated_calories = calories_text
print(f"Estimated calories: {estimated_calories}")
print(f"Logging meal for {username}...")
time.sleep(1) # Add delay to avoid rate limits
log_response = log_meal(username, meal_desc, estimated_calories)
tools_used.add("Meal Logging")
print("Generating next meal suggestion...")
time.sleep(1)
suggestion = suggest_next_meal(estimated_calories, dietary_preference)
tools_used.add("Next Meal Suggestion")
print("Generating image description for suggested meal...")
time.sleep(1)
meal_image = generate_food_image(suggestion)
tools_used.add("Image Description Generation")
return {
"logged": log_response,
"next_meal_suggestion": suggestion,
"meal_image": meal_image,
"tools_used": sorted(list(tools_used))
}
Il codice sopra coordina l’intero workflow dell’assistente nutrizionale concatenando più strumenti di agente in un’unica pipeline. Ecco una scomposizione più dettagliata:
- La funzione
run_nutritionist_pipeline()accettausername,meal_descedietary_preferencecome input per guidare il processo di raccomandazione. - Per prima cosa tenta di determinare le calorie del pasto tramite la funzione
search_calories()alimentata dal connettore di ricerca web di Mistral. Se fallisce, ricorre a una stima tramite un modello leggero conestimate_calories(). - Il valore calorico ottenuto viene poi registrato usando
log_meal(), che etichetta la voce con un timestamp e la associa all’utente. - In base alle calorie consumate e alla preferenza dietetica, la funzione
suggest_next_meal()suggerisce un pasto successivo con ragionamento basato su prompt. - Infine, la funzione
generate_food_image()usa il connettore di generazione immagini di Mistral per produrre una rappresentazione visiva del piatto consigliato. - Durante il processo,
time.sleep(1)introduce brevi pause tra le richieste per evitare di attivare i rate limit durante le chiamate API. - La funzione restituisce un dizionario contenente la conferma del logging del pasto, il testo del suggerimento per il prossimo pasto, il percorso dell’immagine generata e l’elenco degli strumenti usati in questa interazione.
Questa pipeline combina funzionalità come ricerca, stima, logging, suggerimento e visualizzazione in un’esperienza nutrizionale basata sull’AI.
Step 4: Creare un’interfaccia user-friendly con Gradio
Ora che la logica backend è completa, impacchettiamola in un frontend pulito e facile da usare con Gradio.
# Main files
import gradio as gr
from agent import run_nutritionist_pipeline
import os
import re
def process_meal(username, meal_desc, dietary_preference):
# Run the pipeline
result = run_nutritionist_pipeline(username, meal_desc, dietary_preference)
# Extract calories from the logged meal response
calories = "Not available"
if result['logged']:
calorie_match = re.search(r'(\d+)\s*calories', result['logged'], re.IGNORECASE)
if calorie_match:
calories = calorie_match.group(1)
else:
paren_match = re.search(r'\((\d+)\)', result['logged'])
if paren_match:
calories = paren_match.group(1)
else:
number_match = re.search(r'\b(\d+)\b', result['logged'])
if number_match:
calories = number_match.group(1)
# Map tool names to Mistral connectors
connector_map = {
"Web Search": "Web Search",
"Image Description Generation": "Image Generation",
"Meal Logging": "Chat Completion",
"Next Meal Suggestion": "Chat Completion"
}
connectors_used = set()
for tool in result['tools_used']:
if tool in connector_map:
connectors_used.add(connector_map[tool])
output = f"""
# Meal Analysis Results
## Meal Details
- **Meal Description:** {meal_desc}
- **Estimated Calories:** {calories}
## Next Meal Suggestion
{result['next_meal_suggestion']}
## Tools Used
{', '.join(result['tools_used'])}
## Mistral Connectors Used
{', '.join(sorted(connectors_used))}
""
# Get the image path and check if it is valid
image_path = result['meal_image']
if os.path.exists(image_path) and image_path.endswith('.png'):
return output, image_path
else:
return output, None
# Create the Gradio interface
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🍽️ Nutritionist Assistant")
with gr.Row():
with gr.Column():
username = gr.Textbox(label="Username", placeholder="Enter your name")
meal_desc = gr.Textbox(label="Meal Description", placeholder="Describe your meal (e.g., 'Chicken salad with olive oil dressing')")
dietary_preference = gr.Dropdown(
choices=["vegetarian", "vegan", "Non-vegetarian", "gluten-free"],
label="Dietary Preference",
value="omnivore"
)
submit_btn = gr.Button("Process Meal", variant="primary")
with gr.Column():
output = gr.Markdown(label="Results")
image_output = gr.Image(label="Generated Meal Image", type="filepath")
submit_btn.click(
fn=process_meal,
inputs=[username, meal_desc, dietary_preference],
outputs=[output, image_output]
)
# Launch the app
if __name__ == "__main__":
demo.launch()
Nel codice sopra, configuriamo un’interfaccia Gradio completa per interagire con la pipeline del Nutritionist Agent. Ecco come funziona:
- Si parte importando la funzione
run_nutritionist_pipeline()daagent.py, che guida la logica principale degli agenti. - La funzione
process_meal()agisce da wrapper attorno alla pipeline, accettausername,meal_descedietary_preferencecome input utente e attiva la logica multi-agente definita in precedenza. - Dentro
process_meal(), il dizionario dei risultati viene analizzato per estrarre il riepilogo del pasto, le calorie, il suggerimento per il prossimo pasto e i connettori usati. - La funzione verifica anche che il percorso dell’immagine generata sia valido prima di restituirlo per la visualizzazione. Se l’immagine non viene trovata, viene restituito solo il risultato testuale.
- L’app Gradio è costruita con
gr.Blocks()e il layout include due colonne: una con i campi di input e il pulsante Process Meal, l’altra con l’area di output per i risultati dell’analisi del pasto e l’anteprima dell’immagine del prossimo pasto. - La callback
submit_btn.click()collega il pulsante del frontend alla funzioneprocess_meal(), passando gli input e ricevendo in output il markdown formattato e l’immagine. - Infine, l’app viene avviata con
demo.launch()se lo script è eseguito come modulo principale. Puoi impostaredebug = Trueper abilitare la modalità di debug.
Per eseguire questa demo, apri un terminale nella directory di root e digita il seguente comando:
python app.py
La struttura complessiva del progetto sarà simile a questa:
Mistral_Agent_API/
├── generated_images/ # Stores generated meal images
├── tools/
│ ├── configs.py # API setup, tool schema, environment config
│ ├── image_gen.py # Generates meal image
│ ├── next.py # Calorie estimator, logger, and next meal
│ └── web_search.py # Mistral web_search connector to find calorie
├── agent.py # Main pipeline connecting all tools
├── app.py # Gradio UI
├── requirements.txt # Project dependencies
├── .env # Environment variables
Puoi trovare il codice completo di questo progetto in questa repo GitHub.
Conclusione
In questo tutorial abbiamo costruito un Nutrition Coach AI completo usando la Agents API di Mistral. Lungo il percorso, abbiamo esplorato:
- In che modo gli agenti Mistral differiscono dai modelli LLM grezzi
- Il ruolo dei connettori come
web_searcheimage_generation - L’orchestrazione tra più agenti in un’unica pipeline
- La creazione di un frontend user-friendly con Gradio
Questo progetto mostra la potenza dei workflow agentici, in cui gli LLM non sono solo risponditori passivi, ma entità interattive che ragionano, agiscono e coordinano compiti. Dal registrare i pasti al suggerire alternative salutari e persino generare immagini, abbiamo visto come combinare strumenti semplici in esperienze AI potenti.
Per approfondire l’uso degli agenti AI, ti consiglio questi tutorial pratici:
Sono una Google Developers Expert in ML (Gen AI), una Kaggle 3x Expert e una Women Techmakers Ambassador con oltre 3 anni di esperienza nel tech. Ho co-fondato una startup health-tech nel 2020 e sto conseguendo un master in informatica al Georgia Tech, con specializzazione in machine learning.





