Ana içeriğe geç

Mistral Agents API: Demo Projeyle Rehber

Mistral’ın Agents API’sini kullanarak yapay zekâ ajanları oluşturmayı öğrenin ve araç kullanımı, konektörler, devirler ve daha fazlası gibi temel kavramları keşfedin.
· 12 dk. oku

Yapay Zeka ile Keşfedin

Mistral, Agents API’yi yayınladı: karmaşık, çok adımlı görevleri yerine getirebilen akıllı, otonom yapay zekâ ajanlarının geliştirilmesini kolaylaştıran bir çerçeve. Bu yapı, araç kullanımı, kalıcı bellek ve orkestrasyon yeteneklerini entegre ederek geleneksel dil modellerinin ötesine geçiyor.

Bu eğitimde, Mistral Agents API’yi kullanarak şu yeteneklere sahip akıllı asistanlar oluşturmayı adım adım göstereceğim:

  • Web araması, kod çalıştırma ve görsel üretimi gibi araçların kullanımı
  • Bağlamı korumak için uzun sohbetler boyunca belleği sürdürme
  • Görevleri birden fazla ajan arasında paylaştırma

Mistral’ın ajan odaklı çerçevesinin temel kavramlarını öğrenecek, yerleşik konektörleri ve orkestrasyon özelliklerini keşfedecek ve çalışan bir çoklu ajan asistanı inşa edeceksiniz.

Okurlarımızı yapay zekâdaki gelişmelerden haberdar etmek için, haftanın önemli haberlerini sade bir dille özetleyen ücretsiz Cuma bültenimiz The Median’ı gönderiyoruz. Abone olun; haftada sadece birkaç dakikada güncel kalın:

Mistral’ın Agents API’si Nedir?

Mistral Agents API; büyük dil modellerinin çok adımlı eylemler gerçekleştirmesini, harici araçlar kullanmasını ve etkileşimler boyunca belleği sürdürmesini sağlayan bir çerçevedir. Basit sohbet API’lerinden farklı olarak, yapay zekâ ajanlarına şu yetkileri verir:

  • Web’e erişme, kod yürütme, görsel üretme veya belgeleri getirme
  • Orkestrasyon yoluyla diğer ajanlarla koordinasyon kurma
  • Uzun vadeli bellekle kalıcı sohbetleri sürdürme

Şu anda yalnızca mistral-medium-latest (diğer adıyla mistral-medium-2505) ve mistral-large-latest destekleniyor; yakında yeni modeller de desteklenebilir.

Temel Kavramlar

Uygulamalı kısma geçmeden önce, Agents API’nin temel kavramlarını netleştirmenin yararlı olacağını düşünüyorum.

mistral agents api diagram

Kaynak: Mistral AI

Ajanlar

Ajanlar, Mistral’da önceden tanımlı yönergeler, araç erişimi ve sohbet durumu ile güçlendirilmiş model tabanlı personlardır:

  • Yönergeler, ajanın davranışını yönlendirir (ör. “Bir öğün kaydı tutan beslenme koçusunuz”).
  • web_search veya image_generation gibi araçlar, ajanların gerçek dünyada eylem almasını sağlar.
  • Bellek, dönüşler boyunca önceki iletileri ve araç çıktılarını takip etmeyi mümkün kılar; bağlamsal akıl yürütmeyi destekler.

Bu soyutlama, basit bir sohbet modelini, karmaşık iş akışlarına katılabilen çok işlevli bir asistana dönüştürür.

Sohbetler 

Bir kullanıcı ile bir ajan arasındaki her etkileşim, şu öğelerin saklandığı bir sohbetin parçasıdır:

  • Geçmiş iletiler ve asistan yanıtları
  • Araç çağrıları ve sonuçları
  • Token düzeyinde görünürlük için akış metaverileri (isteğe bağlı)

Bu kalıcı sohbetler, ajanların planlama, revizyon veya önceki girdilerden öğrenme gibi çok aşamalı görevleri yerine getirmesine olanak tanır.

Konektörler ve özel araç desteği

Mistral, aşağıdaki yollarla kolay araç entegrasyonu sağlar:

  • Konektörler: Kutudan çıktığı gibi çalışan web_search, code_execution, image_generation, document_library gibi önceden entegre araçlardır.
  • MCP araçları: Geliştiriciler tarafından barındırılan ve ajan iş akışında araç olarak çağrılabilen özel API’lere olanak tanır.

Konektörleri yerleşik uygulamalar, MCP Araçlarını ise sizin yazdığınız eklentiler gibi düşünün. Birlikte, ajanların hem yerleşik yeteneklere hem de geliştirici tanımlı uç noktalara erişmesine olanak tanır; böylece kişiselleştirilmiş mantık ekleyebilirsiniz.

mistral agents api mcp diagram

Kaynak: Mistral AI

Kayıtlar ve devirler (handoff)

Mistral, bir sohbetteki tüm eylemleri yapılandırılmış “Kayıtlar” olarak izler; bu da ileti alışverişleri ve araç yürütmeleri üzerinde izlenebilirlik ve kontrol sağlar.

Ajan devirleri, iş akışlarını modülerleştirmek için bir ajanın kontrolü başka bir ajana devrettiği durumlardır.

mistral agent handoffs

Kaynak: Mistral AI

Bu orkestrasyon mimarisi, şeffaflık veya kontrolden ödün vermeden karmaşık çoklu ajan sistemlerini birleştirip yönetmeyi kolaylaştırır.

Mistral API Kurulumu

Mistral’ı kurarak başlayalım. Proje için bir API anahtarı oluşturmakla başlayacağız. İzlemeniz gereken adımlar şunlar:

  1. Başlamak için bir Mistral hesabı oluşturun veya console.mistral.ai adresinden oturum açın.

Mistral dashboard

  1. Ardından, Çalışma Alanı Ayarları’na (adınızın yanındaki açılır ok—sol üst köşe) gidin ve Faturalama’ya tıklayarak ödeme bilgilerinizi ekleyin ve hesabınızda ödemeleri etkinleştirin.

Mistral billing

  1. Kredi ekle’ye tıklayın ve formdaki fatura bilgilerinizi doldurun. Ardından, istediğiniz kredi miktarını girin. Not: En az 10 kredi eklemeniz gerekir.

Mistral credits

  1. Sonra, sol sekmeden API keys’e tıklayın ve Create new key’e tıklayarak yeni bir API anahtarı oluşturun. API anahtarını kopyaladığınızdan, güvenle sakladığınızdan ve kimseyle paylaşmadığınızdan emin olun.

Artık Mistral modelleriyle etkileşime geçmek ve akıllı ajanlar oluşturmak için geçerli bir API anahtarınız var.

Proje Genel Bakış: Mistral Ajanlarıyla Beslenme Koçu

Bu projede, Mistral’ın Agents API’sini kullanarak yapay zekâ destekli bir Beslenme Koçu oluşturacağız. Kullanıcı akışı şöyle:

  1. Kullanıcı az önce yediği bir öğünü gönderir (ör. "zeytinyağlı soslu tavuk salatası").
  2. Bir web arama ajanı, dahili konektörü kullanarak öğünün kalori tahminini yapar.
  3. Bir kayıtçı ajan, bu girdiyi kullanıcının adı ve zaman damgası altında kaydeder.
  4. Son olarak, bir görsel üretim ajanı sağlıklı bir takip öğünü önerir; hem görseli hem de açıklama ve tarifi döndürür.

Kullanıcıların beslenme koçuyla etkileşim kurabileceği bir web arayüzü sağlamak için Gradio kullanacağız.

Adım 1: Önkoşullar

Başlamadan önce aşağıdakilerin kurulu olduğundan emin olun:

  • Python 3.8+
  • requirements.txt’te listelenen tüm gerekli paketler
python-dotenv==1.1.0
mistralai==0.0.7
typing-extensions==4.12.2
requests==2.31.0
gradio==4.34.0

Ayrıca, Mistral API anahtarınızı içeren bir .env dosyası ayarlayın. Bu yaklaşım, API anahtarlarınızı güvende tutar ve farklı ekip üyelerinin veya dağıtım ortamlarının kaynak kodu değiştirmeden farklı kimlik bilgileri kullanmasına olanak tanır.

MISTRAL_API_KEY=YOUR_API_KEY

Not: Bu bağımlılıkları, diğer Python projeleriyle sürüm çakışmalarından kaçınmak için conda, venv veya uv gibi yalıtılmış bir ortamda kurmanız önerilir.

Farklı ortamları kurmak için komutlar şunlardır:

venv kullanarak

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

Conda kullanarak

conda create -n mistral_env python=3.10
conda activate mistral_env

uv kullanarak

Henüz uv’niz yoksa:

pip install uv

Ardından:

uv venv mistral_env
source mistral_env/bin/activate

Yukarıda belirtilen tüm bağımlılıkları kurmak için terminalinizde şu komutu çalıştırın:

pip install -r requirements.txt

Not: Herhangi bir ajan veya konektörü kullanırken mistralai ile ilgili hatalarla karşılaşırsanız, aşağıdaki komutu çalıştırın:

pip install –upgrade mistralai

Bu, mistralai kütüphanesini en son sürümüne yükseltecektir.

Adım 2: Mistral Araçlarını Kurma

Bu bölümde, Mistral Agents API ile etkileşim için araçlarımızı ve istemci kurulumumuzu hazırlayacağız. Araç şemalarını tanımlayacak, istemciyi başlatacak ve kimlik doğrulamayı doğrulayacağız. Bu araçlar, daha sonra kalori tahminleyiciler veya görsel üreticiler gibi belirli ajanları kurarken referans alınacaktır.

Adım 2.1: Araç kaydı ve başlatma

Önce araç şemalarımızı, model seçimini ve istemci başlatmayı tanımlıyoruz. Ardından create_chat_completion() ve check_client() gibi yardımcı yöntemler oluşturuyoruz. Aşağıdaki kod, tools klasörü içindeki configs.py dosyasına girer:

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

Başlangıçta, Mistral API anahtarı gibi hassas değişkenleri yerel bir .env dosyasından Python ortamına yüklemek için dotenv’i içe aktarıyoruz. Bu, kimlik bilgilerini güvende ve kaynak kodunun dışında tutar. Ardından, varsayılan model olarak mistral-large-latest’i seçip API anahtarını kullanarak bir Mistral istemcisi başlatıyoruz.

Sonra, JSON şema formatını kullanarak dahili araç özelliklerini (şemaları) tanımlarız. Bunlar şu konularda yardımcı olur:

  • MCP araç davranışını simüle etmek (McqTool kütüphanesiyle kaydedilmeseler de)
  • "username", "meal" ve "calories" gibi beklenen girdileri tanımlamak
  • Modüller arasında tutarlı girdi biçimlendirmesini sağlamak

Şimdi, sohbet tamamlama oluşturan, araçları ve ajanları kaydeden ve istemciyi başlatan yardımcı yöntemlerimizi ekleyelim.

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

create_chat_completion() işlevi, Mistral istemci SDK’sının bir parçası olan client.chat.complete() yöntemine yapılan bir çağrıyı sarmalar ve iletileri modele gönderir.

  • Ham sözlük tarzı iletileri, Mistral SDK’sının gerektirdiği UserMessage ve SystemMessage nesnelerine dönüştürür.
  • Uygulama genelinde standartlaştırılmış tamamlamalar için de kullanışlıdır.

register_tools() ve register_agents() işlevleri, yerel geliştirme sırasında sistemde hangi araç ve ajanların etkin olduğunu kayda geçirerek yardımcı olur. Bu arada, check_client() ve is_client_initialized() işlevleri Mistral istemcisinin doğru şekilde başlatıldığını ve API anahtarının mevcut olduğunu doğrulayarak ajan çalıştırma sırasında çalışma zamanı hatalarını önlemeye yardımcı olur.

Adım 2.2: Web arama ajanıyla kalori tahmini

Artık temel araçları ve istemciyi başlattığımıza göre, özel bir Beslenme Web Arama Ajanı oluşturalım. Bu ajan, Mistral’ın web_search konektörünü kullanarak öğünler için gerçek zamanlı kalori tahminleri arar. Bu kod, tools klasörü içindeki web_search.py dosyasında yer alır.

# 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

Yukarıdaki kodda, search_calories() işlevi, Mistral Agents API’nin yerleşik web arama konektörünü kullanır; bu, ajanların kalori tahmini gibi canlı web sorguları gerçekleştirmesini sağlar ve statik model eğitiminin sınırlamalarını aşar. Nasıl çalıştığı şöyle:

  1. Ajan oluşturma: Önce, mistral-medium-latest modelini kullanan ve web_search aracıyla donatılmış, yalnızca kalori döndürmesi talimatı verilmiş bir “Beslenme Arama Ajanı” oluşturur.
  2. Sorgu yürütme: Daha sonra, sağlanan öğün açıklamasındaki toplam kaloriyi soran bir sohbet başlatmak için ajan kullanılır.
  3. Yanıt ayrıştırma: Ajanın yanıtı, ilk sayısal değeri (kalori sayısı olmalı) çıkarmak için düzenli ifadelerle ayrıştırılır.
  4. Geri dönüşler: Geçerli bir sayı bulunamazsa veya bir hata oluşursa, işlev sorunu günlüğe kaydeder ve geri dönüş olarak sıfır döndürür.

web_search olmadan, çoğu model yakın tarihli olaylar veya eğitim verilerinde görülmeyen alanlara özgü öğünler hakkında yanıt veremez. Bununla birlikte, besin bilgilerini, restoran menülerini veya haber makalelerini gerçek zamanlı olarak sorgulayabiliriz.

Web aramasının iki varyantı vardır:

  • web_search: Projemizde kullandığımız hafif, genel amaçlı arama motoru konektörü.
  • web_search_premium: Haber sağlayıcı doğrulaması ve daha geniş bağlam toplama içeren geliştirilmiş sürüm.

Sırada, yalnızca isteme dayalı mantıkla geri dönüş kalori tahminini keşfedeceğiz.

Adım 2.3: Tahmin, kayıt ve öğün önerisi

Bu bölümde, geri dönüş veya iyileştirme olarak iş gören üç temel işlevi uyguluyoruz. Aşağıdaki kod, tools klasöründeki next.py dosyasında bulunur.

#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."

Bu betik, beslenme iş akışımızı güçlendiren temel arka uç işlevlerini tanımlar (kalori tahmininden takip öğünü planlamaya). Bu işlevler, web araması kullanılamadığında veya hız sınırı hatalarından kaçınmak için ajan oluşturma veya konektör gerektirmeden hafif Mistral modelleri ve standart sohbet tamamlama kullanır. Her işlevin yaptığı şunlardır:

  1. estimate_calories(): web_search konektörü başarısız olursa veya kullanılamazsa geri dönüş olarak kullanılır.
    1. Asistanın beslenme uzmanı rolünü içeren bir sistem iletisi ile, kullanıcının kaydetmek istediği öğünün yer aldığı kullanıcı istemini gönderir.
    2. Model temperature=0.1 gibi düşük bir değerle deterministik çıktı için kullanılır. Bu, kalori tahmini ve kayıt gibi yaratıcı çeşitlilikten çok istikrarlı ve olgusal çıktının tercih edildiği görevlerde, modelin aynı girdiler için tutarlı, tekrarlanabilir yanıtlar üretmesi anlamına gelir.
    3. Model yanıtından ilk sayıyı (regex ile) ayrıştırır.
  2. log_meal(): Bir kullanıcının öğününü zaman damgasıyla birlikte kaydeder.
    1. Talimatla bir sohbet tamamlama kullanır ve asistanın biçimlendirilmiş onay iletisini döndürür.
    2. Bu, özel bir arka uç veritabanı gerektirmeden hafif iç kayıt tutmayı sağlar.
  3. suggest_next_meal(): Önceden alınan kalori ve kullanıcının beslenme tercihine göre bir sonraki öğünü önerir.
    1. temperature=0.7 ile çağrılır; bu da daha yaratıcı önerileri teşvik eder.
    2. Yanıt kırpılır ve bir sonraki öğün fikri olarak döndürülür.

Birlikte, bu işlevler harici API’lere ihtiyaç duymadan kalori tahmini, kayıt onayı ve sağlıklı öneriler sunar. Bir sonraki adımda, Mistral’ın görsel üretim konektörüyle yiyecek önerilerini görselleştireceğiz.

Adım 2.4: Görsel üretim konektörüyle görseller oluşturma

Şimdi asistanımıza görsel bir katman ekleyelim. Bu adımda, Mistral’ın yerleşik image_generation konektörünü kullanarak önerilen bir sonraki öğünün iştah açıcı bir görselini üreteceğiz.

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

generate_food_image() işlevi, Mistral’ın yerleşik image_generation aracını kullanarak bir öğünün görsel temsilini üretir. Her bölüm şunu yapar:

  • Ajan oluşturma: Gerçekçi ve iştah açıcı yiyecek görselleri üretmesi talimatı verilmiş yeni bir ajan oluşturulur.
  • Sohbet başlatma: Ajandan, bir sonraki öğün ajanı tarafından üretilen meal_description’ın görselini oluşturması istenir.
  • Yanıt işleme: Yanıtın görsel parçalar içerip içermediği kontrol edilir. Evetse, Mistral istemcisinin files.download() yöntemiyle her görsel indirilir. Görseller, zaman damgalı dosya adlarıyla yerel olarak generated_images/ klasörüne kaydedilir.
  • Çıktı: Başarıyla kaydedilen ilk görselin yolu döndürülür; üretim başarısız olursa geri dönüş hata iletisi döndürülür.

Bu araç, beslenme koçumuza görsel bir katman ekleyerek öğün önerilerini daha ilgi çekici ve gerçekçi kılar.

Adım 3: Tam Beslenme Uzmanı Hattı (Pipeline)

Artık tek tek araçları ve ajan yeteneklerini oluşturduğumuza göre, bunları tek bir hatta toplayalım. Bu adım, aşağıdakileri yöneten çalışan bir asistan oluşturmak için her şeyi birbirine bağlıyor:

  • Kalori sorgulama (web veya tahmin yoluyla)
  • Kayıt (kullanıcı, öğün, kalori, zaman damgası)
  • Takip öğünü önerisi
  • Öğünün görselleştirilmesi

Tüm bu adımlar, önceki dosyalarımızdaki her işlevin doğru sırayla çağrılmasıyla yönetilir. Bu hattın kodu, tools klasörünün dışında agent.py dosyasında yer alır.

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

Yukarıdaki kod, birden fazla ajan aracını tek bir hatta zincirleyerek tam beslenme asistanı iş akışını koordine eder. Kodun ayrıntılı özeti şöyle:

  • run_nutritionist_pipeline() işlevi, öneri sürecini yönlendirmek için girdiler olarak username, meal_desc ve dietary_preference alır.
  • Önce, Mistral’ın web arama konektörü tarafından desteklenen search_calories() işleviyle öğünün kalori içeriğini belirlemeye çalışır. Bu başarısız olursa, estimate_calories() ile hafif bir model kullanılarak tahmine geri döner.
  • Elde edilen kalori değeri, girdiyi zaman damgasıyla etiketleyen ve kullanıcıyla ilişkilendiren log_meal() ile kaydedilir.
  • Tüketilen kalorilere ve beslenme tercihine göre, suggest_next_meal() işlevi isteme dayalı akıl yürütmeyle bir takip öğünü önerir.
  • Son olarak, generate_food_image() işlevi, önerilen yemeğin görsel temsilini üretmek için Mistral’ın görsel üretim konektörünü kullanır.
  • Süreç boyunca, API çağrıları sırasında hız sınırlarını tetiklememek için time.sleep(1) ile kısa duraklamalar eklenir.
  • İşlev; öğün kayıt onayı, bir sonraki öğün öneri metni, oluşturulan görsel yolu ve bu etkileşimde kullanılan araçların listesini içeren bir sözlük döndürür.

Bu hat; arama, tahmin, kayıt, öneri ve görselleştirme gibi çeşitli yetenekleri bir araya getirerek yapay zekâ destekli bir beslenme deneyimi sunar.

Adım 4: Gradio ile Kullanıcı Dostu Arayüz Oluşturma

Art arda gelen mantık tamamlandığına göre, bunu Gradio kullanarak sade ve kullanıcı dostu bir ön yüze saralım.

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

Yukarıdaki kod parçacığında, Beslenme Uzmanı Ajan hattıyla etkileşim için eksiksiz bir Gradio UI arayüzü kurduk. Nasıl çalıştığı şöyle:

  • Önce, çekirdek ajan mantığını yöneten agent.py’den run_nutritionist_pipeline() işlevini içe aktarıyoruz.
  • Ardından process_meal() işlevi, ajan hattının etrafında bir sarmalayıcı görevi görür; username, meal_desc ve dietary_preference girdilerini alır ve daha önce tanımlanan çoklu ajan mantığını tetikler.
  • process_meal() içinde, sonuç sözlüğü; öğün özeti, kaloriler, önerilen bir sonraki öğün ve kullanılan konektörleri çıkarmak için ayrıştırılır.
  • İşlev ayrıca, oluşturulan görsel yolunun görüntülenmeden önce geçerli olup olmadığını denetler. Görsel bulunamazsa yalnızca metinsel sonuç döndürülür.
  • Gradio uygulaması gr.Blocks() kullanılarak oluşturulur; düzen bir tarafta giriş alanları ve Process Meal düğmesini, diğer tarafta ise öğün analizi sonuçları için bir çıktı alanı ve bir sonraki öğünün önizleme görselini içerir.
  • submit_btn.click() geri çağrısı, ön uç düğmesini process_meal() işlevini tetikleyecek şekilde bağlar; girdileri iletir ve çıktı olarak biçimlendirilmiş markdown ve görsel alır.
  • Son olarak, betik ana modül olarak çalıştırıldığında uygulama demo.launch() ile başlatılır. Uygulamanın hata ayıklama modunu etkinleştirmek için debug = True ayarlanabilir.

Bu demoyu çalıştırmak için, kök dizininizde bir terminal açın ve şu komutu yazın:

python app.py

Projenin genel yapısı şöyle görünecektir:

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 

Bu projenin tam kodunu bu GitHub deposunda bulabilirsiniz.

Nutritionist Assistant with mistral agents api

Nutritionist Assistant with mistral agents api

Nutritionist Assistant with mistral agents api

Sonuç

Bu eğitimde, Mistral Agents API kullanarak tamamen işlevsel bir Yapay Zekâ Beslenme Koçu oluşturduk. Bu süreçte şunları inceledik:

  • Mistral ajanlarının ham LLM modellerinden nasıl farklılaştığı
  • web_search ve image_generation gibi konektörlerin rolü
  • Tek bir hat içinde birden fazla ajanın orkestrasyonu
  • Gradio ile kullanıcı dostu bir ön yüz geliştirme

Bu proje, LLM’lerin yalnızca pasif yanıtlayıcılar değil, aynı zamanda akıl yürüten, eyleme geçen ve görevleri koordine eden etkileşimli varlıklar olduğu ajan odaklı iş akışlarının gücünü gösteriyor. Öğün kaydetmekten sağlıklı alternatifler önermeye ve hatta görseller üretmeye kadar, basit araçların nasıl güçlü yapay zekâ deneyimlerine dönüştürülebileceğini gösterdik.

Yapay zekâ ajanlarını kullanmayı öğrenmek için şu uygulamalı eğitimleri öneririm:

Aashi Dutt

Yazar

Aashi Dutt

ML (Üretken Yapay Zekâ) alanında Google Developers Uzmanıyım, Kaggle 3x Expert unvanına sahibim ve 3+ yıllık teknoloji deneyimiyle Women Techmakers Elçisiyim. 2020'de bir sağlık teknolojileri girişiminin kurucu ortağı oldum ve Georgia Tech'te makine öğrenmesi alanında uzmanlaşarak bilgisayar bilimleri yüksek lisansı yapıyorum.

Konular

İlgili