You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

14 KiB

مدیریت مدل‌های LLM در سیستم Islamic Scholar Agent

📋 نمای کلی

سیستم مدیریت مدل‌های LLM در پروژه Islamic Scholar Agent به صورت متمرکز و قابل تنظیم طراحی شده است. این سیستم جایگزین رویکرد قدیمی hardcoded مدل‌ها شده و امکان تغییر سریع بین مدل‌های مختلف، افزودن provider جدید و مدیریت تنظیمات را فراهم می‌کند.

🎯 چرایی این سیستم

مشکل رویکرد قدیمی

در گذشته، مدل‌های LLM به صورت مستقیم در کد استفاده می‌شدند:

# ❌ رویکرد قدیمی - hardcoded
from agno.models.openrouter import OpenRouter
agent = Agent(
    model=OpenRouter(id="deepseek/deepseek-r1-0528:free"),
    ...
)

این رویکرد مشکلات زیر را داشت:

  • عدم انعطاف‌پذیری: تغییر مدل نیازمند تغییر کد بود
  • پراکندگی تنظیمات: هر مدل تنظیمات خودش را داشت
  • مشکل در تست: نمی‌توان به راحتی بین مدل‌ها سوییچ کرد
  • مدیریت API keys: کلیدها در کد پراکنده بودند

راه‌حل جدید

# ✅ رویکرد جدید - متمرکز و قابل تنظیم
from src.models.factory import ModelFactory

model_factory = ModelFactory()
agent = Agent(
    model=model_factory.get_model(),  # استفاده از مدل پیش‌فرض
    # یا
    model=model_factory.get_model('gpt4'),  # تغییر به مدل دیگر
    ...
)

🏗️ معماری سیستم

ساختار فایل‌ها

config/
├── models.yaml          # تنظیمات متمرکز مدل‌ها

src/models/
├── base_model.py        # کلاس پایه abstract
├── factory.py           # کارخانه مدل‌ها
└── ...                  # implementهای خاص هر provider

فایل‌های کلیدی

1. config/models.yaml

فایل تنظیمات مرکزی که همه مدل‌ها و providerها را تعریف می‌کند:

# config/models.yaml
models:
  # سوئیچ اصلی - تغییر این مقدار = تغییر مدل کل سیستم
  default: deepseek_r1

  providers:
    # Provider 1: MegaLLM (OpenAI-Like)
    openai_like:
      api_key: ${MEGALLM_API_KEY}
      base_url: ${API_URL}
      models:
        deepseek_v3:
          id: "deepseek-ai/deepseek-v3.1"
          temperature: 0.7
          max_tokens: 4096
          supports_streaming: true

    # Provider 2: OpenRouter
    openrouter:
      api_key: ${OPENROUTER_API_KEY}
      base_url: ${OPENROUTER_BASE_URL}
      models:
        deepseek_r1:
          id: "deepseek/deepseek-r1-0528:free"
          temperature: 0.6
          max_tokens: 4096

# Rate limiting
rate_limits:
  requests_per_minute: 60
  tokens_per_minute: 100000

2. src/models/base_model.py

کلاس پایه abstract برای همه providerها:

from abc import ABC, abstractmethod
from typing import Optional
import os

class BaseLLMProvider(ABC):
    """Abstract base class for LLM providers"""

    def __init__(self, api_key: str, base_url: Optional[str] = None):
        self.api_key = api_key
        self.base_url = base_url

    @abstractmethod
    def get_model(self):
        """Return configured model instance"""
        pass

3. src/models/factory.py

کارخانه اصلی که مدل‌ها را از تنظیمات ایجاد می‌کند:

import os
import yaml
from typing import Optional
from agno.models.openrouter import OpenRouter
from agno.models.openai.like import OpenAILike

class ModelFactory:
    """Factory for creating LLM instances from configuration"""

    def __init__(self, config_path: str = "config/models.yaml"):
        # بارگذاری YAML
        with open(config_path) as f:
            self.config = yaml.safe_load(f)

    def get_model(self, model_name: Optional[str] = None):
        # 1. تعیین مدل مورد استفاده
        if model_name is None:
            model_name = self.config['models']['default']
            print(f"Using default model: {model_name}")

        # 2. جستجو در همه providerها
        providers = self.config['models']['providers']
        for provider_name, provider_data in providers.items():
            if model_name in provider_data['models']:
                # یافت شد!
                print(f"Found model: {model_name} in provider: {provider_name}")
                model_config_data = provider_data['models'][model_name]

                # Resolve environment variables
                api_key_env = provider_data.get('api_key')
                if api_key_env and api_key_env.startswith("${"):
                    api_key = os.getenv(api_key_env[2:-1])
                else:
                    api_key = api_key_env

                base_url_env = provider_data.get('base_url')
                if base_url_env and base_url_env.startswith("${"):
                    base_url = os.getenv(base_url_env[2:-1])
                else:
                    base_url = base_url_env

                # 3. ایجاد کلاس مناسب
                if provider_name == 'openai_like':
                    return OpenAILike(
                        id=model_config_data['id'],
                        api_key=api_key,
                        base_url=base_url,
                        max_tokens=model_config_data.get('max_tokens', 4096),
                        default_headers={
                        "Authorization": f"Bearer {api_key}",
                        "Content-Type": "application/json"
                        },
                    )

                elif provider_name == 'openrouter':
                    return OpenRouter(
                        id=model_config_data['id'],
                        api_key=api_key,
                        base_url=base_url,
                        default_headers={
                        "Authorization": f"Bearer {api_key}",
                        "Content-Type": "application/json"
                    },
                    )

        raise ValueError(f"Model '{model_name}' not found in configuration")

🚀 نحوه استفاده

استفاده پایه

# src/main.py
from src.models.factory import ModelFactory

def create_app():
    # ایجاد factory
    model = ModelFactory()

    # استفاده از مدل پیش‌فرض
    agent = IslamicScholarAgent(model.get_model(), knowledge_base)

    return agent

تغییر مدل در زمان اجرا

# تغییر به مدل دیگر
gpt4_agent = IslamicScholarAgent(model_factory.get_model('gpt4'), knowledge_base)

# یا تغییر مدل پیش‌فرض در YAML
# models.yaml -> default: gpt4

افزودن مدل جدید

مرحله 1: افزودن به YAML

# config/models.yaml
models:
  providers:
    openai:
      api_key: ${OPENAI_API_KEY}
      base_url: https://api.openai.com/v1
      models:
        gpt4:
          id: "gpt-4o"
          temperature: 0.7
          max_tokens: 4096
          supports_streaming: true

مرحله 2: افزودن logic به factory

# src/models/factory.py
elif provider_name == 'openai':
    return OpenAIChat(
        id=model_config_data['id'],
        api_key=provider_config['api_key'],
        temperature=model_config_data.get('temperature', 0.7),
        max_tokens=model_config_data.get('max_tokens', 4096),
    )

مزایای این سیستم

1. سوئیچ سریع بین مدل‌ها

# تغییر از DeepSeek به GPT-4 فقط با یک خط تغییر در YAML
# config/models.yaml
default: gpt4  # تغییر از deepseek_r1

2. مدیریت متمرکز تنظیمات

  • همه تنظیمات در یک فایل YAML
  • تغییر تنظیمات بدون تغییر کد
  • امکان override توسط environment variables

3. امکان A/B Testing

# تست دو مدل مختلف در کنار هم
model_a = model_factory.get_model('deepseek_r1')
model_b = model_factory.get_model('gpt4')

# مقایسه عملکرد دو مدل

4. مدیریت آسان API Keys

# تنظیم متغیرهای محیطی
export MEGALLM_API_KEY="your_key_here"
export OPENROUTER_API_KEY="your_key_here"
export OPENAI_API_KEY="your_key_here"

5. افزودن Provider جدید بدون تغییر کد موجود

# افزودن provider جدید به YAML
providers:
  anthropic:
    api_key: ${ANTHROPIC_API_KEY}
    models:
      claude3:
        id: "claude-3-sonnet-20240229"
        temperature: 0.7

6. امکان توسعه‌پذیری

  • هر provider می‌تواند تنظیمات خاص خودش را داشته باشد
  • امکان افزودن validation خاص هر مدل
  • پشتیبانی از rate limiting متمرکز

7. تسهیل Testing

# استفاده از مدل‌های mock/test در محیط تست
# config/models.test.yaml
models:
  default: test_model
  providers:
    test:
      models:
        test_model:
          id: "test-model"
          temperature: 0.0

🔧 تنظیمات پیشرفته

Rate Limiting

# config/models.yaml
rate_limits:
  requests_per_minute: 60
  tokens_per_minute: 100000

تنظیمات مدل خاص

models:
  deepseek_r1:
    id: "deepseek/deepseek-r1-0528:free"
    temperature: 0.6          # کنترل خلاقیت
    max_tokens: 4096           # حداکثر طول پاسخ
    supports_streaming: true   # پشتیبانی از streaming

Environment Variables

# .env
MEGALLM_API_KEY=sk-...
OPENROUTER_API_KEY=sk-or-...
OPENAI_API_KEY=sk-...

🧪 تست سیستم

تست‌های واحد

# tests/test_models.py
def test_model_factory_default():
    factory = ModelFactory()
    model = factory.get_model()
    assert model.id == "deepseek/deepseek-r1-0528:free"

def test_model_factory_specific():
    factory = ModelFactory()
    model = factory.get_model('gpt4')
    assert model.id == "gpt-4o"

تست‌های integration

# tests/test_agent_with_models.py
@pytest.mark.parametrize("model_name", ["deepseek_r1", "gpt4"])
def test_agent_with_different_models(model_name):
    factory = ModelFactory()
    model = factory.get_model(model_name)

    agent = IslamicScholarAgent(model, knowledge_base)

    response = agent.run("What is salah?")
    assert len(response.content) > 0

🚨 عیب‌یابی

مشکلات رایج

1. Model not found

ValueError: Model 'unknown_model' not found in configuration

راه‌حل: بررسی کنید مدل در config/models.yaml تعریف شده باشد.

2. API Key not set

Error: API key for provider 'openrouter' not found

راه‌حل: متغیر محیطی مربوطه را تنظیم کنید.

3. Invalid YAML syntax

yaml.YAMLError: mapping values are not allowed here

راه‌حل: syntax YAML را بررسی کنید.

Debug Mode

# فعال کردن debug در factory
import logging
logging.basicConfig(level=logging.DEBUG)

factory = ModelFactory()
model = factory.get_model()  # لاگ‌های مفصل نمایش داده می‌شود

📈 مانیتورینگ و Observability

سیستم با Langfuse integration می‌تواند عملکرد مدل‌ها را مانیتور کند:

  • تعداد استفاده از هر مدل
  • زمان پاسخ مدل‌ها
  • هزینه‌های API
  • نرخ خطای هر مدل

🔄 مهاجرت از سیستم قدیمی

قبل از تغییر

# کد قدیمی
agent = Agent(model=OpenRouter(id="deepseek/deepseek-r1-0528:free"))

بعد از تغییر

# کد جدید
from src.models.factory import ModelFactory

model_factory = ModelFactory()
agent = Agent(model=model_factory.get_model('deepseek_r1'))

مهاجرت تدریجی

  1. ایجاد ModelFactory کنار کد قدیمی
  2. تغییر gradual agentها به استفاده از factory
  3. حذف کد قدیمی پس از تست کامل

📚 بهترین تجربیات (Best Practices)

1. استفاده از Environment Variables

همیشه از environment variables برای API keys استفاده کنید:

api_key: ${OPENROUTER_API_KEY}  # ✅ خوب
api_key: sk-or-...              # ❌ بد

2. نام‌گذاری معنادار مدل‌ها

models:
  deepseek_r1:    # ✅ واضح و معنادار
  model1:         # ❌ نام‌گذار بی‌معنا

3. Validation تنظیمات

# اضافه کردن validation در factory
def _validate_config(self):
    """Validate configuration on load"""
    required_keys = ['models', 'providers']
    for key in required_keys:
        if key not in self.config:
            raise ValueError(f"Missing required config key: {key}")

4. Caching مدل‌ها

# Cache مدل‌ها برای جلوگیری از recreate مکرر
@lru_cache(maxsize=10)
def get_model(self, model_name: Optional[str] = None):
    # ... logic

🎯 نتیجه‌گیری

این سیستم مدیریت مدل‌های LLM مزایای زیر را فراهم می‌کند:

  1. انعطاف‌پذیری بالا: تغییر مدل‌ها بدون تغییر کد
  2. مدیریت متمرکز: همه تنظیمات در یک مکان
  3. تسهیل توسعه: افزودن مدل جدید ساده
  4. امکان تست: A/B testing و مقایسه مدل‌ها
  5. امنیت بهتر: API keys در environment variables
  6. قابل نگهداری: کد تمیز و سازمان‌یافته

این رویکرد نه تنها مشکلات سیستم قدیمی را حل می‌کند، بلکه پایه‌ای محکم برای توسعه آینده سیستم فراهم می‌کند.