Ga naar hoofdinhoud

Mistral Agents API: een gids met demoproject

Leer hoe je AI-agents bouwt met Mistrals Agents API, en ontdek kernconcepten zoals toolgebruik, connectors, handoffs en meer.
· 12 min lezen

Verken met AI

Mistral heeft de Agents API uitgebracht, een framework dat het ontwikkelen van intelligente, autonome AI-agents vergemakkelijkt die complexe taken in meerdere stappen kunnen uitvoeren. Het gaat verder dan traditionele taalmodellen door toolgebruik, persistente geheugenfuncties en orkestratiemogelijkheden te integreren.

In deze tutorial laat ik je zien hoe je de Mistral Agents API gebruikt om slimme assistenten te bouwen die kunnen:

  • Tools gebruiken zoals webzoekopdrachten, code-uitvoering en afbeeldingsgeneratie
  • Geheugen behouden over lange gesprekken om context te bewaren
  • Taken delegeren tussen meerdere agents

Je leert de kernconcepten achter Mistrals agentische framework, verkent de ingebouwde connectors en orkestratiefuncties, en bouwt een werkende multi-agentassistent.

We houden onze lezers op de hoogte van het laatste AI-nieuws met The Median, onze gratis vrijdagse nieuwsbrief die de belangrijkste verhalen van de week uiteenzet. Abonneer je en blijf scherp in slechts een paar minuten per week:

Wat is Mistrals Agents API?

De Mistral Agents API is een framework waarmee large language models acties in meerdere stappen kunnen uitvoeren, externe tools kunnen gebruiken en geheugen kunnen behouden over interacties heen. In tegenstelling tot eenvoudige chat-API’s stelt het AI-agents in staat om:

  • Toegang te krijgen tot het web, code uit te voeren, afbeeldingen te genereren of documenten op te halen
  • Te coördineren met andere agents via orkestratie
  • Persistente gesprekken met langetermijngeheugen te onderhouden

Momenteel worden alleen mistral-medium-latest (ook bekend als mistral-medium-2505) en mistral-large-latest ondersteund, maar binnenkort kunnen nieuwe modellen worden toegevoegd.

Uitleg van kernconcepten

Voordat we aan de slag gaan, is het handig om de kernconcepten van de Agents API te verduidelijken.

mistral agents api diagram

Bron: Mistral AI

Agents

Agents in Mistral zijn modelgestuurde persona’s met vooraf gedefinieerde instructies, toegang tot tools en gespreksstatus:

  • Instructies sturen het gedrag van de agent (bijv. “Je bent een voedingscoach die maaltijden logt”).
  • Tools zoals web_search of image_generation laten agents acties in de echte wereld ondernemen.
  • Geheugen stelt agents in staat eerdere berichten en tooluitvoer over beurten heen bij te houden, wat contextueel redeneren ondersteunt.

Deze abstractie verandert een basaal chatmodel in een multifunctionele assistent die complexe workflows aankan.

Gesprekken 

Elke interactie tussen een gebruiker en een agent maakt deel uit van een gesprek, waarin het volgende wordt opgeslagen:

  • Eerdere berichten en assistentantwoorden
  • Toolaanroepen en resultaten
  • Streamingmetadata voor zichtbaarheid op tokenniveau (optioneel)

Dankzij deze persistente gesprekken kunnen agents meerstaps taken uitvoeren, zoals plannen, herzien of leren van eerdere input.

Connectors en ondersteuning voor aangepaste tools

Mistral maakt eenvoudige toolintegratie mogelijk via:

  • Connectors: Dit zijn vooraf geïntegreerde tools zoals web_search, code_execution, image_generation, document_library die out-of-the-box werken.
  • MCP-tools: Hiermee kunnen ontwikkelaars eigen API’s hosten die als tools binnen de agentworkflow kunnen worden aangeroepen.

Zie connectors als ingebouwde apps, en MCP-tools als plug-ins die je zelf schrijft. Samen geven ze agents toegang tot zowel ingebouwde mogelijkheden als door ontwikkelaars gedefinieerde endpoints voor gepersonaliseerde logica.

mistral agents api mcp diagram

Bron: Mistral AI

Entries en handoffs

Mistral volgt alle acties in een gesprek als gestructureerde “Entries”, waardoor traceerbaarheid en controle over berichtuitwisselingen en toolexecuties mogelijk zijn.

Agent-handoffs zijn momenten waarop de ene agent de controle overdraagt aan een andere om workflows te modulariseren.

mistral agent handoffs

Bron: Mistral AI

Deze orkestratiearchitectuur maakt het eenvoudig om complexe multi-agentsystemen samen te stellen en te beheren zonder transparantie of controle te verliezen.

Mistral API instellen

Laten we beginnen met het instellen van Mistral. We starten met het aanmaken van een API-sleutel voor het project. Volg deze stappen:

  1. Maak een Mistral-account aan of log in via console.mistral.ai.

Mistral dashboard

  1. Ga vervolgens naar Workspace Settings (pijltje naast je naam—linksboven) en klik op Billing om je betaalgegevens toe te voegen en betalingen op je account te activeren.

Mistral billing

  1. Klik op Add credits en vul je factuurgegevens in het formulier in. Vul daarna het aantal credits in dat je wilt. Let op: je moet minimaal 10 credits toevoegen.

Mistral credits

  1. Klik vervolgens in het linkertabblad op API keys en maak een nieuwe API-sleutel aan door op Create new key te klikken. Kopieer de API-sleutel, bewaar deze veilig en deel hem met niemand.

Je hebt nu een geldige API-sleutel om met Mistral-modellen te communiceren en intelligente agents te bouwen.

Projectoverzicht: Voedingscoach met Mistral Agents

In dit project bouwen we een AI-gestuurde Voedingscoach met Mistrals Agents API. Zo ziet de gebruikersflow eruit:

  1. De gebruiker voert een maaltijd in die hij/zij net heeft gegeten (bijv. "kipsalade met olijfoliedressing").
  2. Een webzoekagent gebruikt de ingebouwde connector om de calorieën voor de maaltijd te schatten.
  3. Een logger-agent registreert deze invoer onder de naam van de gebruiker met een tijdstempel.
  4. Tot slot stelt een afbeeldingsgeneratieagent een gezonde vervolgemaaltijd voor en geeft zowel een afbeelding als een beschrijving en recept terug.

Om een webinterface te bieden waar gebruikers met de voedingscoach kunnen communiceren, gebruiken we Gradio.

Stap 1: Vereisten

Zorg ervoor dat je het volgende hebt geïnstalleerd voordat je begint:

  • Python 3.8+
  • Alle vereiste pakketten die in requirements.txt staan
python-dotenv==1.1.0
mistralai==0.0.7
typing-extensions==4.12.2
requests==2.31.0
gradio==4.34.0

Maak ook een .env-bestand aan met je Mistral API-sleutel. Deze aanpak houdt je API-sleutels veilig en maakt het mogelijk dat verschillende teamleden of omgevingen andere inloggegevens gebruiken zonder de broncode te wijzigen.

MISTRAL_API_KEY=YOUR_API_KEY

Let op: het is aan te raden om deze dependencies in een geïsoleerde omgeving zoals conda, venv of uv te installeren om versieconflicten met andere Python-projecten te voorkomen.

Hier zijn de commando’s om verschillende omgevingen op te zetten:

Met venv

python -m venv mistral_env
source mistral_env/bin/activate   # On Windows: mistral_env\Scripts\activate

Met Conda

conda create -n mistral_env python=3.10
conda activate mistral_env

Met uv

Als je uv nog niet hebt:

pip install uv

Dan:

uv venv mistral_env
source mistral_env/bin/activate

Om alle bovengenoemde dependencies te installeren, voer je in je terminal het volgende uit:

pip install -r requirements.txt

Let op: als je fouten tegenkomt met betrekking tot mistralai bij het gebruiken van een agent of connector, voer dan de volgende code uit:

pip install –upgrade mistralai

Dit werkt de mistralai-bibliotheek bij naar de nieuwste versie.

Stap 2: Mistral-tools instellen

In deze sectie bereiden we onze tools en clientsetup voor interactie met de Mistral Agents API voor. We definiëren toolschemas, initialiseren de client en verifiëren de authenticatie. Deze tools verwijzen we later als we specifieke agents instellen, zoals calorie-schatters of afbeeldingsgeneratoren.

Stap 2.1: Toolregister en initialisatie

Eerst definiëren we onze toolschemas, modelkeuze en clientinstantie. Daarna bouwen we hulpmethoden zoals create_chat_completion() en check_client(). De volgende code komt in het bestand configs.py binnen de map 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"]
        }
    }
}

We beginnen met het importeren van dotenv om gevoelige variabelen, zoals de Mistral API-sleutel, uit een lokaal .env-bestand in de Python-omgeving te laden. Dit houdt inloggegevens veilig en buiten de broncode. Vervolgens selecteren we het standaardmodel mistral-large-latest en maken we een Mistral-client aan met de API-sleutel.

Daarna definiëren we interne toolspecificaties (schemas) met JSON Schema. Ze helpen bij het volgende:

  • MCP-toolgedrag simuleren (ook al zijn ze niet geregistreerd via de McpTool-bibliotheek)
  • Verwachte input beschrijven zoals "username", "meal" en "calories"
  • Consistente inputopmaak tussen modules waarborgen

Laten we nu onze hulpmethoden toevoegen die chatcompletions maken, tools en agents registreren en de client initialiseren.

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()

De functie create_chat_completion() wikkelt een aanroep naar de methode client.chat.complete() uit de Mistral-client-SDK in om berichten naar het model te sturen.

  • Hij formatteert ruwe dict-achtige berichten naar UserMessage- en SystemMessage-objecten die de Mistral SDK vereist.
  • Hij is ook handig voor gestandaardiseerde completions in de hele app.

De functies register_tools() en register_agents() helpen tijdens lokale ontwikkeling door te loggen welke tools en agents actief zijn in het systeem. Ondertussen zorgen check_client() en is_client_initialized() ervoor dat de Mistral-client correct is geïnitialiseerd en dat de API-sleutel beschikbaar is, waardoor runtimefouten tijdens agentuitvoering worden voorkomen.

Stap 2.2: Calorieën schatten met de webzoekagent

Nu we de basistools en client hebben geïnitialiseerd, bouwen we een speciale Nutrition Web Search Agent. Deze agent gebruikt Mistrals web_search-connector om in realtime calorie-schattingen voor maaltijden op te zoeken. Deze code staat in het bestand web_search.py binnen de map 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

In de bovenstaande code gebruikt de functie search_calories() de ingebouwde connector-tool voor webzoekopdrachten uit de Mistral Agents API, waardoor agents live webqueries kunnen uitvoeren zoals een calorie-schatting, en zo de beperkingen van statische modeltraining omzeilen. Zo werkt het:

  1. Agentcreatie: Er wordt eerst een “Nutrition Search Agent” aangemaakt met het model mistral-medium-latest, uitgerust met de tool web_search en geïnstrueerd om alleen calorieën terug te geven.
  2. Uitvoering van de query: Vervolgens wordt met de agent een gesprek gestart waarin wordt gevraagd naar het totale aantal calorieën in de opgegeven maaltijdomschrijving.
  3. Response-parsing: De reactie van de agent wordt met reguliere expressies geparsed om de eerste numerieke waarde te extraheren (dit zou de calorieëntelling moeten zijn).
  4. Fallbacks: Als er geen geldig getal wordt gevonden of er een fout optreedt, logt de functie het probleem en geeft als fallback nul terug.

Zonder web_search kunnen de meeste modellen geen vragen beantwoorden over recente gebeurtenissen of domeinspecifieke maaltijden die niet in hun trainingsdata voorkomen. Met web_search kunnen we in realtime voedingsinfo, restaurantmenu’s of nieuwsartikelen opvragen.

Er zijn twee varianten van webzoekopdracht:

  • web_search: Een lichte, algemene zoekengine-connector (gebruikt in ons project).
  • web_search_premium: Een verbeterde versie met verificatie van nieuwsbronnen en bredere contextverzameling.

Vervolgens bekijken we een fallback voor het schatten van calorieën met alleen promptlogica.

Stap 2.3: Schatting, logging en maaltijdsuggestie

In deze sectie implementeren we drie essentiële functies die dienen als fallbacks of verbeteringen. De volgende code staat in het bestand next.py in de map 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."

Dit script definieert de kernfuncties aan de achterkant die onze voedingsworkflow aandrijven (van calorie-schatting tot vervolgmaaltijdplanning). Deze functies gebruiken lichte Mistral-modellen en standaard chatcompletions, zonder dat er agents of connectors nodig zijn wanneer webzoekopdrachten niet beschikbaar zijn of om rate limits te vermijden. Dit doet elke functie:

  1. estimate_calories(): Deze functie wordt gebruikt als fallback als de web_search-connector faalt of niet beschikbaar is.
    1. Hij stuurt een systeembericht met de rol van de assistent als voedingsexpert, samen met de gebruikersprompt met de maaltijd die de gebruiker wil loggen.
    2. Het model wordt gebruikt met een lage temperature=0.1 voor deterministische output. Dit betekent dat het model consistente, herhaalbare antwoorden geeft voor dezelfde input—handig voor taken zoals calorie-schatting en logging, waar stabiele en feitelijke output belangrijker is dan creativiteit.
    3. Hij haalt het eerste getal (met regex) uit de modelrespons.
  2. log_meal(): Deze functie logt de maaltijd van een gebruiker, inclusief een tijdstempel.
    1. Hij gebruikt een chatcompletion met de instructie en geeft het geformatteerde bevestigingsbericht van de assistent terug.
    2. Dit maakt lichte interne logging mogelijk zonder een aparte back-enddatabase.
  3. suggest_next_meal(): Deze functie raadt de volgende maaltijd van de gebruiker aan op basis van eerder geconsumeerde calorieën en het dieetprofiel.
    1. Het model wordt aangeroepen met temperature=0.7 om creatievere suggesties te stimuleren.
    2. De respons wordt opgeschoond en teruggegeven als idee voor de volgende maaltijd.

Samen maken deze functies calorie-schatting, logbevestiging en gezonde aanbevelingen mogelijk zonder externe API’s. In de volgende stap visualiseren we voedselsuggesties met Mistrals connector voor afbeeldingsgeneratie.

Stap 2.4: Visuals genereren met de connector voor afbeeldingsgeneratie

Laten we nu een visuele laag toevoegen aan onze assistent. In deze stap gebruiken we Mistrals ingebouwde connector image_generation om een smakelijke afbeelding van de volgende voorgestelde maaltijd te genereren.

#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)}" 

De functie generate_food_image() genereert een visuele weergave van een maaltijd met behulp van Mistrals ingebouwde tool image_generation. Dit doet elk onderdeel:

  • Agentcreatie: Er wordt een nieuwe agent geïnstrueerd om realistische en smakelijke voedselvisuals te maken.
  • Gesprek starten: Er wordt een prompt gestuurd met het verzoek een afbeelding te genereren van de opgegeven meal_description die door de volgende-maaltijd-agent is gegenereerd.
  • Afhandeling van de respons: De functie controleert of de respons beeldchunks bevat. Zo ja, dan downloadt hij elke afbeelding via de methode files.download() van de Mistral-client. De beelden worden lokaal opgeslagen in de map generated_images/ met bestandsnamen met tijdstempel.
  • Output: Hij retourneert het pad naar de eerste succesvol opgeslagen afbeelding, of een fallbackfoutmelding als genereren mislukt.

Deze tool voegt een visuele laag toe aan onze voedingscoach, waardoor maaltijdsuggesties aantrekkelijker en realistischer worden.

Stap 3: Volledige voedingscoach-pijplijn

Nu we de individuele tools en agentmogelijkheden hebben gebouwd, is het tijd om ze samen te voegen in één pijplijn. Deze stap lijmt alles aan elkaar tot een werkende assistent die het volgende afhandelt:

  • Caloriezoekopdracht (via web of schatting)
  • Logging (gebruiker, maaltijd, calorieën, tijdstempel)
  • Een vervolgemaaltijd suggereren
  • De maaltijd visualiseren met een afbeelding

Al deze stappen worden afgehandeld door in de juiste volgorde elke functie uit onze vorige bestanden aan te roepen. De code voor deze pijplijn staat buiten de map tools in het bestand 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))
    }

De bovenstaande code coördineert de volledige workflow van de voedingsassistent door meerdere agenttools in één pijplijn te koppelen. Laten we de code hierboven in meer detail doornemen:

  • De functie run_nutritionist_pipeline() accepteert username, meal_desc en dietary_preference als input om het aanbevelingsproces aan te sturen.
  • Eerst probeert hij het caloriegehalte van de maaltijd te bepalen met de functie search_calories() die wordt aangedreven door Mistrals webzoekconnector. Als dit faalt, wordt teruggevallen op een schatting met een lichtgewicht model via estimate_calories().
  • De verkregen calorie waarde wordt vervolgens gelogd met de functie log_meal(), die de invoer van een tijdstempel voorziet en aan de gebruiker koppelt.
  • Op basis van de geconsumeerde calorieën en dieetvoorkeur stelt de functie suggest_next_meal() een vervolgemaaltijd voor met prompt-gebaseerd redeneren.
  • Tot slot gebruikt de functie generate_food_image() Mistrals connector voor afbeeldingsgeneratie om een visuele weergave van het aanbevolen gerecht te produceren.
  • Gedurende het proces wordt time.sleep(1) gebruikt om korte pauzes tussen verzoeken in te lassen en zo rate limits tijdens API-calls te vermijden.
  • De functie retourneert een dictionary met de logbevestiging van de maaltijd, de tekst van de volgende maaltijdsuggestie, het pad naar de gegenereerde afbeelding en een lijst met tools die tijdens deze interactie zijn gebruikt.

Deze pijplijn combineert meerdere mogelijkheden zoals zoeken, schatten, loggen, suggereren en visualiseren tot een AI-gestuurde voedingservaring.

Stap 4: Een gebruiksvriendelijke interface maken met Gradio

Nu de backendlogica klaar is, wikkelen we alles in een strakke, gebruiksvriendelijke frontend met 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() 

In de bovenstaande code richten we een complete Gradio-UI in om met de Nutritionist Agent-pijplijn te werken. Zo werkt het:

  • We beginnen met het importeren van de functie run_nutritionist_pipeline() uit agent.py, die de kernlogica van de agent aanstuurt.
  • Vervolgens fungeert de functie process_meal() als wrapper rond de agentpijplijn. Hij accepteert username, meal_desc en dietary_preference als gebruikersinput en triggert de eerder gedefinieerde multi-agentlogica.
  • Binnen process_meal() wordt de result-dictionary geparsed om de maaltijdsamenvatting, calorieën, voorgestelde volgende maaltijd en gebruikte connectors te extraheren.
  • De functie controleert ook of het pad naar de gegenereerde afbeelding geldig is voordat deze wordt getoond. Als de afbeelding niet wordt gevonden, wordt alleen het tekstuele resultaat teruggegeven.
  • De Gradio-app is opgebouwd met gr.Blocks() en de lay-out bevat twee zijden: een met invoervelden en een Process Meal-knop, en een andere met een uitvoergebied voor resultaten van de maaltijanalyse en een afbeeldingsvoorvertoning van de volgende maaltijd.
  • De callback submit_btn.click() koppelt de front-endknop aan de functie process_meal(), waarbij de inputs worden doorgegeven en geformatteerde markdown en afbeelding als output worden ontvangen.
  • Tot slot wordt de app gestart via demo.launch() als het script als hoofdmodule wordt uitgevoerd. Je kunt debug = True instellen om de debugmodus van de app in te schakelen.

Om deze demo uit te voeren, open je een terminal in je hoofdmap en typ je het volgende commando:

python app.py

De algehele structuur van dit project ziet er als volgt uit:

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 

Je vindt de volledige code voor dit project in deze GitHub-repo.

Nutritionist Assistant with mistral agents api

Nutritionist Assistant with mistral agents api

Nutritionist Assistant with mistral agents api

Conclusie

In deze tutorial hebben we een volledig functionerende AI-voedingscoach gebouwd met de Mistral Agents API. Onderweg hebben we het volgende verkend:

  • Hoe Mistral-agents verschillen van ruwe LLM-modellen
  • De rol van connectors zoals web_search en image_generation
  • Orkestratie over meerdere agents in één pijplijn
  • Een gebruiksvriendelijke frontend bouwen met Gradio

Dit project laat de kracht zien van agentische workflows waarin LLM’s niet alleen passieve beantwoorders zijn, maar interactieve entiteiten die redeneren, actie ondernemen en taken coördineren. Van maaltijden loggen tot gezonde alternatieven suggereren en zelfs afbeeldingen genereren: we hebben laten zien hoe je eenvoudige tools combineert tot krachtige AI-ervaringen.

Wil je meer leren over het gebruik van AI-agents? Dan raad ik deze praktische tutorials aan:

Aashi Dutt

Auteur

Aashi Dutt

Ik ben een Google Developers Expert in ML (Gen AI), een Kaggle 3x Expert en een Women Techmakers Ambassador met meer dan 3 jaar ervaring in tech. In 2020 heb ik een healthtech-startup mee opgericht en ik volg een master computer science aan Georgia Tech, met als specialisatie machine learning.

Onderwerpen

Gerelateerd