معماری چندمدلی هوش مصنوعی چیست؟ راهنمای طراحی Multi-Model و Multi-Provider AI

معماری چندمدلی به نرم‌افزار اجازه می‌دهد براساس نوع وظیفه، کیفیت، هزینه و سرعت از مدل‌ها و ارائه‌دهندگان مختلف استفاده کند. در این راهنما طراحی، مسیریابی، Fallback، Evals و پیاده‌سازی آن را بررسی می‌کنیم.

Share
معماری چندمدلی هوش مصنوعی چیست؟ راهنمای طراحی Multi-Model و Multi-Provider AI

یک مدل هوش مصنوعی نمی‌تواند در تمام وظایف، هم‌زمان بهترین کیفیت، کمترین هزینه، بالاترین سرعت و بیشترین پایداری را ارائه کند.

ممکن است یک مدل در تولید کد عملکرد بسیار خوبی داشته باشد، اما برای طبقه‌بندی ساده بیش از حد گران باشد. مدل دیگری می‌تواند پاسخ‌های سریع و اقتصادی تولید کند، اما از ورودی تصویر یا Tool Calling پشتیبانی نکند. حتی ممکن است یک مدل مناسب باشد، اما ارائه‌دهندۀ آن در زمان افزایش ترافیک با Rate Limit یا اختلال موقت روبه‌رو شود.

به همین دلیل، معماری بسیاری از محصولات حرفه‌ای هوش مصنوعی به‌جای اتصال مستقیم به یک مدل، به سمت استفاده از چند مدل و چند ارائه‌دهنده حرکت کرده است.

در معماری چندمدلی یا Multi-Model AI، نرم‌افزار می‌تواند متناسب با نوع درخواست، یکی از چند مدل موجود را انتخاب کند. در معماری چندارائه‌دهنده‌ای یا Multi-Provider AI نیز یک مدل یا قابلیت می‌تواند از طریق چند زیرساخت و ارائه‌دهندۀ مختلف در دسترس باشد.

هدف این معماری فقط امکان تعویض مدل نیست. یک سیستم چندمدلی حرفه‌ای باید بتواند:

  • قابلیت موردنیاز درخواست را تشخیص دهد.
  • مدل‌های ناسازگار را حذف کند.
  • مدل مناسب را براساس کیفیت، هزینه و سرعت انتخاب کند.
  • Rate Limit و ظرفیت Providerها را در نظر بگیرد.
  • در زمان اختلال، Fallback انجام دهد.
  • تفاوت قالب APIها را مدیریت کند.
  • هزینه و مصرف مسیر واقعی را ثبت کند.
  • مدل جدید را بدون تغییر گستردۀ کد آزمایش کند.
  • از وابستگی شدید به یک ارائه‌دهنده جلوگیری کند.

در این مقاله، معماری Multi-Model و Multi-Provider را از سطح مفهومی تا طراحی Production، نمونه‌کد، تست، Billing، امنیت و اتصال به API درواره بررسی می‌کنیم.

پاسخ کوتاه: معماری چندمدلی هوش مصنوعی چیست؟

معماری چندمدلی هوش مصنوعی روشی برای طراحی نرم‌افزار است که در آن برنامه به‌جای وابستگی به یک مدل ثابت، می‌تواند از چند مدل برای وظایف مختلف استفاده کند.

برای مثال:

طبقه‌بندی ساده → مدل سریع و اقتصادی
تولید محتوای عمومی → مدل متعادل
تحلیل پیچیده → مدل استدلالی
بررسی تصویر → مدل چندوجهی
تولید کد → مدل تخصصی کدنویسی

در معماری چندارائه‌دهنده‌ای، یک مدل یا قابلیت می‌تواند از چند مسیر زیرساختی ارائه شود:

مدل اصلی → Provider A
همان مدل یا مدل هم‌سطح → Provider B
مسیر جایگزین → Provider C

یک Router یا AI Gateway درخواست را دریافت می‌کند، محدودیت‌ها را بررسی می‌کند و مناسب‌ترین مدل و Provider را انتخاب می‌کند.

تفاوت Multi-Model و Multi-Provider

این دو اصطلاح به یک مفهوم اشاره نمی‌کنند.

Multi-Model چیست؟

Multi-Model یعنی استفاده از چند مدل با توانایی‌ها یا ویژگی‌های متفاوت.

برای مثال:

fast-model
reasoning-model
coding-model
vision-model
embedding-model

هر مدل می‌تواند برای وظیفۀ خاصی انتخاب شود.

Multi-Provider چیست؟

Multi-Provider یعنی استفاده از چند ارائه‌دهنده یا مسیر زیرساختی.

ممکن است دو Provider مدل یکسانی را ارائه کنند یا مدل‌های متفاوتی با قابلیت مشابه داشته باشند.

Provider A → Model X
Provider B → Model X
Provider C → Model Y

معماری ترکیبی

در یک معماری کامل، هم چند مدل و هم چند Provider وجود دارند:

وظیفۀ ساده
├── مدل اقتصادی در Provider A
└── مدل اقتصادی جایگزین در Provider B

وظیفۀ پیچیده
├── مدل استدلالی در Provider C
└── مدل استدلالی جایگزین در Provider D

چرا اتصال مستقیم به یک مدل کافی نیست؟

یک مدل در تمام وظایف بهترین نیست

مدلی که برای استدلال پیچیده طراحی شده است، ممکن است برای طبقه‌بندی یک پیام کوتاه انتخاب اقتصادی مناسبی نباشد.

همچنین یک مدل ارزان ممکن است برای تولید JSON ساده مناسب باشد، اما در تحلیل قرارداد، تولید کد یا Tool Calling عملکرد کافی نداشته باشد.

مدل‌ها تغییر می‌کنند

اکوسیستم مدل‌های هوش مصنوعی با سرعت زیادی تغییر می‌کند:

  • مدل‌های جدید منتشر می‌شوند.
  • مدل‌های قدیمی بازنشسته می‌شوند.
  • قیمت‌ها تغییر می‌کنند.
  • Context Window افزایش می‌یابد.
  • نسخه‌های جدید رفتار متفاوتی دارند.
  • Providerها Endpointها یا محدودیت‌ها را تغییر می‌دهند.

اگر نام مدل در تمام بخش‌های کد پخش شده باشد، هر تغییر به بازنویسی و انتشار مجدد نیاز خواهد داشت.

Providerها ممکن است مختل شوند

حتی اگر یک مدل مناسب باشد، مسیر دسترسی به آن ممکن است با مشکلات زیر روبه‌رو شود:

  • Rate Limit
  • Timeout
  • خطای شبکه
  • کاهش ظرفیت
  • اختلال منطقه‌ای
  • توقف موقت مدل
  • تغییر دسترسی حساب
  • افزایش Latency

قیمت مدل‌ها یکسان نیست

قیمت توکن ورودی، خروجی، Cache، تصویر، صوت و ابزارها میان مدل‌ها متفاوت است. استفاده از یک مدل گران برای تمام درخواست‌ها می‌تواند اقتصاد محصول را نامتعادل کند.

نیازهای محصول متفاوت‌اند

یک محصول ممکن است هم‌زمان نیازمند موارد زیر باشد:

  • پاسخ سریع
  • استدلال دقیق
  • تولید کد
  • تحلیل تصویر
  • Embedding
  • تولید تصویر
  • پردازش صوت

معمولاً یک مدل واحد تمام این قابلیت‌ها را با بهترین کیفیت فراهم نمی‌کند.

معماری ساده اتصال مستقیم

در معماری اولیه، کد برنامه مستقیماً SDK یک ارائه‌دهنده را فراخوانی می‌کند:

Application
    ↓
Provider SDK
    ↓
Single Model

نمونۀ ساده:

const response = await provider.chat.completions.create({
  model: "specific-model-version",
  messages,
});

این روش برای Prototype مناسب است، اما با رشد محصول مشکلاتی ایجاد می‌کند:

  • نام مدل در کد ثابت می‌شود.
  • تغییر Provider دشوار است.
  • منطق Retry در چند نقطه تکرار می‌شود.
  • هزینه‌ها به‌شکل پراکنده ثبت می‌شوند.
  • قالب خطا به Provider وابسته می‌ماند.
  • Fallback پیچیده می‌شود.
  • قابلیت‌های مدل در زمان اجرا بررسی نمی‌شوند.

معماری پیشنهادی چندمدلی

معماری مناسب‌تر چند لایه دارد:

Application
    ↓
AI Service Layer
    ↓
Policy and Model Router
    ↓
Provider Adapters
    ↓
Models and Providers

هر لایه مسئولیت مشخصی دارد.

Application

برنامۀ اصلی فقط نوع وظیفه و نیازهای خود را بیان می‌کند:

{
  "task": "extract_invoice",
  "requires_vision": true,
  "requires_json": true,
  "latency_tier": "standard",
  "max_cost_usd": 0.05
}

Application نباید جزئیات Provider را مدیریت کند.

AI Service Layer

رابط داخلی یکپارچه‌ای برای قابلیت‌های هوش مصنوعی فراهم می‌کند:

interface AIService {
  generateText(input: GenerateTextInput): Promise<TextResult>;
  generateObject<T>(input: GenerateObjectInput): Promise<T>;
  createEmbedding(input: EmbeddingInput): Promise<number[]>;
  analyzeImage(input: ImageAnalysisInput): Promise<TextResult>;
}

Policy Engine

قوانین سازمانی و محصول را اعمال می‌کند:

  • مدل‌های مجاز
  • بودجۀ درخواست
  • محدودیت داده
  • Providerهای مجاز
  • موقعیت پردازش
  • سطح کیفیت
  • سطح سرعت
  • محدودیت کاربر
  • قابلیت‌های لازم

Model Router

براساس نیاز درخواست، مدل یا گروه مدل را انتخاب می‌کند.

Provider Adapter

قالب داخلی برنامه را به API هر Provider تبدیل می‌کند و پاسخ را به قرارداد داخلی بازمی‌گرداند.

Observability و Billing

مدل واقعی، Provider، Usage، هزینه، Latency، خطا و Fallback را ثبت می‌کند.

اصل مهم: برنامه باید وظیفه را بداند، نه نام مدل را

در کد محصول بهتر است این درخواست ارسال شود:

await ai.generate({
  task: "customer_support_reply",
  quality: "balanced",
  prompt,
});

نه این درخواست:

await ai.generate({
  model: "provider-specific-model-version-2026-07",
  prompt,
});

در حالت اول، Router می‌تواند مدل واقعی را بدون تغییر کد محصول عوض کند.

Model Alias چیست؟

Model Alias یک نام منطقی و پایدار است که به یک یا چند مدل واقعی نگاشت می‌شود.

نمونه Aliasها:

fast
balanced
reasoning
coding
vision
embedding

نگاشت داخلی:

fast      → Provider A / Economy Model
balanced  → Provider B / General Model
reasoning → Provider C / Reasoning Model
coding    → Provider D / Coding Model
vision    → Provider E / Multimodal Model

مزایای Model Alias

  • مدل واقعی از کد محصول جدا می‌شود.
  • مهاجرت بدون تغییر کد انجام می‌شود.
  • چند Deployment زیر یک نام قرار می‌گیرند.
  • Canary Release ساده‌تر می‌شود.
  • Fallback قابل‌مدیریت می‌شود.
  • مدل‌های هر محیط می‌توانند متفاوت باشند.

Alias براساس وظیفه

به‌جای Alias عمومی می‌توان از Alias دامنه‌ای استفاده کرد:

support-classifier
support-answer
invoice-extractor
product-description
code-reviewer
document-summarizer

این روش برای تیم‌های بزرگ مناسب‌تر است؛ زیرا مدل و Prompt هر وظیفه مستقل مدیریت می‌شوند.

Model Registry چیست؟

Model Registry فهرست متمرکز مدل‌ها و مشخصات آن‌ها است.

نمونۀ اطلاعات هر مدل:

{
  "id": "provider/model-id",
  "aliases": ["balanced", "support-answer"],
  "provider": "provider-a",
  "capabilities": {
    "text": true,
    "vision": false,
    "streaming": true,
    "tools": true,
    "structured_output": true
  },
  "limits": {
    "context_tokens": 128000,
    "max_output_tokens": 16000,
    "rpm": 500,
    "tpm": 1000000
  },
  "pricing": {
    "input_per_million": 2,
    "output_per_million": 10
  },
  "status": "active"
}

Registry باید مرجع انتخاب مدل باشد و اطلاعات آن نسخه‌بندی شود.

قابلیت‌های مدل را صریح نگهداری کنید

نام مدل به‌تنهایی برای تصمیم‌گیری کافی نیست. Router باید بداند مدل از چه قابلیت‌هایی پشتیبانی می‌کند:

  • متن
  • تصویر
  • صوت
  • ویدئو
  • Streaming
  • Tool Calling
  • Parallel Tool Calling
  • Structured Output
  • JSON Mode
  • Embedding
  • Context طولانی
  • زبان فارسی
  • Prompt Caching
  • Batch Processing

برای مثال، درخواست دارای تصویر نباید به مدل Text-only ارسال شود.

فرایند انتخاب مدل

یک Router حرفه‌ای معمولاً این مراحل را طی می‌کند:

  1. نیازهای درخواست را استخراج می‌کند.
  2. مدل‌های فاقد قابلیت لازم را حذف می‌کند.
  3. سیاست‌های سازمانی را اعمال می‌کند.
  4. Context Window را بررسی می‌کند.
  5. مدل‌های ناسالم را حذف می‌کند.
  6. Rate Limit و ظرفیت را بررسی می‌کند.
  7. سقف هزینه را اعمال می‌کند.
  8. کیفیت تاریخی مدل‌ها را در نظر می‌گیرد.
  9. مسیر نهایی را براساس Strategy انتخاب می‌کند.

نمونۀ مفهومی:

تمام مدل‌ها
    ↓
فیلتر قابلیت
    ↓
فیلتر سیاست امنیتی
    ↓
فیلتر Context Window
    ↓
فیلتر سلامت و ظرفیت
    ↓
فیلتر بودجه
    ↓
رتبه‌بندی کیفیت، هزینه و سرعت
    ↓
مدل نهایی

استراتژی‌های مسیریابی

مسیریابی ثابت

هر Alias همیشه به یک مدل مشخص نگاشت می‌شود:

balanced → model-a

ساده‌ترین روش است و برای شروع مناسب است.

مسیریابی براساس وظیفه

classification → economy-model
coding → code-model
complex-analysis → reasoning-model
image-analysis → vision-model

مسیریابی براساس هزینه

ارزان‌ترین مدل سالمی انتخاب می‌شود که تمام قابلیت‌های ضروری را داشته باشد.

این استراتژی برای پردازش‌های حجیم و کم‌ریسک مناسب است، اما نباید کیفیت را نادیده بگیرد.

مسیریابی براساس Latency

مدلی انتخاب می‌شود که در بازۀ اخیر زمان پاسخ کمتری داشته است.

این روش برای چت زنده و قابلیت‌های تعاملی مفید است.

مسیریابی براساس کیفیت

مدل براساس نتایج Evals و عملکرد تاریخی در همان وظیفه انتخاب می‌شود.

مسیریابی براساس ظرفیت

ترافیک به Provider یا Deploymentی ارسال می‌شود که RPM، TPM و ظرفیت بیشتری در اختیار دارد.

مسیریابی وزن‌دار

ترافیک براساس وزن توزیع می‌شود:

Model A: 80%
Model B: 20%

کاربردها:

  • Canary Release
  • A/B Test
  • تقسیم ظرفیت
  • مقایسۀ مدل
  • مهاجرت تدریجی

مسیریابی ترکیبی

در محیط Production معمولاً یک معیار کافی نیست.

فرمول مفهومی:

Score =
Quality Score × Wq
- Cost Score × Wc
- Latency Score × Wl
- Error Rate × We

وزن‌ها باید بر اساس نوع وظیفه تعیین شوند.

نمونه Router ساده با TypeScript

type Capability =
  | "text"
  | "vision"
  | "tools"
  | "structured_output"
  | "streaming";

type ModelConfig = {
  id: string;
  provider: string;
  capabilities: Capability[];
  inputPricePerMillion: number;
  outputPricePerMillion: number;
  qualityScore: number;
  latencyScore: number;
  enabled: boolean;
};

type RouteRequest = {
  requiredCapabilities: Capability[];
  maxInputPricePerMillion?: number;
  prefer: "quality" | "cost" | "latency";
};

const models: ModelConfig[] = [
  {
    id: "MODEL_A",
    provider: "provider-a",
    capabilities: [
      "text",
      "tools",
      "structured_output",
      "streaming",
    ],
    inputPricePerMillion: 2,
    outputPricePerMillion: 10,
    qualityScore: 0.91,
    latencyScore: 0.72,
    enabled: true,
  },
  {
    id: "MODEL_B",
    provider: "provider-b",
    capabilities: ["text", "streaming"],
    inputPricePerMillion: 0.4,
    outputPricePerMillion: 2,
    qualityScore: 0.76,
    latencyScore: 0.94,
    enabled: true,
  },
];

function selectModel(request: RouteRequest): ModelConfig {
  const candidates = models.filter((model) => {
    if (!model.enabled) {
      return false;
    }

    const supportsAll = request.requiredCapabilities.every(
      (capability) =>
        model.capabilities.includes(capability),
    );

    if (!supportsAll) {
      return false;
    }

    if (
      request.maxInputPricePerMillion !== undefined &&
      model.inputPricePerMillion >
        request.maxInputPricePerMillion
    ) {
      return false;
    }

    return true;
  });

  if (candidates.length === 0) {
    throw new Error("No compatible model is available");
  }

  const sorted = [...candidates].sort((a, b) => {
    if (request.prefer === "cost") {
      return (
        a.inputPricePerMillion -
        b.inputPricePerMillion
      );
    }

    if (request.prefer === "latency") {
      return b.latencyScore - a.latencyScore;
    }

    return b.qualityScore - a.qualityScore;
  });

  return sorted[0];
}

این نمونه برای نمایش مفهوم است. Router واقعی باید سلامت، ظرفیت، Context، Tenant، منطقه، Budget و وضعیت Provider را نیز بررسی کند.

Provider Adapter چیست؟

Provider Adapter تفاوت میان API ارائه‌دهندگان را از لایه‌های بالاتر پنهان می‌کند.

رابط داخلی:

type ChatMessage = {
  role: "system" | "user" | "assistant" | "tool";
  content: string;
};

type CompletionRequest = {
  model: string;
  messages: ChatMessage[];
  stream?: boolean;
  temperature?: number;
};

type CompletionResult = {
  text: string;
  model: string;
  provider: string;
  inputTokens?: number;
  outputTokens?: number;
  finishReason?: string;
};

interface ProviderAdapter {
  complete(
    request: CompletionRequest,
  ): Promise<CompletionResult>;
}

هر Provider یک Adapter اختصاصی دارد:

class ProviderAAdapter implements ProviderAdapter {
  async complete(
    request: CompletionRequest,
  ): Promise<CompletionResult> {
    // تبدیل درخواست داخلی به قالب Provider A
    // ارسال درخواست
    // تبدیل پاسخ Provider A به قالب داخلی
    throw new Error("Not implemented");
  }
}

مزیت این الگو آن است که Business Logic به SDK یک شرکت وابسته نمی‌شود.

چرا فقط استانداردسازی درخواست کافی نیست؟

Providerها ممکن است در این موارد تفاوت داشته باشند:

  • ساختار System Prompt
  • قالب Tool Calling
  • نام پارامتر خروجی
  • Structured Output
  • نحوۀ ارسال تصویر
  • Eventهای Streaming
  • Usage
  • Finish Reason
  • Error Body
  • Request ID
  • محدودیت Context
  • Retry Header
  • Tokenizer

Adapter باید علاوه بر درخواست، پاسخ و خطا را نیز استاندارد کند.

استانداردسازی خطاها

کدهای داخلی:

type AIErrorCode =
  | "authentication_error"
  | "permission_denied"
  | "invalid_request"
  | "model_not_found"
  | "rate_limit_exceeded"
  | "context_too_large"
  | "provider_timeout"
  | "provider_unavailable"
  | "content_blocked"
  | "budget_exceeded"
  | "unknown_error";

لایۀ Adapter خطاهای Provider را به این کدها نگاشت می‌کند.

این کار باعث می‌شود Application برای هر Provider منطق جداگانه نداشته باشد.

تفاوت Load Balancing و Model Routing

Load Balancing

درخواست‌ها را میان چند Deployment سازگار از یک مدل یا گروه هم‌سطح توزیع می‌کند.

هدف:

  • استفاده بهتر از ظرفیت
  • جلوگیری از Rate Limit
  • کاهش فشار
  • افزایش دسترس‌پذیری

Model Routing

مدل مناسب را براساس محتوای وظیفه و نیاز محصول انتخاب می‌کند.

هدف:

  • کیفیت
  • قیمت
  • قابلیت
  • سرعت
  • تناسب با وظیفه

ممکن است Router ابتدا گروه مدل را انتخاب کند و سپس Load Balancer یکی از Deploymentهای آن گروه را برگزیند.

استراتژی‌های Load Balancing

Round Robin

درخواست‌ها به‌ترتیب میان مسیرها توزیع می‌شوند.

Weighted Round Robin

به هر مسیر وزن داده می‌شود:

Deployment A: 70%
Deployment B: 30%

Least Busy

مسیری انتخاب می‌شود که درخواست فعال کمتری دارد.

Latency-Based

مسیر با زمان پاسخ پایین‌تر انتخاب می‌شود.

Rate-Limit-Aware

Router وضعیت RPM و TPM را بررسی می‌کند و از مسیر نزدیک به محدودیت فاصله می‌گیرد.

Cost-Based

مسیر اقتصادی‌تر انتخاب می‌شود.

ابزارهایی مانند LiteLLM استراتژی‌های وزن‌دار، مبتنی بر Latency، ظرفیت، هزینه، Fallback، Timeout و Retry را برای چند Deployment ارائه می‌کنند. مستندات رسمی Routing و Load Balancing در LiteLLM

Health Check

Router نباید فقط براساس Config تصمیم بگیرد؛ وضعیت واقعی مقصد نیز باید بررسی شود.

Health Check فعال

سامانه به‌صورت دوره‌ای درخواست آزمایشی ارسال می‌کند.

Health Check غیرفعال

وضعیت براساس درخواست‌های واقعی ثبت می‌شود:

  • نرخ خطا
  • Timeout
  • Latency
  • پاسخ 429
  • خطای اتصال

وضعیت‌های پیشنهادی

healthy
degraded
cooldown
unavailable
disabled

مدلی که در وضعیت cooldown قرار دارد باید برای مدت کوتاهی از چرخۀ انتخاب خارج شود.

Fallback چیست؟

Fallback یعنی اگر مدل یا Provider اصلی نتواند درخواست را پردازش کند، مسیر جایگزین امتحان شود.

زنجیرۀ نمونه:

Primary Deployment
    ↓ خطای موقت
Secondary Deployment of Same Model
    ↓ عدم دسترسی
Equivalent Model
    ↓ شکست
Standard Error Response

LiteLLM نیز Fallback، Cooldown، Timeout و Retry میان Providerها و Deploymentها را به‌عنوان قابلیت‌های Reliability ارائه می‌کند. مستندات رسمی Provider Failover

ترتیب مناسب Fallback

بهتر است مسیر جایگزین به این ترتیب بررسی شود:

  1. Deployment دیگر از همان مدل
  2. Provider دیگر برای همان مدل
  3. مدل هم‌سطح با قابلیت مشابه
  4. مدل ضعیف‌تر با پاسخ محدود
  5. پاسخ Cache‌شده
  6. خطای استاندارد

تغییر مدل باید دیرتر از تغییر Deployment انجام شود؛ زیرا رفتار یک مدل جدید ممکن است متفاوت باشد.

چه خطاهایی باید باعث Fallback شوند؟

معمولاً مناسب:

  • خطای اتصال
  • Timeout
  • 429
  • 500
  • 502
  • 503
  • 504
  • مدل موقتاً در دسترس نیست
  • Provider در وضعیت ناسالم

معمولاً نامناسب:

  • API Key نامعتبر
  • درخواست نامعتبر
  • JSON Schema اشتباه
  • مدل غیرمجاز برای کاربر
  • بودجه تمام‌شده
  • ورودی بیش از حد مجاز
  • نقض سیاست امنیتی

Fallback نباید خطاهای برنامۀ شما را پنهان کند.

Fallback و قابلیت‌های مدل

مدل جایگزین باید حداقل قابلیت‌های ضروری را داشته باشد.

اگر درخواست به این موارد نیاز دارد:

Vision
Tool Calling
Structured Output
128K Context
Streaming

مدل جایگزین نیز باید آن‌ها را پشتیبانی کند.

تنها شباهت قیمت یا کیفیت عمومی کافی نیست.

Fallback و عملیات حساس

برای عملیات غیر Idempotent، Retry یا Fallback می‌تواند باعث تکرار اثر خارجی شود:

  • ایجاد سفارش
  • ارسال پیام
  • کسر موجودی
  • اجرای پرداخت
  • تغییر داده

اگر مدل پیش از خطا Tool Call ایجاد کرده باشد، اجرای دوبارۀ درخواست می‌تواند همان ابزار را دوباره فراخوانی کند.

راهکارها:

  • Idempotency Key
  • ثبت وضعیت Tool Call
  • جلوگیری از اجرای تکراری
  • Transaction
  • تأیید انسانی برای عملیات حساس

Timeout

Timeout باید در چند سطح تعریف شود:

Connection Timeout
Provider Timeout
Model Timeout
Tool Timeout
Total Workflow Timeout

برای مثال:

Connection: 3s
First Token: 10s
Model Completion: 60s
Tool Call: 15s
Total Agent Run: 120s

مقادیر باید براساس نوع مدل و وظیفه تنظیم شوند. مدل استدلالی یا تولید ویدئو ممکن است به زمان بیشتری نیاز داشته باشد.

Retry

Retry باید محدود و هدفمند باشد.

استراتژی مناسب:

تلاش اول
↓ خطای موقت
انتظار با Exponential Backoff و Jitter
↓
تلاش دوم
↓ شکست
Fallback

Retryهای زیاد می‌توانند:

  • هزینه را افزایش دهند.
  • Latency را بالا ببرند.
  • Provider ناسالم را تحت فشار قرار دهند.
  • Retry Storm ایجاد کنند.

Circuit Breaker

اگر یک Provider به‌طور مداوم شکست بخورد، ارسال درخواست بیشتر به آن مفید نیست.

Circuit Breaker سه حالت دارد:

Closed

درخواست‌ها عادی ارسال می‌شوند.

Open

درخواست‌ها بدون تماس با Provider به مسیر جایگزین می‌روند.

Half-Open

تعداد محدودی درخواست آزمایشی برای بررسی بازیابی سرویس ارسال می‌شوند.

معیار باز شدن Circuit می‌تواند ترکیبی از این موارد باشد:

  • نرخ خطا
  • تعداد خطاهای متوالی
  • P95 Latency
  • Timeout
  • پاسخ 429

مدیریت Rate Limit

در معماری چندارائه‌دهنده‌ای باید دو سطح محدودیت کنترل شود.

محدودیت مصرف‌کننده

  • RPM هر API Key
  • TPM هر کاربر
  • بودجۀ پروژه
  • تعداد درخواست هم‌زمان

محدودیت Provider

  • RPM حساب
  • TPM مدل
  • محدودیت منطقه
  • ظرفیت Deployment
  • تعداد اتصال Streaming

Router باید مسیرهایی را که نزدیک محدودیت‌اند موقتاً از اولویت خارج کند.

چرا شمارندۀ توزیع‌شده لازم است؟

اگر Router در چند Instance اجرا شود، حافظۀ محلی برای شمارش RPM کافی نیست.

Gateway Instance A
Gateway Instance B
Gateway Instance C

تمام Instanceها باید وضعیت مشترکی از ظرفیت و Rate Limit داشته باشند. یک Store سریع و اشتراکی می‌تواند شمارنده‌های RPM، TPM، Cooldown و اتصال‌های فعال را نگهداری کند.

مدیریت Context Window

پیش از انتخاب مدل باید اندازۀ ورودی تخمین زده شود:

System Prompt
+ Messages
+ Tool Definitions
+ RAG Context
+ Image Tokens
+ Output Budget

شرط انتخاب:

Estimated Input
+ Reserved Output
≤ Model Context Window

اگر ورودی بیش از ظرفیت باشد، Router می‌تواند:

  • مدل با Context بزرگ‌تر انتخاب کند.
  • تاریخچه را خلاصه کند.
  • RAG Context را کاهش دهد.
  • پیام‌های قدیمی را حذف کند.
  • درخواست را با خطای مشخص رد کند.

نباید ورودی بدون اطلاع کاربر به‌شکل تصادفی Truncate شود.

تفاوت Tokenizerها

متن یکسان ممکن است در مدل‌های مختلف تعداد توکن متفاوتی داشته باشد. این تفاوت در زبان فارسی، کد، JSON و متن چندزبانه می‌تواند محسوس باشد.

به همین دلیل:

  • تخمین Context باید محافظه‌کارانه باشد.
  • Billing باید براساس Usage مسیر واقعی انجام شود.
  • تغییر مدل می‌تواند هزینه را حتی با قیمت مشابه تغییر دهد.
  • تست باید با داده واقعی فارسی انجام شود.

Structured Output در معماری چندمدلی

مدل‌ها در پشتیبانی از JSON و JSON Schema یکسان نیستند.

سطوح مختلف:

  • Prompt برای تولید JSON
  • JSON Mode
  • Structured Output
  • Schema Enforcement
  • Tool Calling با Schema

Router باید مشخص کند درخواست به کدام سطح نیاز دارد.

برای مثال:

{
  "requires_valid_json": true,
  "requires_schema_enforcement": true
}

مدلی که فقط JSON Mode دارد نباید به‌عنوان جایگزین کامل مدلی با Schema Enforcement در نظر گرفته شود.

خروجی همیشه باید در Application اعتبارسنجی شود.

Tool Calling در معماری چندمدلی

تفاوت مدل‌ها می‌تواند شامل موارد زیر باشد:

  • قالب تعریف ابزار
  • Parallel Tool Calls
  • طول توضیح ابزار
  • نحوۀ بازگرداندن Tool Result
  • پشتیبانی از Tool Choice
  • دقت انتخاب ابزار
  • شکل آرگومان‌ها

Adapter باید ساختارها را استاندارد کند، اما کیفیت Tool Calling فقط با تبدیل Schema حل نمی‌شود. مدل جایگزین باید با ابزارهای واقعی محصول آزمایش شود.

استانداردسازی Streaming

Providerها ممکن است رویدادهای متفاوتی ارسال کنند:

  • Text Delta
  • Tool Call Delta
  • Usage
  • Reasoning Event
  • Finish Event
  • Error Event

لایۀ داخلی بهتر است رویدادهای استاندارد داشته باشد:

type AIStreamEvent =
  | { type: "text_delta"; text: string }
  | {
      type: "tool_call_delta";
      callId: string;
      data: string;
    }
  | {
      type: "usage";
      inputTokens: number;
      outputTokens: number;
    }
  | {
      type: "completed";
      finishReason: string;
    }
  | {
      type: "error";
      code: string;
      message: string;
    };

Application فقط این قرارداد را پردازش می‌کند.

قطع Streaming

اگر کاربر ارتباط را قطع کند، درخواست Provider نیز باید در صورت امکان لغو شود.

در غیر این صورت:

  • تولید ادامه پیدا می‌کند.
  • هزینه افزایش می‌یابد.
  • اتصال و Worker اشغال می‌شوند.
  • Usage بدون مصرف کاربر ایجاد می‌شود.

Abort باید از کلاینت تا Provider منتقل شود.

Billing در معماری چندارائه‌دهنده‌ای

Billing باید مسیر واقعی را ثبت کند، نه فقط مدلی که Application درخواست کرده است.

اطلاعات لازم:

requested_alias
requested_model
actual_model
provider
deployment
input_tokens
cached_input_tokens
output_tokens
reasoning_tokens
retry_count
fallback_count
provider_cost
final_charge
pricing_version

اگر Alias balanced به یک مدل واقعی نگاشت شده باشد، گزارش هزینه باید هر دو را ثبت کند.

هزینه Retry و Fallback

فرض کنید درخواست ابتدا به Provider A ارسال شود و پس از مصرف بخشی از منابع شکست بخورد؛ سپس Provider B پاسخ را کامل کند.

هزینۀ نهایی =
مصرف Provider A
+ مصرف Provider B

هزینه Provider اول همیشه صفر نیست. Billing باید Usage هر Attempt را جدا ثبت کند.

ساختار Attempt

{
  "request_id": "req_123",
  "attempt": 2,
  "requested_alias": "balanced",
  "actual_model": "provider-b/model-y",
  "provider": "provider-b",
  "status": "success",
  "input_tokens": 4000,
  "output_tokens": 700,
  "latency_ms": 1300,
  "cost_usd": 0.018
}

یک Request می‌تواند چند Attempt داشته باشد، اما Charge نهایی باید با Request ID مشخص و Idempotent باشد.

امنیت API Keyهای Provider

در معماری Multi-Provider تعداد Secretهای بالادستی افزایش می‌یابد.

کلیدها نباید در این محل‌ها قرار گیرند:

  • Repository
  • فایل Config عمومی
  • Frontend
  • لاگ
  • Error Response
  • Prompt
  • Analytics
  • Dashboard عمومی

راهکارها:

  • Secret Manager
  • Rotation
  • دسترسی حداقلی
  • جداسازی محیط‌ها
  • Audit Log
  • رمزنگاری
  • محدودیت IP در صورت پشتیبانی
  • کلید جدا برای هر Provider و محیط

Application نباید به API Keyهای Provider دسترسی مستقیم داشته باشد. فقط Gateway یا Adapter Layer باید آن‌ها را دریافت کند.

جداسازی Tenantها

در سیستم چندسازمانی باید سیاست‌های هر Tenant جدا باشند:

  • مدل‌های مجاز
  • Providerهای مجاز
  • بودجه
  • Rate Limit
  • Region
  • نگهداری لاگ
  • Prompt
  • API Key
  • داده و Cache

Cache مشترک نباید باعث نشت پاسخ یا اطلاعات میان سازمان‌ها شود.

حریم خصوصی و محل پردازش داده

برخی سازمان‌ها ممکن است محدودیت داشته باشند:

  • داده فقط در Region مشخص پردازش شود.
  • Prompt ذخیره نشود.
  • Provider خاصی مجاز نباشد.
  • مدل متن‌باز خصوصی استفاده شود.
  • اطلاعات شخصی حذف شوند.

این الزامات باید پیش از امتیازدهی هزینه و Latency اعمال شوند:

ابتدا Policy و Compliance
سپس Optimization

ارزان‌تر بودن یک Provider مجوز نقض سیاست داده نیست.

Observability

برای هر درخواست این اطلاعات را ثبت کنید:

  • Request ID
  • Trace ID
  • Tenant
  • Task
  • Alias
  • مدل واقعی
  • Provider
  • Deployment
  • تعداد Attempt
  • Fallback
  • Latency
  • Time to First Token
  • Input Token
  • Output Token
  • هزینه
  • Error Code
  • Finish Reason

متریک‌های Router

  • نرخ انتخاب هر مدل
  • نرخ انتخاب هر Provider
  • Fallback Rate
  • Retry Rate
  • Error Rate
  • P50 Latency
  • P95 Latency
  • P99 Latency
  • Time to First Token
  • هزینه هر Request
  • هزینه هر نتیجۀ موفق
  • نرخ Structured Output معتبر
  • نرخ Tool Call موفق
  • نرخ پاسخ پذیرفته‌شده

چرا میانگین کافی نیست؟

ممکن است متوسط Latency مناسب باشد، اما P99 بسیار بالا باشد. همچنین متوسط هزینه می‌تواند رفتار تعداد کمی درخواست بسیار گران را پنهان کند.

بهتر است توزیع هزینه و Latency بررسی شود:

P50
P90
P95
P99
Maximum

Evals چیست؟

Eval یک آزمون ساختاریافته برای اندازه‌گیری عملکرد مدل در وظایف واقعی محصول است.

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

{
  "input": "پیام مشتری",
  "expected_category": "billing",
  "expected_priority": "high"
}

یا برای پاسخ آزاد:

  • Rubric
  • Reference Answer
  • معیار صحت
  • معیار کامل بودن
  • معیار رعایت قالب
  • امتیاز انسانی

راهنمای رسمی OpenAI نیز Evals را برای آزمون و مقایسۀ خروجی‌ها در سناریوهای تعریف‌شده ارائه می‌کند. راهنمای رسمی Evals

چرا Benchmark عمومی کافی نیست؟

Benchmark عمومی ممکن است توانایی کلی مدل را نشان دهد، اما الزاماً با کاربرد شما یکسان نیست.

برای مثال:

  • کیفیت پاسخ فارسی
  • استخراج فاکتور ایرانی
  • طبقه‌بندی تیکت‌های محصول شما
  • تولید کد با Stack مشخص
  • پاسخ براساس اسناد داخلی
  • استفاده صحیح از ابزارهای اختصاصی

باید با داده‌های واقعی محصول ارزیابی شوند.

Dataset ارزیابی

Dataset مناسب باید شامل موارد زیر باشد:

  • نمونه‌های عادی
  • نمونه‌های دشوار
  • ورودی فارسی
  • ورودی چندزبانه
  • Prompt Injection
  • داده ناقص
  • ورودی طولانی
  • قالب نامعتبر
  • موارد مرزی
  • خطاهای واقعی گذشته

داده حساس باید پیش از استفاده در Eval ناشناس‌سازی شود.

معیارهای ارزیابی مدل

معیارهای کیفیت

  • Accuracy
  • F1 Score
  • Exact Match
  • JSON Validity
  • Schema Compliance
  • Citation Correctness
  • Tool Selection Accuracy
  • Human Rating

معیارهای عملیاتی

  • Latency
  • Time to First Token
  • Error Rate
  • Rate Limit
  • Fallback Rate

معیارهای اقتصادی

  • هزینه هر درخواست
  • هزینه هر پاسخ معتبر
  • هزینه هر Tool Call موفق
  • هزینه هر نتیجۀ پذیرفته‌شده

مدلی که کیفیت بالاتری دارد اما بسیار گران است، ممکن است برای تمام ترافیک مناسب نباشد.

فرمول انتخاب مدل براساس نتیجه موفق

معیار مفید:

Cost per Successful Result =
Total Model Cost
÷ Number of Valid Results

مثال:

مدلهزینۀ ۱۰۰۰ درخواستپاسخ معتبرهزینه هر پاسخ معتبر
مدل A۱۰ دلار۶۵۰۰٫۰۱۵۴ دلار
مدل B۱۸ دلار۹۵۰۰٫۰۱۸۹ دلار
مدل C۳۰ دلار۹۸۰۰٫۰۳۰۶ دلار

مدل B ممکن است برای محصولی که دقت بالا نیاز دارد بهترین تعادل باشد.

Model Selection Matrix

وظیفهاولویت اصلیقابلیت ضروریمدل پیشنهادی
طبقه‌بندی پیامهزینه و سرعتStructured Outputمدل اقتصادی
پاسخ پشتیبانیکیفیت و لحنContext و فارسیمدل متعادل
تحلیل قرارداددقتContext طولانیمدل قدرتمند
تولید کدکیفیت کدTool Callingمدل کدنویسی
بررسی تصویردرک بصریVisionمدل چندوجهی
Agentپایداری ابزارTool Callingمدل Agent مناسب
Embeddingکیفیت بازیابیبردار پایدارمدل Embedding

Canary Release مدل جدید

مدل جدید نباید یک‌باره جایگزین مدل Production شود.

فرایند پیشنهادی:

  1. اجرای Eval آفلاین
  2. اجرای Shadow Traffic
  3. ارسال ۱ درصد ترافیک
  4. مقایسۀ کیفیت و خطا
  5. افزایش به ۵ درصد
  6. افزایش به ۲۰ درصد
  7. انتشار کامل یا Rollback

Shadow Traffic

در Shadow Mode، درخواست واقعی به مدل جدید نیز ارسال می‌شود، اما پاسخ آن به کاربر نمایش داده نمی‌شود.

مزایا:

  • ارزیابی روی داده واقعی
  • بدون اثر بر تجربۀ کاربر
  • اندازه‌گیری هزینه و Latency
  • کشف خطاهای پیش‌بینی‌نشده

Shadow Traffic هزینه اضافه ایجاد می‌کند و باید داده‌های حساس و رضایت کاربران در آن لحاظ شوند.

A/B Test

در A/B Test، کاربران مختلف پاسخ مدل‌های متفاوت را مشاهده می‌کنند.

معیارها:

  • رضایت کاربر
  • نرخ پذیرش پاسخ
  • نرخ اصلاح
  • نرخ تبدیل
  • مدت تعامل
  • هزینه
  • Latency
  • شکایت یا خطا

Assignment باید پایدار باشد تا یک کاربر در طول یک مکالمه بین مدل‌ها جابه‌جا نشود.

Versioning مدل و Prompt

نتیجۀ سیستم فقط به مدل وابسته نیست:

Result =
Model
+ Prompt
+ Tools
+ Retrieval
+ Parameters
+ Provider Behavior

بنابراین باید هم مدل و هم Prompt نسخه‌بندی شوند:

model_policy_version: 12
prompt_version: support-v7
tool_schema_version: 4

بدون Versioning نمی‌توان علت تغییر کیفیت را تشخیص داد.

Prompt Portability

Prompt یک مدل ممکن است روی مدل دیگر همان رفتار را نداشته باشد.

تفاوت‌ها:

  • میزان پیروی از System Prompt
  • حساسیت به ترتیب دستورها
  • نیاز به مثال
  • قالب Tool Calling
  • زبان فارسی
  • طول پاسخ
  • رفتار در ابهام
  • سیاست ایمنی

قبل از تغییر مدل باید Prompt Regression Test اجرا شود.

Auto Router مبتنی بر مدل

برخی Routerها برای انتخاب مدل، ابتدا درخواست را با یک Classifier یا مدل کوچک تحلیل می‌کنند.

جریان:

Request
    ↓
Task Classifier
    ↓
Model Selection
    ↓
Selected Model

مزیت:

  • تصمیم انعطاف‌پذیرتر

معایب:

  • یک فراخوانی اضافه
  • Latency بیشتر
  • هزینه بیشتر
  • احتمال خطای Classifier
  • پیچیدگی عیب‌یابی

برای وظایف مشخص، Rule-based Routing ممکن است ساده‌تر و قابل‌اعتمادتر باشد.

Rule-Based یا AI-Based Routing؟

معیارRule-BasedAI-Based
پیش‌بینی‌پذیریبالاکمتر
هزینه اضافیکمبیشتر
Latencyکمتربیشتر
انعطاف‌پذیریمتوسطبالا
عیب‌یابیسادهپیچیده‌تر
مناسب برایوظایف مشخصورودی‌های متنوع

معماری ترکیبی معمولاً مناسب است:

  1. قواعد قطعی قابلیت و امنیت
  2. Classifier برای تشخیص وظیفه
  3. Scoring برای انتخاب نهایی

Semantic Router

Semantic Router می‌تواند با Embedding، ورودی را به دسته‌های معنایی نزدیک کند:

پرسش برنامه‌نویسی → coding
پرسش مالی → finance-safe
تحلیل تصویر → vision
مکالمۀ عمومی → balanced

برای این روش باید:

  • Threshold تعریف شود.
  • مسیر پیش‌فرض وجود داشته باشد.
  • دسته‌های مبهم مدیریت شوند.
  • Dataset فارسی آزمایش شود.
  • هزینه Embedding در نظر گرفته شود.

معماری پیشنهادی Production

Client Applications
        ↓
Authentication and Rate Limit
        ↓
AI Service Layer
        ↓
Policy Engine
        ↓
Model Router
        ↓
Provider Adapters
        ↓
AI Gateway
        ↓
Models and Providers

اجزای جانبی:

  • Model Registry
  • Secret Manager
  • Distributed Rate Limiter
  • Usage Store
  • Billing Ledger
  • Metrics
  • Logs
  • Tracing
  • Eval Pipeline
  • Configuration Store
  • Alerting

مدل داده پیشنهادی

جدول مدل‌ها

CREATE TABLE ai_models (
    id UUID PRIMARY KEY,
    model_id TEXT NOT NULL,
    provider_id UUID NOT NULL,
    model_group TEXT NOT NULL,
    capabilities JSONB NOT NULL,
    pricing JSONB NOT NULL,
    context_window BIGINT,
    status TEXT NOT NULL,
    config_version INTEGER NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

جدول تلاش‌های درخواست

CREATE TABLE ai_request_attempts (
    id UUID PRIMARY KEY,
    request_id UUID NOT NULL,
    attempt_number INTEGER NOT NULL,
    requested_alias TEXT NOT NULL,
    actual_model TEXT NOT NULL,
    provider_id UUID NOT NULL,
    status TEXT NOT NULL,
    latency_ms INTEGER,
    input_tokens BIGINT DEFAULT 0,
    output_tokens BIGINT DEFAULT 0,
    cost_usd NUMERIC(20, 10),
    error_code TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (request_id, attempt_number)
);

نمونۀ سرویس چندمدلی با Node.js و درواره

API درواره رابط سازگار با OpenAI ارائه می‌کند:

https://api.darvareh.ir/v1

ساخت Client:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.DARVAREH_API_KEY,
  baseURL: "https://api.darvareh.ir/v1",
});

تعریف Policy:

const modelPolicy = {
  fast: {
    primary: "FAST_MODEL_ID",
    fallback: ["FAST_FALLBACK_MODEL_ID"],
  },
  balanced: {
    primary: "BALANCED_MODEL_ID",
    fallback: ["BALANCED_FALLBACK_MODEL_ID"],
  },
  reasoning: {
    primary: "REASONING_MODEL_ID",
    fallback: ["REASONING_FALLBACK_MODEL_ID"],
  },
  vision: {
    primary: "VISION_MODEL_ID",
    fallback: ["VISION_FALLBACK_MODEL_ID"],
  },
};

تابع تشخیص خطای قابل‌تلاش:

function isRetryableError(error) {
  const status = error?.status;

  return (
    status === 408 ||
    status === 429 ||
    status === 500 ||
    status === 502 ||
    status === 503 ||
    status === 504
  );
}

تابع اجرای مدل:

async function callModel({
  model,
  messages,
  signal,
}) {
  const startedAt = Date.now();

  const response =
    await client.chat.completions.create(
      {
        model,
        messages,
      },
      {
        signal,
      },
    );

  return {
    text:
      response.choices[0]?.message?.content ?? "",
    model: response.model,
    inputTokens:
      response.usage?.prompt_tokens ?? 0,
    outputTokens:
      response.usage?.completion_tokens ?? 0,
    latencyMs: Date.now() - startedAt,
  };
}

اجرای Fallback:

async function generateWithFallback({
  modelGroup,
  messages,
  signal,
}) {
  const policy = modelPolicy[modelGroup];

  if (!policy) {
    throw new Error(
      `Unknown model group: ${modelGroup}`,
    );
  }

  const candidates = [
    policy.primary,
    ...policy.fallback,
  ];

  const attempts = [];

  for (const model of candidates) {
    const startedAt = Date.now();

    try {
      const result = await callModel({
        model,
        messages,
        signal,
      });

      attempts.push({
        model,
        status: "success",
        latencyMs: result.latencyMs,
        inputTokens: result.inputTokens,
        outputTokens: result.outputTokens,
      });

      return {
        ...result,
        attempts,
      };
    } catch (error) {
      attempts.push({
        model,
        status: "failed",
        latencyMs: Date.now() - startedAt,
        statusCode: error?.status,
        message: error?.message,
      });

      if (!isRetryableError(error)) {
        throw Object.assign(error, { attempts });
      }
    }
  }

  const finalError = new Error(
    "All compatible models failed",
  );

  finalError.attempts = attempts;
  throw finalError;
}

استفاده:

const result = await generateWithFallback({
  modelGroup: "balanced",
  messages: [
    {
      role: "system",
      content: "پاسخ را دقیق و فارسی بنویس.",
    },
    {
      role: "user",
      content: "معماری چندمدلی چیست؟",
    },
  ],
});

console.log(result.text);
console.log(result.attempts);

شناسه‌های نمونه باید با Model IDهای واقعی موجود در کاتالوگ درواره جایگزین شوند.

انتخاب گروه مدل براساس وظیفه

function classifyTask({
  hasImage,
  requiresReasoning,
  requiresCode,
  expectedOutputTokens,
}) {
  if (hasImage) {
    return "vision";
  }

  if (requiresReasoning) {
    return "reasoning";
  }

  if (requiresCode) {
    return "coding";
  }

  if (expectedOutputTokens < 300) {
    return "fast";
  }

  return "balanced";
}

در Production، تشخیص وظیفه باید با داده واقعی و قواعد دقیق‌تر انجام شود.

نمونه درخواست مستقیم به درواره

curl "https://api.darvareh.ir/v1/chat/completions" \
  -H "Authorization: Bearer $DARVAREH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "messages": [
      {
        "role": "system",
        "content": "شما یک معمار نرم‌افزار حرفه‌ای هستید."
      },
      {
        "role": "user",
        "content": "برای یک چت‌بات پرترافیک معماری چندمدلی پیشنهاد بده."
      }
    ]
  }'

نقش درواره در معماری چندمدلی

ساخت زیرساخت Multi-Provider از ابتدا نیازمند مدیریت مجموعه بزرگی از مسائل است:

  • اتصال به چند Provider
  • نگهداری API Keyها
  • استانداردسازی درخواست
  • تبدیل پاسخ
  • مدیریت خطا
  • Streaming
  • Billing
  • قیمت مدل‌ها
  • گزارش مصرف
  • Rate Limit
  • Fallback
  • پایش Provider
  • تغییر مدل
  • امنیت
  • پرداخت

درواره بخشی از این پیچیدگی را در لایۀ AI Gateway یکپارچه می‌کند.

توسعه‌دهنده به‌جای اتصال مستقیم به چند ارائه‌دهنده، از یک Base URL استفاده می‌کند:

https://api.darvareh.ir/v1

و مدل را از طریق Model ID انتخاب می‌کند.

مزایای این رویکرد:

  • یک API Key
  • کیف پول ریالی
  • API سازگار با OpenAI
  • دسترسی به صدها مدل
  • کاتالوگ مدل‌ها
  • گزارش مصرف
  • Playground
  • مدیریت متمرکز هزینه
  • کاهش پیچیدگی اتصال
  • امکان آزمایش مدل‌های مختلف

درواره منطق دامنه‌ای محصول شما را تعیین نمی‌کند. تیم شما همچنان باید مشخص کند چه وظیفه‌ای به چه گروه مدلی نیاز دارد؛ اما لایۀ اتصال به مدل‌ها یکپارچه‌تر می‌شود.

معماری پیشنهادی با درواره

Application
    ↓
Internal Task Router
    ↓
Darvareh OpenAI-Compatible API
    ↓
Selected Model

Application وظیفه را تشخیص می‌دهد، Router داخلی Model ID مناسب را انتخاب می‌کند و درخواست از طریق درواره ارسال می‌شود.

این روش برای شروع ساده‌تر از نگهداری Adapter جداگانه برای هر Provider است.

چه زمانی Router داخلی لازم است؟

Router داخلی زمانی مفید است که:

  • وظایف مشخصی دارید.
  • برای هر وظیفه چند مدل آزمایش کرده‌اید.
  • بودجه هر نوع درخواست متفاوت است.
  • برخی کاربران پلن کیفیت بالاتر دارند.
  • ورودی‌ها گاهی تصویر دارند.
  • Agent و Tool Calling استفاده می‌کنید.
  • می‌خواهید مدل‌ها را بدون تغییر کد جابه‌جا کنید.

چه زمانی انتخاب مستقیم مدل کافی است؟

اگر:

  • پروژه در مرحلۀ آزمایشی است.
  • فقط یک وظیفۀ مشخص دارید.
  • ترافیک کم است.
  • مدل مناسب مشخص شده است.
  • نیاز به Routing پویا ندارید.

می‌توانید Model ID را در Config قرار دهید و بعداً Router اضافه کنید.

اشتباهات رایج

پخش کردن نام مدل در تمام کد

Model ID باید در Config یا Registry باشد.

انتخاب مدل فقط براساس قیمت

هزینه هر پاسخ معتبر مهم‌تر از قیمت خام توکن است.

Fallback میان مدل‌های ناسازگار

مدل جایگزین باید قابلیت‌های ضروری را داشته باشد.

Retry برای تمام خطاها

خطاهای ورودی، مجوز و بودجه با Retry حل نمی‌شوند.

ثبت نکردن Provider واقعی

برای Billing و عیب‌یابی باید مسیر واقعی ثبت شود.

تغییر مدل بدون Eval

مدل جدید ممکن است در Benchmark عمومی قوی باشد، اما در وظیفۀ شما ضعیف‌تر عمل کند.

اعتماد به Structured Output بدون اعتبارسنجی

خروجی باید در Application با Schema بررسی شود.

استفاده از مدل استدلالی برای تمام درخواست‌ها

این کار می‌تواند هزینه و Latency را غیرضروری افزایش دهد.

نبود سقف Agent

Agent بدون محدودیت می‌تواند وارد Loop شود و چندین فراخوانی پرهزینه انجام دهد.

Routing براساس محتوای حساس بدون Policy

قواعد امنیت و محل پردازش باید پیش از Optimization اعمال شوند.

Cache مشترک میان Tenantها

Cache Key باید Tenant، مدل، Prompt Version و پارامترها را در نظر بگیرد.

چک‌لیست طراحی معماری چندمدلی

  • وظایف اصلی محصول مشخص شده‌اند.
  • برای هر وظیفه معیار کیفیت تعریف شده است.
  • مدل‌ها در Registry نگهداری می‌شوند.
  • کد محصول از Model ID واقعی مستقل است.
  • Model Alias یا Task Alias تعریف شده است.
  • قابلیت‌های هر مدل ثبت شده‌اند.
  • قیمت و Context Window ثبت شده‌اند.
  • Provider Adapter یا Gateway وجود دارد.
  • خطاها استاندارد شده‌اند.
  • Timeout برای هر مسیر تعریف شده است.
  • Retry محدود و هدفمند است.
  • Fallback فقط میان مدل‌های سازگار انجام می‌شود.
  • Circuit Breaker وجود دارد.
  • Rate Limit توزیع‌شده مدیریت می‌شود.
  • Provider و مدل واقعی ثبت می‌شوند.
  • Usage هر Attempt ثبت می‌شود.
  • Billing با Request ID انجام می‌شود.
  • API Keyها در Secret Manager هستند.
  • Tenantها از هم جدا هستند.
  • Dataset ارزیابی واقعی وجود دارد.
  • مدل جدید ابتدا Canary می‌شود.
  • Prompt و Model Policy نسخه‌بندی می‌شوند.
  • امکان Rollback سریع وجود دارد.
  • هزینه هر نتیجۀ موفق محاسبه می‌شود.
  • P95 و P99 Latency مانیتور می‌شوند.

پرسش‌های متداول

معماری چندمدلی چیست؟

معماری چندمدلی روشی است که در آن نرم‌افزار براساس نوع وظیفه، کیفیت، قیمت، سرعت یا قابلیت موردنیاز از چند مدل هوش مصنوعی استفاده می‌کند.

Multi-Provider چیست؟

Multi-Provider یعنی یک سیستم به بیش از یک ارائه‌دهنده یا مسیر زیرساختی متصل باشد تا ظرفیت، دسترس‌پذیری و انعطاف بیشتری داشته باشد.

تفاوت Multi-Model و Multi-Provider چیست؟

Multi-Model به تنوع مدل‌ها و توانایی‌های آن‌ها اشاره دارد. Multi-Provider به تنوع مسیرهای ارائه و زیرساخت دسترسی مربوط است.

آیا یک مدل برای تمام وظایف کافی نیست؟

در Prototype ممکن است کافی باشد، اما در محصول واقعی معمولاً وظایف از نظر کیفیت، هزینه، سرعت و قابلیت تفاوت دارند.

Model Alias چیست؟

نام منطقی و پایداری مانند fast یا reasoning است که در پشت صحنه به یک یا چند مدل واقعی نگاشت می‌شود.

Model Router چیست؟

لایه‌ای است که نیازهای درخواست را بررسی و مدل مناسب را انتخاب می‌کند.

تفاوت Router و Load Balancer چیست؟

Router گروه یا مدل مناسب را انتخاب می‌کند. Load Balancer درخواست را میان چند Deployment از مدل یا گروه انتخاب‌شده توزیع می‌کند.

Fallback چیست؟

انتقال درخواست به مسیر جایگزین در صورت بروز خطای موقت یا عدم دسترسی مسیر اصلی است.

آیا Fallback همیشه باید به مدل دیگری برود؟

خیر. بهتر است ابتدا Deployment یا Provider دیگری از همان مدل امتحان شود و سپس مدل هم‌سطح انتخاب شود.

آیا Fallback هزینه را افزایش می‌دهد؟

ممکن است. اگر مسیر اول بخشی از درخواست را پردازش کرده باشد، مصرف آن نیز می‌تواند محاسبه شود.

چگونه بهترین مدل را انتخاب کنیم؟

با Dataset واقعی محصول، معیارهای کیفیت، هزینه، Latency و نرخ موفقیت را اندازه‌گیری کنید. Benchmark عمومی به‌تنهایی کافی نیست.

Evals چیست؟

مجموعه آزمون‌های ساختاریافته برای سنجش کیفیت مدل در وظایف واقعی محصول است.

آیا ارزان‌ترین مدل بهترین انتخاب است؟

خیر. معیار مناسب، هزینه هر نتیجۀ موفق و قابل‌استفاده است.

آیا Router هوشمند به مدل جدا نیاز دارد؟

نه همیشه. وظایف مشخص را می‌توان با قواعد قطعی مسیریابی کرد. برای ورودی‌های متنوع می‌توان از Classifier یا Semantic Router استفاده کرد.

آیا معماری چندمدلی Latency را افزایش می‌دهد؟

اگر Routing سبک و مبتنی بر Config باشد، افزایش Latency محدود است. Routing مبتنی بر فراخوانی مدل یا Storeهای متعدد می‌تواند تأخیر بیشتری ایجاد کند.

آیا درواره یک Model Router است؟

درواره یک AI API Gateway و لایۀ اتصال یکپارچه به مدل‌های مختلف است. برنامه می‌تواند مدل را با Model ID انتخاب کند و منطق Task Routing خود را در Backend پیاده‌سازی کند.

Base URL درواره چیست؟

https://api.darvareh.ir/v1

آیا می‌توان با SDK رسمی OpenAI به درواره متصل شد؟

برای قابلیت‌های سازگار، بله. کافی است API Key و Base URL درواره را در Client تنظیم کنید.

آیا می‌توان بدون ساخت چند Adapter از چند مدل استفاده کرد؟

استفاده از یک API Gateway سازگار مانند درواره می‌تواند نیاز به Adapter مستقیم برای هر Provider را کاهش دهد.

آیا Prompt در مدل‌های مختلف یکسان عمل می‌کند؟

خیر. Prompt باید برای مدل‌های جایگزین آزمایش و Regression Test شود.

چگونه مدل جدید را منتشر کنیم؟

ابتدا Eval آفلاین، سپس Shadow Traffic، Canary محدود و در نهایت انتشار تدریجی انجام دهید.

آیا Tool Calling میان مدل‌ها سازگار است؟

ساختار API ممکن است قابل‌استانداردسازی باشد، اما دقت انتخاب ابزار و تولید آرگومان‌ها متفاوت است و باید آزمایش شود.

جمع‌بندی

معماری چندمدلی هوش مصنوعی به نرم‌افزار اجازه می‌دهد برای هر وظیفه از مدل مناسب استفاده کند و وابستگی خود را به یک مدل یا ارائه‌دهنده کاهش دهد.

یک معماری حرفه‌ای شامل اجزای زیر است:

  • AI Service Layer
  • Policy Engine
  • Model Registry
  • Model Router
  • Provider Adapter
  • Load Balancer
  • Fallback
  • Circuit Breaker
  • Observability
  • Billing
  • Eval Pipeline

اصل اساسی این معماری آن است که Application باید نیاز خود را بیان کند، نه نام فنی یک مدل خاص را.

وظیفه
→ قابلیت لازم
→ سیاست
→ مدل مناسب
→ Provider سالم
→ پاسخ استاندارد

مدل‌ها باید براساس داده واقعی محصول ارزیابی شوند. قیمت خام توکن، Benchmark عمومی یا شهرت مدل برای تصمیم Production کافی نیست. معیارهای کیفیت، هزینه هر نتیجۀ موفق، Latency، پایداری و سازگاری قابلیت‌ها باید هم‌زمان بررسی شوند.

درواره با فراهم کردن یک API یکپارچه، کیف پول ریالی، کاتالوگ مدل، گزارش مصرف و رابط سازگار با OpenAI، اتصال به مدل‌های مختلف را برای توسعه‌دهندگان ایرانی ساده‌تر می‌کند.

برای شروع:

  1. در درواره ثبت‌نام کنید.
  2. API Key بسازید.
  3. مدل‌های موردنظر را از کاتالوگ انتخاب کنید.
  4. آن‌ها را با Dataset واقعی خود آزمایش کنید.
  5. Model Policy و Fallback را در Backend تعریف کنید.
  6. Base URL را روی آدرس زیر قرار دهید:
https://api.darvareh.ir/v1
یک مدل برای تمام وظایف بهترین نیست؛ معماری درست باید بتواند برای هر درخواست، مدل مناسب را انتخاب کند.

مقالات مرتبط پیشنهادی

Read more