كيف تقلل تكلفة AI API في Laravel؟ دليل شامل لخفض استهلاك Tokens وتكاليف الذكاء الاصطناعي

عند بناء أول ميزة تعتمد على الذكاء الاصطناعي داخل تطبيق Laravel، تكون البداية غالبًا بسيطة جدًا:

$response = (new SupportAgent)
    ->prompt($message);

تعمل الميزة، تحصل على نتيجة جيدة، ثم تنتقل إلى Production.

لكن مع نمو التطبيق يبدأ عدد المستخدمين والطلبات بالارتفاع:

100 مستخدم
1,000 مستخدم
10,000 مستخدم
100,000 مستخدم

وهنا يظهر السؤال الذي يواجه تقريبًا كل تطبيق AI ناجح:

لماذا ترتفع فاتورة الـ AI بهذه السرعة، وكيف يمكن خفضها دون التضحية بجودة النتائج؟

في كثير من الحالات، المشكلة ليست أن خدمات الذكاء الاصطناعي غالية بطبيعتها، بل أن بنية التطبيق لم تُصمم منذ البداية للتفريق بين مهمة بسيطة يمكن تنفيذها بنموذج صغير، ومهمة تحتاج فعلًا إلى نموذج قوي.

قد تكتشف مثلًا أنك تستخدم أقوى Model لديك لمعرفة هل الرسالة:

positive
neutral
negative

أو أنك ترسل محادثة تحتوي على 150 رسالة في كل Request لكي تجيب عن سؤال بسيط مثل:

متى ينتهي اشتراكي؟

أو تعيد إنشاء نفس Embedding عشرات أو آلاف المرات رغم أن النص لم يتغير.

أو تسمح للنموذج بإنتاج 4,000 Token بينما النتيجة المطلوبة لا تتجاوز:

hot
warm
cold

لهذا فإن Cost Optimization الحقيقية لا تعني:

استخدم أرخص Model في كل مكان.

بل تعني:

استخدم أقل قدر من الـ Compute والـ Context والـ Tokens اللازم لإنجاز كل مهمة بالمستوى المطلوب من الجودة والموثوقية.

في هذا الدليل سنبني استراتيجية شاملة لتقليل تكلفة AI داخل Laravel تشمل:

  • Model Routing.
  • اختيار Model المناسبة لكل مهمة.
  • Token Optimization.
  • Context Reduction.
  • Prompt Optimization.
  • Structured Outputs.
  • Result Caching.
  • Embedding Caching.
  • RAG Optimization.
  • Conversation Summarization.
  • Laravel Queues.
  • منع Duplicate Jobs.
  • Agent Step Limits.
  • Usage Tracking.
  • Cost Budgets.
  • Adaptive Cost Control.
  • Evaluation وقياس Cost per Useful Result.

أولًا: كيف تُحسب تكلفة AI API؟

لفهم كيفية تخفيض التكلفة، يجب أولًا معرفة من أين تأتي.

في معظم تطبيقات LLM يمكن تبسيط تكلفة العملية بالشكل التالي:

AI Cost =
Input Tokens
+
Output Tokens
+
Model Cost
+
Number of Requests
+
Tool / Search / Embedding Costs
+
Retries and Duplicate Work

إذا كانت إحدى العمليات ترسل:

Input:
5,000 tokens

Output:
1,000 tokens

Total:
6,000 tokens

وتنفذ العملية 100,000 مرة، فأنت تتعامل نظريًا مع:

6,000 × 100,000
=
600,000,000 tokens

لهذا فإن تحسينًا صغيرًا جدًا على مستوى Request واحدة يمكن أن يتحول إلى توفير ضخم عند تكراره مئات الآلاف أو ملايين المرات.

القاعدة الأولى: لا تستخدم AI عندما يستطيع PHP أو SQL تنفيذ المهمة

هذه واحدة من أهم قواعد خفض التكلفة.

ليس كل شيء يحتاج إلى LLM.

إذا أردت حساب إجمالي فاتورة:

total = subtotal + tax

فلا يوجد أي سبب منطقي لإرسال القيم إلى AI.

$total = $subtotal + $tax;

PHP هنا:

  • أسرع.
  • أرخص.
  • حتمي Deterministic.
  • أسهل في الاختبار.
  • أقل عرضة للأخطاء.

أمثلة على مهام لا تحتاج إلى AI

Calculate age
Check subscription expiration
Validate email
Find order by ID
Calculate discount
Sum invoice
Check account status
Compare numbers
Calculate percentages
Apply business rules
Check permissions
Validate database values

هذه مهام يجب تنفيذها غالبًا باستخدام:

PHP
SQL
Laravel Validation
Business Logic
Database Queries

وليس LLM.

متى تصبح AI مناسبة؟

استخدم AI عندما تحتوي المهمة على معنى غير منظم أو تحتاج إلى فهم اللغة والسياق، مثل:

  • فهم نية العميل.
  • تحليل المشاعر.
  • تلخيص محادثة.
  • استخراج معلومات من نص غير منظم.
  • تحليل عقد.
  • اكتشاف اعتراضات العميل.
  • Semantic Search.
  • توليد نصوص.
  • التعامل مع أسئلة بلغة طبيعية.
  • تحليل حالات معقدة لا يمكن التعبير عنها بسهولة بقواعد ثابتة.

أكبر خطأ: استخدام Model واحدة لكل شيء

تخيل CRM يحتوي على الوظائف التالية:

Detect Sentiment
Classify Lead
Generate Tags
Summarize Message
Answer Customer
Analyze Sales Call
Extract Invoice
Analyze Contract
Build Sales Strategy
Complex Reasoning

الخطأ الشائع هو إرسال كل هذه المهام إلى أقوى Model.

Everything
    ↓
Most Powerful Model

هذه Architecture سهلة برمجيًا، لكنها قد تكون مكلفة جدًا.

السؤال:

هل هذه الرسالة positive أم negative؟

ليس بنفس صعوبة:

حلل هذا العقد المكون من 60 صفحة،
استخرج الالتزامات القانونية،
حدد التعارضات بين البنود،
ثم صنف المخاطر حسب شدتها.

الحل: Model Routing

قسّم مهام AI حسب درجة التعقيد.

المستوى الأول: Simple Tasks

  • Sentiment Classification.
  • Intent Detection.
  • Lead Classification.
  • Tag Generation.
  • Short Summaries.
  • Simple Extraction.

المستوى الثاني: Medium Tasks

  • Customer Support.
  • Lead Analysis.
  • Document Extraction.
  • Call Summaries.
  • Moderate RAG Questions.
  • Email generation.

المستوى الثالث: Complex Tasks

  • Contract Risk Analysis.
  • Strategic Analysis.
  • Multi-step Agents.
  • Complex Reasoning.
  • Large document synthesis.
  • Tasks requiring several tools.

فتصبح Architecture:

Task
 ↓
Task Classification
 ↓
Complexity
 ↓
Model Router
 ↓
Cheap / Standard / Powerful Model

استخدام UseCheapestModel في Laravel AI SDK

إذا كنت تستخدم Laravel AI SDK، فيمكن تحديد Agents المناسبة للمهام منخفضة التعقيد لكي تستخدم أرخص Text Model متاحة لدى Provider.

use Laravel\Ai\Attributes\UseCheapestModel;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

#[UseCheapestModel]
class SentimentClassifier implements Agent
{
    use Promptable;

    // ...
}

هذه الاستراتيجية مناسبة لمهام مثل:

  • Sentiment Classification.
  • Intent Detection.
  • Simple Summaries.
  • Simple Extraction.
  • Tagging.

متى تستخدم UseSmartestModel؟

في الطرف الآخر، توجد مهام تكون فيها جودة الاستدلال أهم بكثير من تكلفة Request الواحدة.

use Laravel\Ai\Attributes\UseSmartestModel;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

#[UseSmartestModel]
class ContractRiskAnalyzer implements Agent
{
    use Promptable;

    // ...
}

الفكرة:

Simple Task
→ Cheapest acceptable model

Normal Task
→ Standard model

Complex Task
→ Smartest / powerful model

بدل:

Everything
→ Most expensive model

متى يكون تثبيت Model أفضل؟

الاختيار التلقائي ممتاز عندما تريد الاستفادة من تطور الـ Providers والنماذج الجديدة.

لكن في Production توجد حالات تحتاج فيها إلى:

  • تكلفة متوقعة.
  • سلوك ثابت.
  • نتائج قابلة للاختبار.
  • منع تغيّر Model دون إجراء Evaluation جديد.

عندها يكون تثبيت Model محددة أكثر ملاءمة.

use Laravel\Ai\Attributes\Model;

#[Model('your-model-name')]
class SupportAgent
{
    // ...
}
Cost Optimization لا تعني اختيار Model الأرخص، بل اختيار أرخص Model تحقق مستوى الجودة المطلوب للمهمة.

استخدم Evaluation قبل تخفيض قوة Model

لا تغيّر Model لأن سعرها أرخص ثم تفترض أنها ستعمل بنفس الجودة.

أنشئ Dataset حقيقية من التطبيق.

مثلًا في Lead Classification:

100 real customer messages

Expected output:
Hot
Warm
Cold

ثم اختبر:

Cheap Model
Standard Model
Powerful Model

وقارن:

  • Accuracy.
  • Cost.
  • Latency.
  • Failure Rate.
  • Retry Rate.
  • JSON validity.

مثلًا:

Model A

Accuracy: 94%
Relative Cost: 1x


Model B

Accuracy: 95%
Relative Cost: 4x

في بعض المهام قد لا تكون زيادة Accuracy بنسبة 1% مبررًا لدفع أربعة أضعاف التكلفة.

لكن في مهام مالية أو قانونية أو عالية الحساسية، قد تكون الزيادة الصغيرة في الجودة مهمة جدًا.

لا تقيس Cost per Request فقط

Model منخفضة السعر ليست دائمًا الأرخص على مستوى النظام.

افترض أن Model رخيصة تفشل في 30% من الطلبات، فيضطر التطبيق إلى:

  • إعادة Request.
  • استدعاء Model ثانية.
  • استهلاك المزيد من Tokens.
  • تشغيل Validation إضافية.

لذلك:

Cheapest Model
≠
Lowest System Cost

المقياس الأكثر أهمية هو:

Cost per Successful Result

أو

Cost per Useful Result

استراتيجية أقوى: Model Escalation

لا تحتاج إلى إرسال كل Request إلى Model قوية من البداية.

يمكنك بدء المهمة بـ Model منخفضة التكلفة، وإذا كانت النتيجة غير مؤكدة فقط يتم تصعيد الحالة.

Cheap Model
     ↓
Confidence?
   ↙      ↘
 YES      NO
 ↓         ↓
Done   Strong Model

مثلًا:

{
    "classification": "hot",
    "confidence": 0.96
}

إذا كان:

confidence >= 0.85

نعتمد النتيجة.

أما إذا كانت:

{
    "classification": "warm",
    "confidence": 0.48
}

يمكن تصعيد الحالة إلى Model أقوى.

فتصبح التكلفة مثلًا:

80% of requests
→ Cheap Model

20% of requests
→ Strong Model

بدل:

100%
→ Strong Model

قلل Output Tokens

كل Token يقوم النموذج بإنشائها لها تكلفة.

إذا كانت UI تحتاج جملتين، فلا تطلب مقالًا.

على سبيل المثال:

Summarize this customer message.

تعليمة مفتوحة مثل هذه قد تسمح للنموذج بإنتاج مئات الكلمات.

الأفضل:

Summarize the customer message in a maximum
of two short sentences.

استخدام MaxTokens

Laravel AI SDK تسمح بتحديد أقصى عدد من Tokens التي يمكن للـ Agent توليدها.

use Laravel\Ai\Attributes\MaxTokens;

#[MaxTokens(200)]
class LeadClassifier implements Agent
{
    use Promptable;
}

إذا كانت المهمة عبارة عن:

  • Lead Score.
  • Classification.
  • Short Summary.

فغالبًا لا تحتاج إلى السماح بإنتاج آلاف Tokens.

MaxTokens ليست بديلًا عن Prompt جيدة

إذا قلت للنموذج:

Write a detailed analysis of every possible
interpretation and provide 20 recommendations...

ثم وضعت:

#[MaxTokens(100)]

قد تحصل ببساطة على إجابة مقطوعة.

الأفضل الجمع بين:

Clear Task
+
Compact Prompt
+
Structured Output
+
Appropriate MaxTokens

استخدم Structured Output بدل المقالات الطويلة

إذا كان تطبيقك يحتاج إلى بيانات، فاطلب بيانات.

بدل:

Analyze this lead.

استخدم Output واضحة مثل:

{
    "score": 85,
    "classification": "hot",
    "summary": "Customer is highly interested in pricing.",
    "next_action": "Call within 24 hours"
}

هذه الطريقة تقلل:

  • Output Tokens.
  • الكلام غير المطلوب.
  • Parsing complexity.
  • احتمالات تغير شكل الإجابة.

Input Tokens قد تكون المشكلة الأكبر

المطورون يركزون كثيرًا على طول Output، لكن Input قد تكون أكبر منها بعشرات المرات.

تخيل Request يحتوي على:

System Prompt:
2,000 tokens

Conversation:
8,000 tokens

CRM Data:
5,000 tokens

Knowledge Base:
10,000 tokens

User Question:
50 tokens

Total:
25,050 tokens

وكل ذلك للإجابة عن:

متى ينتهي اشتراكي؟

هذه ليست مشكلة Model.

هذه مشكلة Architecture.

Context Reduction: لا ترسل كل شيء للنموذج

من أكبر فرص التوفير في تطبيقات AI تقليل Context.

تصميم سيئ:

$agent->prompt(
    json_encode($customer->toArray())
);

قد يؤدي ذلك إلى إرسال:

Name
Phone
Email
Orders
Invoices
Notes
Activities
Subscriptions
Messages
Logs
Metadata
Payments
Tickets
Relationships

بينما السؤال:

ما حالة اشتراكي؟

يحتاج ربما إلى:

Current Subscription
Expiration Date
Status

فقط.

استخدم Tools بدل إرسال قاعدة البيانات كاملة

أحد أفضل Designs للـ Agents هو منح Agent أدوات محددة للوصول إلى المعلومات عند الحاجة.

بدل:

Entire CRM Record
       ↓
      LLM

استخدم:

User Question
     ↓
Agent
     ↓
Needs subscription data?
     ↓
GetSubscription Tool
     ↓
Only required fields
     ↓
LLM Response

هذا يحسن في الوقت نفسه:

  • التكلفة.
  • الخصوصية.
  • الأمان.
  • جودة Context.
  • سهولة Debugging.

Conversation History قد تصبح قاتل التكلفة

تخيل Support Chat وصلت إلى 150 رسالة.

إذا كنت ترسل جميع الرسائل القديمة في كل Request:

Message #151
→ sends 150 old messages

Message #152
→ sends 151 old messages

Message #153
→ sends 152 old messages

أنت تعيد شراء نفس Context مرارًا وتكرارًا.

الحل: Rolling Summary

بدل إرسال:

Messages 1 → 150

أرسل:

Conversation Summary
+
Last 10 Messages

مثال:

Conversation Summary:

- Customer subscribed to Premium.
- Payment completed.
- Activation is still pending.
- Ticket #1842 was created.
- Customer prefers WhatsApp.

Recent Context:

Last 10 messages.

بهذه الطريقة تحافظ على أهم المعلومات دون إعادة إرسال تاريخ كامل للمحادثة.

Long-Term Memory يجب أن تكون Selective

إذا كان المستخدم يمتلك 500 Memory، فهذا لا يعني أن ترسل 500 Memory مع كل سؤال.

استخدم Semantic Retrieval لاسترجاع الأكثر ارتباطًا فقط.

Current Message
      ↓
Memory Search
      ↓
Top Relevant Memories
      ↓
Prompt

مثلًا:

500 memories stored

Retrieved:
Top 5 relevant memories

وبذلك تحصل على Personalization دون تضخيم Context.

RAG ليست فقط لتحسين Accuracy

RAG يمكن أن تكون أيضًا أداة قوية لتقليل التكلفة.

بدل:

100 Documents
     ↓
All Document Text
     ↓
LLM

استخدم:

Question
   ↓
Embedding
   ↓
Vector Search
   ↓
Relevant Chunks
   ↓
LLM

وبهذا ترسل أجزاء الوثائق المرتبطة بالسؤال بدل Knowledge Base كاملة.

لا تستخدم Top-K كبير بلا سبب

إذا كانت أفضل نتيجة لديك تتحقق باستخدام:

Top 3

فإرسال:

Top 20

قد يؤدي إلى:

  • Input Tokens أكبر.
  • Cost أعلى.
  • Noise أكبر.
  • احتمال تشتيت Model.

اختبر:

Top 3
Top 5
Top 8
Top 10

ثم اختر أصغر قيمة تحافظ على Retrieval Quality المطلوبة.

Caching: لا تدفع مرتين مقابل نفس العمل

من أكثر التكاليف التي يمكن تجنبها:

Same Input
   ↓
Same AI Task
   ↓
New API Request

في كل مرة.

مثلًا إذا كانت سياسة الاسترجاع ثابتة، وسأل 5,000 مستخدم أسئلة متشابهة عنها، فليس من الضروري دائمًا إنشاء إجابة جديدة بالكامل.

Result Caching في Laravel

مثال مبسط:

use Illuminate\Support\Facades\Cache;

$key = 'ai:refund-summary:v3';

$result = Cache::remember(
    $key,
    now()->addHours(24),
    fn () => (new PolicySummarizer)
        ->prompt($refundPolicy)
);

فتصبح العملية:

First Request
→ AI API

Next Requests
→ Cache

Cache Key يجب أن تحتوي Version

لا تستخدم Key عامة مثل:

ai:summary

لأنها لا تميز بين المحتوى أو Prompt أو Model.

صمم Key اعتمادًا على:

Task
+
Input Hash
+
Prompt Version
+
Model Version

مثال:

$key = sprintf(
    'ai:summary:%s:%s:%s',
    hash('sha256', $document->content),
    'prompt-v4',
    'model-v2'
);

إذا تغير المحتوى:

New Content Hash
→ New Generation

وإذا تغير Prompt:

New Prompt Version
→ New Generation

لا تستخدم Cache للبيانات الحية بلا تفكير

السؤال:

What is order #9281 status?

قد تكون إجابته الآن:

Shipped

وبعد ساعة:

Delivered

إذا خزنت إجابة AI لمدة 24 ساعة، فستعيد معلومات قديمة.

لذلك:

Static Knowledge
→ Long Cache

Slow-changing Data
→ Short Cache

Live Transaction Data
→ Very Short Cache / No Result Cache

Embedding Caching

إذا كنت تستخدم Embeddings في RAG أو Semantic Search، فلا تعِد إنشاء Embedding لنفس المحتوى بلا سبب.

Laravel AI SDK توفر دعمًا مباشرًا لتخزين Embeddings مؤقتًا.

في ملف:

config/ai.php

يمكن تفعيلها مثلًا:

'caching' => [
    'embeddings' => [
        'cache' => true,
        'store' => env('CACHE_STORE', 'database'),
    ],
],

وعندما يكون المحتوى والـ Provider والـ Model وإعدادات Embedding متطابقة، يمكن إعادة استخدام النتيجة بدل تنفيذ API call جديدة.

Cache Embedding لطلب محدد

$response = Embeddings::for([
    'Subscription payment issue',
])
    ->cache()
    ->generate();

أو عند استخدام Helper مناسب:

$embedding = Str::of($content)
    ->toEmbeddings(cache: true);

الأفضل من Cache: لا تعِد Indexing محتوى لم يتغير

Cache ممتازة، لكن التصميم الأفضل هو منع العمل أصلًا.

أنشئ Hash للمحتوى:

$hash = hash(
    'sha256',
    $article->content
);

ثم قارنها بالنسخة السابقة:

if ($article->embedding_hash === $hash) {
    return;
}

فتصبح Architecture:

Content Updated?
      ↓

NO
→ Skip Embedding

YES
→ Generate Embedding
→ Store New Hash

منع العمل أفضل من تنفيذ العمل ثم الاعتماد على Cache لإلغائه.

Prompt Optimization

Prompt طويلة ليست بالضرورة Prompt أفضل.

من الأخطاء الشائعة كتابة System Prompt تحتوي على عشرات التعليمات العامة من نوع:

You are the world's greatest expert...

You must carefully think...

Always be accurate...

Always analyze every possible angle...

You should...

ثم إضافة عشرات القواعد التي لا تؤثر فعليًا في المهمة.

المشكلة أن System Prompt قد يتم إرسالها مع كل Request.

إذا كان حجمها:

1,500 tokens

وكان لديك:

1,000,000 requests

فأنت تتعامل مع:

1.5 billion repeated system-prompt tokens

قبل حساب سؤال المستخدم أو Context الخاصة به.

اختصر التعليمات المتكررة

بدل:

You should under all circumstances carefully
analyze the user's customer message and determine
whether the sentiment expressed by the customer
is positive, neutral or negative...

يمكن أن تكون:

Classify customer sentiment as:
positive, neutral, or negative.

إذا كانت الاختبارات تثبت أن النسختين تحققان الجودة نفسها، فالثانية أفضل وأرخص.

لا تضع Documentation كاملة داخل System Prompt

تصميم مكلف:

System Prompt

[20 pages of company policies]

User:
Hi

التصميم الأفضل:

Short System Prompt
      +
User Question
      ↓
RAG Search
      ↓
Relevant Policy Chunks
      ↓
LLM

Agent Loops قد تستهلك ميزانيتك بسرعة

Agents التي تستطيع استخدام Tools قد تنفذ عدة Steps قبل الوصول إلى الإجابة.

مثلًا:

Agent
 ↓
Tool
 ↓
Model
 ↓
Tool
 ↓
Model
 ↓
Tool
 ↓
Model

كل Step قد تعني Request جديدة وTokens إضافية.

إذا لم يكن هناك حد واضح، يمكن أن تتحول مهمة واحدة إلى سلسلة مكلفة من العمليات.

استخدام MaxSteps

حدد عدد الخطوات المناسب لطبيعة Agent.

use Laravel\Ai\Attributes\MaxSteps;

#[MaxSteps(5)]
class SupportAgent implements Agent
{
    use Promptable;
}

لا تجعل:

MaxSteps = 20

إذا كانت المهمة في الظروف الطبيعية تحتاج إلى خطوتين أو ثلاث فقط.

Laravel Queues لا تخفض سعر Token مباشرة، لكنها مهمة جدًا

Queue لا تجعل Model أرخص تلقائيًا.

لكنها تسمح لك بتنظيم العمليات المكلفة وإبعادها عن Request المستخدم المباشرة.

مهام مناسبة للـ Queue:

  • تحليل مكالمات طويلة.
  • إنشاء Embeddings.
  • Document Indexing.
  • Bulk Classification.
  • Call Summarization.
  • Large Import Processing.
  • Offline AI Reports.

مثال:

AnalyzeSalesCall::dispatch($call->id);

وبذلك يمكن التحكم في:

  • Concurrency.
  • Rate Limits.
  • Retries.
  • Timeouts.
  • Priority.
  • Batching.

انتبه إلى Retries

Retry غير منضبطة يمكن أن تضاعف التكلفة.

تخيل Job تكلف:

$0.10

ويتم Retry خمس مرات بسبب Timeout غير صحيح.

قد تدفع عدة أضعاف التكلفة الفعلية للعملية.

حدد عدد المحاولات وBackoff بعناية، ولا تعِد تشغيل Generation ناجحة لمجرد أن جزءًا لاحقًا من Job فشل.

اجعل AI Operations قابلة لإعادة التشغيل بأمان

افصل:

Generate AI Result

عن:

Save Result
Send Notification
Update CRM

إذا نجحت عملية AI وفشل إرسال Notification، فلا ينبغي أن تعيد Generation كاملة فقط لإعادة الإشعار.

امنع Duplicate AI Jobs

تخيل أن المستخدم ضغط زر التحليل ثلاث مرات.

بدون حماية:

Click
→ AI Job

Click
→ AI Job

Click
→ AI Job

وقد تدفع ثلاث مرات مقابل النتيجة نفسها.

في Laravel يمكن استخدام Unique Jobs عندما يناسب السيناريو.

use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;

class AnalyzeDocument implements ShouldQueue, ShouldBeUnique
{
    public function __construct(
        public int $documentId
    ) {}

    public function uniqueId(): string
    {
        return (string) $this->documentId;
    }
}

استخدم Content Fingerprint لمنع العمل المكرر

في كثير من عمليات AI يمكن تعريف العملية باستخدام:

Task
+
Input
+
Prompt Version
+
Model
+
Configuration

ثم بناء Fingerprint:

$fingerprint = hash('sha256', json_encode([
    'task' => 'document-summary',
    'input' => $document->content,
    'prompt_version' => 'v5',
    'model' => $model,
]));

قبل تنفيذ AI:

$existing = AiResult::where(
    'fingerprint',
    $fingerprint
)->first();

if ($existing) {
    return $existing->result;
}

هذه التقنية مفيدة جدًا في:

  • Document Summaries.
  • Classification.
  • Embeddings.
  • Reports.
  • Product descriptions.
  • Offline analysis.

Batch Processing

إذا كان لديك 10,000 Record تحتاج إلى Classification، لا تتعامل معها بالطريقة نفسها التي تتعامل بها مع Chat مباشر للمستخدم.

Interactive Request تحتاج Low Latency.

أما Offline Processing فيمكن أن تستخدم:

  • Queues.
  • Batches.
  • أقل Priority.
  • Provider Batch APIs عندما تكون متاحة ومناسبة.
  • Models أقل تكلفة إذا كانت الجودة كافية.

اجمع عدة تصنيفات صغيرة عندما يكون ذلك منطقيًا

في بعض الحالات، إرسال 100 Request صغيرة بشكل منفصل قد يكون أقل كفاءة من معالجة مجموعة منظمة.

بدل:

Message 1 → API
Message 2 → API
Message 3 → API
...
Message 100 → API

يمكن في بعض السيناريوهات:

Messages 1-20
→ One structured classification task

لكن لا تطبق هذا بصورة عمياء.

Batch كبيرة جدًا قد تؤدي إلى:

  • Context ضخمة.
  • Parsing أصعب.
  • فشل العملية كاملة بسبب عنصر واحد.
  • Latency أعلى.

Usage Tracking ليس Feature اختيارية

لا يمكنك تحسين شيء لا تقيسه.

يجب أن تعرف على الأقل:

  • كم Request AI يتم تنفيذها؟
  • أي Features تستهلك أكثر؟
  • أي Model تُستخدم؟
  • ما متوسط Input Tokens؟
  • ما متوسط Output Tokens؟
  • كم تبلغ التكلفة لكل مستخدم؟
  • كم تبلغ التكلفة لكل Feature؟
  • كم تبلغ التكلفة لكل Tenant؟
  • كم Retry تحدث؟
  • كم Cache Hit لدينا؟

أنشئ جدول ai_usage

مثال على البيانات التي يمكنك تخزينها:

id
user_id
tenant_id
feature
provider
model
input_tokens
output_tokens
total_tokens
estimated_cost
latency_ms
cache_hit
success
created_at

مثال Migration مبسط:

Schema::create('ai_usage', function ($table) {
    $table->id();

    $table->foreignId('user_id')
        ->nullable()
        ->index();

    $table->string('feature')->index();
    $table->string('provider')->nullable();
    $table->string('model')->nullable();

    $table->unsignedBigInteger('input_tokens')
        ->default(0);

    $table->unsignedBigInteger('output_tokens')
        ->default(0);

    $table->unsignedBigInteger('total_tokens')
        ->default(0);

    $table->decimal('estimated_cost', 12, 6)
        ->default(0);

    $table->unsignedInteger('latency_ms')
        ->nullable();

    $table->boolean('cache_hit')
        ->default(false);

    $table->boolean('success')
        ->default(true);

    $table->timestamps();
});

راقب Cost per User

قد تكتشف:

User #10

Monthly Revenue:
$100

AI Cost:
$4

وهذا ممتاز.

لكن مستخدمًا آخر:

User #91

Monthly Revenue:
$19

AI Cost:
$38

هنا لديك مشكلة تجارية حتى لو كانت Feature تعمل تقنيًا بشكل ممتاز.

راقب Cost per Feature

قد تكون التكلفة:

Support Chat
$500 / month

Lead Classification
$120 / month

Contract Analyzer
$3,800 / month

Daily AI Report
$7,200 / month

الآن أصبحت تعرف أين يجب أن تبدأ Optimization.

Budget Limits

لا تجعل استهلاك AI مفتوحًا بلا حدود، خصوصًا في SaaS.

يمكن بناء حدود حسب الخطة:

Basic
→ 100 AI actions / month

Pro
→ 1,000 AI actions / month

Enterprise
→ Custom

أو استخدم:

Monthly AI Credit Budget

بدل الاعتماد فقط على عدد Requests، لأن Request واحدة قد تكلف أكثر بكثير من أخرى.

Hard Limit وSoft Limit

Hard Limit

Budget exhausted
      ↓
AI disabled

هذا بسيط لكنه قد يؤدي إلى تجربة سيئة.

Soft Limit

استراتيجية أكثر ذكاءً:

Budget 80%
↓
Switch non-critical tasks
to cheaper models


Budget 95%
↓
Disable optional bulk analysis


Budget 100%
↓
Keep only critical AI functions

Adaptive Cost Mode

يمكن أن تجعل النظام يعدل سلوكه تلقائيًا بناء على الاستهلاك.

Usage < 70%
→ Normal Mode


Usage 70%–90%
→ Cheapest acceptable models


Usage 90%–100%
→ Disable non-essential AI


Usage >= 100%
→ Critical AI only

هذه Architecture أكثر مرونة من إغلاق AI بالكامل بمجرد الوصول إلى Limit.

راقب Cache Hit Rate

إذا كنت تستخدم Caching، يجب ألا تكتفي بتفعيلها.

راقب:

Cache Hits
Cache Misses
Hit Rate

مثلًا:

10,000 AI-compatible operations

8,000 cache hits
2,000 API calls

Hit Rate:
80%

هذا يعني أن Cache منعت 8,000 عملية محتملة.

راقب Token Distribution

المتوسط وحده قد يخدعك.

راقب:

Average Input Tokens
P50
P90
P95
P99

قد تكتشف أن معظم Requests حجمها:

2,000 tokens

لكن 1% منها تصل إلى:

80,000 tokens

وهي التي ترفع الفاتورة بشكل كبير.

ضع Alerts للتكلفة غير الطبيعية

لا تنتظر نهاية الشهر حتى تكتشف المشكلة.

يمكن بناء Alerts مثل:

Daily AI cost > expected × 2

User cost > plan threshold

Feature cost spike > 50%

Token usage spike

Retry rate spike

Cache hit rate drops significantly

لا تعرض AI Feature مجانية بلا حماية

إذا كانت لديك Endpoint مثل:

POST /api/ai/generate

من دون:

  • Authentication.
  • Rate Limiting.
  • Usage Quotas.
  • Request Validation.
  • Input Size Limits.

فأنت لا تواجه فقط خطر Abuse، بل أيضًا فاتورة غير محدودة.

ضع Input Size Limit قبل API

إذا كانت Feature مصممة لتحليل رسالة عميل، فلا تسمح للمستخدم بإرسال كتاب كامل.

$request->validate([
    'message' => [
        'required',
        'string',
        'max:10000',
    ],
]);

حدد الحد بناءً على احتياجات Feature الحقيقية وليس رقمًا عشوائيًا.

Rate Limiting جزء من Cost Control

مثلًا:

RateLimiter::for('ai', function ($request) {
    return Limit::perMinute(20)
        ->by($request->user()->id);
});

يمكنك أيضًا وضع Limits مختلفة بناءً على خطة المستخدم.

لا ترسل أسرارًا وبيانات لا يحتاجها النموذج

Context Reduction لا تحسن التكلفة فقط، بل تقلل Data Exposure.

إذا كانت المهمة لا تحتاج:

  • Password hashes.
  • API keys.
  • Internal metadata.
  • Private notes.
  • Full database records.

فلا ترسلها.

أفضل Token من ناحية التكلفة والأمان هو Token لم ترسلها أصلًا.

افصل AI Features حسب الغرض

بدل Agent ضخمة تحتوي على جميع تعليمات النظام:

MegaAgent

- Support
- Lead analysis
- Invoice extraction
- Contract analysis
- Sales strategy
- Classification
- Reports
- Everything else

يمكن تقسيمها إلى Agents صغيرة:

SentimentClassifier

LeadClassifier

SupportAgent

InvoiceExtractor

ContractAnalyzer

SalesCoach

هذا يسمح لكل Agent بالحصول على:

  • Prompt أقصر.
  • Model مناسبة.
  • MaxTokens مختلفة.
  • MaxSteps مختلفة.
  • Tools محددة.

مثال على Cost-Aware Architecture

                    User Request
                         │
                         ▼
                   Laravel API
                         │
                         ▼
                  Is AI Needed?
                    │        │
                   NO       YES
                    │        │
                    ▼        ▼
              PHP / SQL   Task Router
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
           Simple          Medium         Complex
              │              │              │
              ▼              ▼              ▼
         Cheap Model    Standard Model   Strong Model
              │              │              │
              └──────────────┼──────────────┘
                             ▼
                      Context Builder
                             │
                   ┌─────────┼─────────┐
                   ▼         ▼         ▼
                 RAG      Memory     Tools
                   │         │         │
                   └─────────┼─────────┘
                             ▼
                      Cache Lookup
                        │       │
                      HIT      MISS
                        │       │
                        ▼       ▼
                      Result   AI API
                                │
                                ▼
                         Usage Tracking
                                │
                                ▼
                          Result Cache
                                │
                                ▼
                              User

Production Strategy مقترحة

المرحلة 1: هل نحتاج AI؟

إذا كانت المهمة Deterministic، استخدم PHP أو SQL.

المرحلة 2: حدد نوع المهمة

classification
summary
support
extraction
reasoning
agent
RAG

المرحلة 3: اختر Model المناسبة

لا تستخدم Model واحدة لكل Tasks.

المرحلة 4: ابنِ Minimum Context

أرسل فقط المعلومات اللازمة.

المرحلة 5: افحص Cache

إذا كانت النتيجة متاحة وصالحة، لا تستدعِ API.

المرحلة 6: ضع Limits

MaxTokens
MaxSteps
Input Size
Timeout
Retries

المرحلة 7: نفذ العملية

استخدم Queue إذا لم تكن النتيجة مطلوبة فورًا.

المرحلة 8: سجل Usage

احفظ Tokens والتكلفة وModel والـ Feature والـ User.

المرحلة 9: خزّن النتائج القابلة لإعادة الاستخدام

مع Cache Versioning واضح.

المرحلة 10: راقب الميزانية

استخدم Soft Limits قبل الوصول إلى Hard Limit.

Cost Optimization Checklist

قبل إطلاق أي AI Feature في Laravel، اسأل الأسئلة التالية:

  • هل تحتاج المهمة إلى AI أصلًا؟
  • هل يستطيع PHP أو SQL تنفيذها؟
  • هل نستخدم Model أقوى من المطلوب؟
  • هل توجد Model أرخص تحقق الجودة نفسها؟
  • هل تم إجراء Evaluation بين Models؟
  • هل يمكن استخدام Escalation؟
  • هل يمكن Cache النتيجة؟
  • هل Cache Key تحتوي Prompt Version؟
  • هل Embedding نفسها موجودة مسبقًا؟
  • هل المحتوى تغير أصلًا قبل Re-indexing؟
  • هل نرسل بيانات أكثر مما تحتاجه المهمة؟
  • هل Conversation History كبيرة؟
  • هل يمكن استخدام Rolling Summary؟
  • هل نسترجع Memories ذات صلة فقط؟
  • هل Top-K في RAG أكبر من اللازم؟
  • هل System Prompt أطول من اللازم؟
  • هل Output أطول مما تحتاجه UI؟
  • هل يمكن استخدام Structured Output؟
  • هل MaxTokens محددة؟
  • هل MaxSteps محددة؟
  • هل Timeout مناسب؟
  • هل Retry Policy مناسبة؟
  • هل يمكن Queue العملية؟
  • هل Job قد تُنفذ أكثر من مرة؟
  • هل يمكن استخدام Unique Job؟
  • هل نسجل Usage لكل Request؟
  • هل نعرف Cost per User؟
  • هل نعرف Cost per Feature؟
  • هل لدينا Monthly Budget؟
  • هل لدينا Alerts للارتفاع غير الطبيعي؟
  • هل Endpoint محمية بـ Rate Limits؟

إذا لم تعرف إجابة عدد كبير من هذه الأسئلة، فهناك احتمال مرتفع لوجود Cost Waste داخل التطبيق.

ما الذي توفره Laravel نفسها لهذا النوع من Optimization؟

عند استخدام Laravel AI SDK وLaravel Framework، توجد عدة أدوات يمكن الاستفادة منها مباشرة.

UseCheapestModel

لاختيار Model منخفضة التكلفة للمهام التي لا تحتاج قدرات عالية.

UseSmartestModel

للمهام التي تستحق Model الأكثر قدرة.

Model

لتثبيت Model محددة عندما تحتاج Pricing وسلوكًا أكثر ثباتًا.

MaxTokens

للحد من حجم Generation.

MaxSteps

للحد من عدد خطوات Agent عند استخدام Tools.

Embedding Caching

لمنع إعادة طلب Embeddings المتطابقة.

Laravel Cache

لتخزين النتائج التي يمكن إعادة استخدامها.

Laravel Queues

لنقل العمليات الثقيلة أو غير الفورية إلى Background Workers.

Unique Jobs

لمنع بعض أنواع العمل المكرر.

Rate Limiting

للحد من Abuse والاستهلاك غير الطبيعي.

أين يبدأ أكبر توفير عادةً؟

ليس هناك Trick واحدة تخفض الفاتورة للجميع.

لكن في معظم المشاريع، يجب البحث أولًا عن هذه النقاط:

  1. إرسال Context أكبر من اللازم.
  2. استخدام Model قوية لمهام بسيطة.
  3. عدم استخدام Cache.
  4. إعادة إنشاء Embeddings بلا داعٍ.
  5. إرسال Conversation History كاملة.
  6. Outputs طويلة وغير ضرورية.
  7. AI Jobs مكررة.
  8. Retries غير منضبطة.
  9. Agent loops طويلة.
  10. عدم وجود Usage Tracking.

الخلاصة

تقليل تكلفة AI API داخل Laravel لا يعني البحث عن أرخص Model ثم استخدامها في كل شيء.

هذه الطريقة قد تقلل سعر Request الواحدة، لكنها قد تدمر الجودة وترفع عدد الإعادات والأخطاء، وبالتالي تصبح أغلى على مستوى النظام.

الاستراتيجية الصحيحة هي:

Right Task
    ↓
Is AI Really Needed?
    ↓
Right Model
    ↓
Minimum Required Context
    ↓
Minimum Useful Output
    ↓
Cache When Possible
    ↓
Avoid Duplicate Work
    ↓
Queue When Appropriate
    ↓
Track Usage
    ↓
Control Budgets
    ↓
Evaluate Quality vs Cost

تذكر أن الفاتورة الكبيرة نادرًا ما تأتي من Request واحدة مكلفة.

غالبًا تأتي من قرار صغير غير فعال يتكرر عشرات أو مئات الآلاف من المرات.

System Prompt أكبر من اللازم بمئات Tokens.

Conversation كاملة تُرسل في كل رسالة.

Embedding تُنشأ للمحتوى نفسه مرارًا.

Model قوية تُستخدم لمجرد Classification بسيطة.

Generation من 1,000 Token بينما التطبيق يحتاج 50 فقط.

Job واحدة يتم تنفيذها ثلاث مرات.

كل واحدة من هذه المشكلات قد تبدو صغيرة وحدها، لكن عند Scale تصبح تكلفة حقيقية.

أفضل نظام AI ليس النظام الذي يستخدم أقوى Model في كل Request، بل النظام الذي يعرف متى يحتاج إلى الذكاء، وكم يحتاج منه، ومتى لا يحتاج إليه أصلًا.