Programa
A Mistral lançou a API de agentes, uma estrutura que facilita o desenvolvimento de agentes de IA inteligentes e autônomos, capazes de executar tarefas complexas e de várias etapas. Ele vai além dos modelos de linguagem tradicionais, integrando o uso de ferramentas, memória persistente e recursos de orquestração.
Neste tutorial, mostrarei a você como usar a API Mistral Agents para criar assistentes inteligentes capazes de:
- Usar ferramentas como pesquisa na Web, execução de código e geração de imagens
- Retenção de memória em conversas longas para preservar o contexto
- Delegar tarefas a vários agentes
Você aprenderá os principais conceitos por trás da estrutura agêntica da Mistral, explorará os conectores integrados e os recursos de orquestração e criará um assistente multiagente funcional.
Mantemos nossos leitores atualizados sobre as últimas novidades em IA enviando o The Median, nosso boletim informativo gratuito de sexta-feira que detalha as principais histórias da semana. Inscreva-se e fique atento em apenas alguns minutos por semana:
O que é a API de agentes da Mistral?
A API Mistral Agents é uma estrutura que permite que grandes modelos de linguagem executem ações em várias etapas, usem ferramentas externas e mantenham a memória entre as interações. Diferentemente das APIs de bate-papo simples, ela permite que os agentes de IA:
- Acessar a Web, executar código, gerar imagens ou recuperar documentos
- Coordenar com outros agentes por meio de orquestração
- Manter conversas persistentes com a memória de longo prazo
Atualmente, apenas mistral-medium-latest
(também conhecido como mistral-medium-2505
) e mistral-large-latest
são compatíveis, mas em breve novos modelos poderão ser compatíveis.
Explicação dos principais conceitos
Antes de entrarmos na parte prática, acho que é útil esclarecer os principais conceitos da API de agentes.
Fonte: Mistral AI
Agentes
Os agentes do Mistral são personas baseadas em modelos, aprimoradas com instruções predefinidas, acesso a ferramentas e estado da conversa:
- As instruções orientam o comportamento do agente (por exemplo, "Você é um treinador de nutrição de registro de refeições").
- Ferramentas como
web_search
ouimage_generation
permitem que os agentes realizem ações no mundo real. - A memória permite que os agentes rastreiem mensagens anteriores e resultados de ferramentas em turnos, dando suporte ao raciocínio contextual.
Essa abstração transforma um modelo básico de bate-papo em um assistente multifuncional que pode participar de fluxos de trabalho complexos.
Conversas
Cada interação entre um usuário e um agente faz parte de uma conversa, que é armazenada:
- Mensagens anteriores e respostas de assistentes
- Chamadas de ferramentas e resultados
- Metadados de streaming para visibilidade em nível de token (opcional)
Essas conversas persistentes permitem que os agentes realizem tarefas com várias voltas, como planejamento, revisão ou aprendizado com entradas anteriores.
Conectores e suporte a ferramentas personalizadas
O Mistral permite a fácil integração de ferramentas por meio de:
- Conectores: Essas são ferramentas pré-integradas, como
web_search
,code_execution
,image_generation
,document_library
, que funcionam imediatamente. - Ferramentas MCP: Eles permitem APIs personalizadas hospedadas por desenvolvedores que podem ser invocadas como ferramentas dentro do fluxo de trabalho do agente.
Pense nos conectores como aplicativos integrados e nas ferramentas MCP como plug-ins que você escreve. Juntos, eles permitem que os agentes acessem recursos incorporados e pontos de extremidade definidos pelo desenvolvedor para lógica personalizada.
Fonte: Mistral AI
Entradas e transferências
O Mistral programa todas as ações em uma conversa como "Entradas" estruturadas, permitindo a rastreabilidade e o controle sobre trocas de mensagens e execuções de ferramentas.
As transferências de agentes são aquelas em que um agente delega o controle a outro para modular os fluxos de trabalho.
Fonte: Mistral AI
Essa arquitetura de orquestração facilita a composição e o gerenciamento de sistemas multiagentes complexos sem perder a transparência ou o controle.
Configuração da API do Mistral
Vamos começar a configurar o Mistral. Começaremos criando uma chave de API para o projeto. Aqui estão as etapas que você deve seguir:
- Para começar, crie uma conta Mistral ou faça login em console.mistral.ai.
- Em seguida, navegue até Workspace Settings (seta suspensa perto do seu nome - canto superior esquerdo) e clique em Billing (Faturamento) para adicionar suas informações de pagamento e ativar os pagamentos em sua conta.
- Clique em Add credits (Adicionar créditos) e preencha suas informações de cobrança no formulário. Em seguida, preencha o número de créditos que você deseja. Observação: Você precisa adicionar pelo menos 10 créditos.
- Em seguida, na guia do lado esquerdo, clique em Chaves de API e crie uma nova chave de API clicando em Criar nova chave. Certifique-se de copiar a chave da API, salvá-la com segurança e não compartilhá-la com ninguém.
Agora você tem uma chave de API válida para interagir com os modelos Mistral e criar agentes inteligentes.
Visão geral do projeto: Treinador de nutrição com a Mistral Agents
Neste projeto, criaremos um treinador nutricional alimentado por IA usando a API de agentes da Mistral. Aqui está o fluxo do usuário:
- O usuário envia uma refeição que acabou de comer (por exemplo, "salada de frango com molho de azeite de oliva").
- Um agente de pesquisa na Web usa o conector integrado para estimar as calorias da refeição.
- Um agente de logger registra essa entrada com o nome do usuário e o registro de data e hora.
- Por fim, um agente de geração de imagens sugere uma refeição saudável de acompanhamento, retornando uma imagem, uma descrição e uma receita.
Para fornecer uma interface da Web em que os usuários possam interagir com o nutricionista, usaremos o Gradio.
Etapa 1: Pré-requisitos
Antes de começarmos, verifique se você tem os seguintes itens instalados:
- Python 3.8+
- Todos os pacotes necessários listados em
requirements.txt
python-dotenv==1.1.0
mistralai==0.0.7
typing-extensions==4.12.2
requests==2.31.0
gradio==4.34.0
Além disso, configure um arquivo .env
que contenha sua chave de API Mistral. Essa abordagem mantém as chaves de API seguras e permite que diferentes membros da equipe ou ambientes de implementação usem credenciais diferentes sem modificar o código-fonte.
MISTRAL_API_KEY=YOUR_API_KEY
Observação: Recomenda-se que você instale essas dependências em um ambiente isolado, como conda, venv ou uv, para evitar conflitos de versão com outros projetos Python.
Aqui estão os comandos para você configurar diferentes ambientes:
Usando o venv
python -m venv mistral_env
source mistral_env/bin/activate # On Windows: mistral_env\Scripts\activate
Usando o Conda
conda create -n mistral_env python=3.10
conda activate mistral_env
Usando uv
Se você ainda não tiver uv:
pip install uv
Então:
uv venv mistral_env
source mistral_env/bin/activate
Para instalar todas as dependências mencionadas acima, execute o seguinte código em seu terminal:
pip install -r requirements.txt
Observação: Se você encontrar algum erro relacionado a mistralai
ao usar qualquer agente ou conector, execute o seguinte código:
pip install –upgrade mistralai
Isso atualizará a biblioteca mistralai
para sua versão mais recente.
Etapa 2: Configuração das ferramentas Mistral
Nesta seção, prepararemos nossas ferramentas e a configuração do cliente para a interação com a API do Mistral Agents. Definiremos os esquemas de ferramentas, inicializaremos o cliente e verificaremos a autenticação. Essas ferramentas serão consultadas posteriormente ao configurar agentes específicos, como estimadores de calorias ou geradores de imagens.
Etapa 2.1: Registro e inicialização da ferramenta
Primeiro, definimos os esquemas de nossas ferramentas, a seleção de modelos e a instanciação de clientes. Em seguida, criamos métodos auxiliares como create_chat_completion()
e check_client()
. O código a seguir vai para o arquivo configs.py
dentro da pasta 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"]
}
}
}
Começamos importando dotenv
para carregar variáveis sensíveis, como a chave da API da Mistral, de um arquivo local .env
para o ambiente do Python. Isso mantém as credenciais seguras e fora do código-fonte. Em seguida, selecionamos o modelo padrão mistral-large-latest
e instanciamos um cliente Mistral usando a chave da API.
Em seguida, definimos as especificações internas da ferramenta (esquemas) usando o formato de esquema JSON. Eles ajudam com o seguinte:
- Simular o comportamento da ferramenta MCP (embora não estejam registradas por meio da biblioteca McpTool)
- Descreva as entradas esperadas, como "nome de usuário", "refeição" e "calorias"
- Ajude a garantir uma formatação de entrada consistente em todos os módulos
Agora, vamos adicionar nossos métodos auxiliares que criam conclusões de bate-papo, registram ferramentas, agentes e inicializam o cliente.
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()
A função create_chat_completion()
envolve uma chamada ao método client.chat.complete()
, que faz parte do SDK do cliente Mistral, para enviar mensagens ao modelo.
- Ele reformata mensagens brutas no estilo dict em objetos
UserMessage
eSystemMessage
exigidos pelo Mistral SDK. - Ele também é útil para preenchimentos padronizados em todo o aplicativo.
As funções register_tools()
e register_agents()
ajudam durante o desenvolvimento local, registrando quais ferramentas e agentes estão ativos no sistema. Enquanto isso, as funções check_client()
e is_client_initialized()
garantem que o cliente Mistral tenha sido instanciado corretamente e que a chave da API esteja disponível, ajudando a evitar erros de tempo de execução durante a execução do agente.
Etapa 2.2: Estimativa de calorias com o agente de pesquisa na Web
Agora que inicializamos as ferramentas básicas e o cliente, vamos criar um agente dedicado do Nutrition Web Search. Esse agente usa o conector web_search
da Mistral para procurar estimativas de calorias para refeições em tempo real. Esse código está localizado no arquivo web_search.py
dentro da pasta 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
No código acima, a função search_calories()
usa a ferramenta de conector integrada para pesquisa na Web da API Mistral Agents, que permite que os agentes realizem consultas na Web ao vivo, como estimativa de calorias, superando as limitações do treinamento de modelo estático. Veja como isso funciona:
- Criação de agentes: Primeiro, ele cria um "Nutrition Search Agent" usando o modelo
mistral-medium-latest
, que é equipado com a ferramentaweb_search
e é instruído a retornar apenas calorias. - Execução da consulta: O agente é então usado para iniciar uma conversa em que ele é questionado sobre o total de calorias na descrição da refeição fornecida.
- Análise de respostas: A resposta do agente é analisada usando expressões regulares para extrair o primeiro valor numérico (que deve ser a contagem de calorias).
- Fallbacks: Se não for encontrado nenhum número válido ou se ocorrer um erro, a função registrará o problema e retornará zero como um retorno.
Sem o site web_search
, a maioria dos modelos não consegue responder a perguntas sobre eventos recentes ou refeições específicas do domínio não vistas nos dados de treinamento. Com ele, podemos consultar informações nutricionais, cardápios de restaurantes ou artigos de notícias em tempo real.
Há duas variantes de pesquisa na Web:
web_search
: Um conector de mecanismo de pesquisa leve e de uso geral (usado em nosso projeto).web_search_premium
: Uma versão aprimorada que inclui verificação do provedor de notícias e coleta de contexto mais ampla.
Em seguida, exploraremos a estimativa de calorias de fallback usando a lógica somente de prompt.
Etapa 2.3: Estimativa, registro e sugestão de refeições
Nesta seção, implementamos três funções essenciais que atuam como fallbacks ou aprimoramentos. O código a seguir fica dentro do arquivo next.py
na pasta 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."
Esse script define as principais funções de back-end que alimentam nosso fluxo de trabalho de nutrição (da estimativa de calorias ao planejamento de refeições de acompanhamento). Essas funções usam modelos Mistral leves e preenchimento de bate-papo padrão, sem exigir a criação de agentes ou conectores a serem usados quando a pesquisa na Web não estiver disponível ou para evitar erros de limite de taxa. Aqui está o que cada função faz:
estimate_calories()
: Essa função é usada como um fallback se o conectorweb_search
falhar ou não estiver disponível.- Ele envia uma mensagem do sistema contendo a função do assistente como especialista em nutrição, juntamente com o prompt do usuário, que inclui a refeição que o usuário deseja registrar.
- O modelo é usado com baixo
temperature=0.1
para resultados determinísticos. Isso significa que o modelo produzirá respostas consistentes e repetíveis para as mesmas tarefas de entrada, como estimativa de calorias e registro, em que resultados estáveis e factuais são preferíveis à variação criativa. - Ele analisa o primeiro número (usando regex) da resposta do modelo.
log_meal()
: Essa função registra a refeição de um usuário, incluindo um registro de data e hora.- Ele usa uma conclusão de bate-papo com a instrução e retorna a mensagem de confirmação formatada do assistente.
- Isso permite um registro interno leve sem a necessidade de um banco de dados backend dedicado.
suggest_next_meal()
: Essa função recomenda a próxima refeição do usuário com base na ingestão anterior de calorias e no seu perfil alimentar.- O modelo é invocado com
temperature=0.7
para incentivar sugestões mais criativas. - A resposta é então removida e retornada como a próxima ideia de refeição.
Juntas, essas funções permitem a estimativa de calorias, a confirmação de registros e recomendações saudáveis sem a necessidade de APIs externas. Na próxima etapa, visualizaremos as sugestões de alimentos com o conector de geração de imagens da Mistral.
Etapa 2.4: Geração de imagens com o conector de geração de imagens
Agora vamos adicionar uma camada visual ao nosso assistente. Nesta etapa, usaremos o conector image_generation
incorporado do Mistral para gerar uma imagem apetitosa da próxima refeição sugerida.
#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)}"
A função generate_food_image()
gera uma representação visual de uma refeição usando a ferramenta image_generation
integrada do Mistral. Veja a seguir o que cada parte faz:
- Criação de agentes: Um novo agente é instruído a criar visuais realistas e apetitosos de alimentos.
- Início da conversa: Um prompt é enviado solicitando que o agente gere uma imagem do site
meal_description
fornecido que é gerado pelo próximo agente de refeição. - Tratamento de respostas: A função verifica se a resposta contém pedaços de imagem. Em caso afirmativo, você fará o download de cada imagem por meio do método
files.download()
do cliente Mistral. As imagens são salvas localmente em uma pastagenerated_images/
com nomes de arquivos com registro de data e hora. - Saída: Ele retorna o caminho para a primeira imagem salva com êxito ou uma mensagem de erro de fallback se a geração falhar.
Essa ferramenta acrescenta uma camada visual ao nosso treinador de nutrição, tornando as sugestões de refeições mais envolventes e realistas.
Etapa 3: Linha de produção completa para nutricionistas
Agora que criamos as ferramentas individuais e os recursos do agente, é hora de colocá-los em um único pipeline. Nesta etapa, você cola tudo em um assistente de trabalho que pode ser manuseado:
- Pesquisa de calorias (via web ou estimativa)
- Registro (usuário, refeição, calorias, registro de data e hora)
- Sugerir uma refeição de acompanhamento
- Visualizando a refeição com uma imagem
Todas essas etapas são tratadas chamando cada função dos nossos arquivos anteriores na ordem correta. O código para esse pipeline fica fora da pasta de ferramentas no arquivo 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))
}
O código acima coordena todo o fluxo de trabalho do assistente de nutrição, encadeando várias ferramentas de agente em um único pipeline. Vamos analisar o código acima com mais detalhes:
- A função
run_nutritionist_pipeline()
aceitausername
,meal_desc
edietary_preference
como entradas para conduzir o processo de recomendação. - Primeiro, ele tenta determinar o conteúdo de calorias da refeição usando a função
search_calories()
, alimentada pelo conector de pesquisa na Web da Mistral. Se isso falhar, você recorrerá a uma estimativa usando um modelo leve por meio do siteestimate_calories()
. - O valor de calorias obtido é então registrado usando a função
log_meal()
, que marca a entrada com um carimbo de data/hora e a associa ao usuário. - Com base nas calorias consumidas e na preferência alimentar, a função
suggest_next_meal()
sugere uma refeição de acompanhamento usando o raciocínio baseado em solicitações. - Por fim, a função
generate_food_image()
usa o conector de geração de imagens do Mistral para produzir uma representação visual do prato recomendado. - Durante todo o processo, o site
time.sleep(1)
é usado para introduzir breves pausas entre as solicitações para evitar o acionamento de limites de taxa durante as chamadas de API. - A função retorna um dicionário que contém a confirmação do registro da refeição, o texto da sugestão da próxima refeição, o caminho da imagem gerada e uma lista de ferramentas que foram usadas nessa interação.
Esse pipeline combina vários recursos, como pesquisa, estimativa, registro, sugestão e visualização, em uma experiência de nutrição com tecnologia de IA.
Etapa 4: Criando uma interface amigável para o usuário com o Gradio
Agora que a lógica de back-end está concluída, vamos transformá-la em um front-end limpo e fácil de usar usando o 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()
No trecho de código acima, configuramos uma interface completa da IU do Gradio para interagir com o pipeline do agente nutricionista. Veja como isso funciona:
- Começamos importando a função
run_nutritionist_pipeline()
do siteagent.py
, que orienta a lógica central do agente. - Em seguida, a função
process_meal()
atua como um invólucro em torno do pipeline do agente, que aceitausername
,meal_desc
edietary_preference
como entradas do usuário e aciona a lógica de vários agentes definida anteriormente. - Dentro da função
process_meal()
, o dicionário de resultados é analisado para extrair o resumo da refeição, as calorias, a próxima refeição sugerida e os conectores usados. - A função também verifica se o caminho da imagem gerada é válido antes de retorná-lo para exibição. Se a imagem não for encontrada, somente o resultado textual será retornado.
- O aplicativo Gradio foi criado usando o site
gr.Blocks()
e o layout inclui dois lados, um com campos de entrada e um botão Process Meal. Enquanto o outro lado contém uma área de saída para os resultados da análise da refeição e uma visualização da imagem da próxima refeição. - A chamada de retorno
submit_btn.click()
conecta o botão de front-end para acionar a funçãoprocess_meal()
, passando as entradas e recebendo a marcação formatada e a imagem como saídas. - Por fim, o aplicativo é iniciado via
demo.launch()
se o script for executado como o módulo principal. Você pode definirdebug = True
para ativar o modo de depuração do aplicativo.
Para executar essa demonstração, abra um terminal no diretório raiz e digite o seguinte comando:
python app.py
A estrutura geral desse projeto seria semelhante a esta:
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
Você pode encontrar o código completo desse projeto em este repositório do GitHub.
Conclusão
Neste tutorial, criamos um treinador de nutrição com IA totalmente funcional usando a API Mistral Agents. Ao longo do caminho, exploramos:
- Como os agentes Mistral diferem dos modelos LLM brutos
- A função de conectores como
web_search
eimage_generation
- Orquestração de vários agentes em um único pipeline
- Criando um front-end fácil de usar com o Gradio
Este projeto mostra o poder dos fluxos de trabalho agênticos em que os LLMs não são apenas respondedores passivos, mas entidades interativas que raciocinam, agem e coordenam tarefas. Desde o registro de refeições até a sugestão de alternativas saudáveis e até mesmo a geração de imagens, mostramos como combinar ferramentas simples em experiências poderosas de IA.
Para saber mais sobre o uso de agentes de IA, recomendo estes tutoriais práticos:

Sou Google Developers Expert em ML (Gen AI), Kaggle 3x Expert e Women Techmakers Ambassador com mais de 3 anos de experiência em tecnologia. Fui cofundador de uma startup de tecnologia de saúde em 2020 e estou fazendo mestrado em ciência da computação na Georgia Tech, com especialização em machine learning.