LLMProvider هو ما يولّد به الوكيل ردوده. تأتي الـ SDK بمزوّدين لـ OpenAI وAnthropic وOpenRouter وOllama (كل منهم يستند إلى حزمة نظيرة اختيارية، انظر التثبيت) وبمزوّد وهمي حتمي للاختبارات. حدِّد المزوّد بسلسلة نصية بصيغة provider/model، أو مرِّر كائن مزوّد (instance).
اختيار المزوّد في createAgent()
يقبل createAgent() واحدًا فقط مما يلي:
model: 'provider/model'- يُحلّ بواسطةresolveProvider()؛ ويأتي المفتاح من متغير البيئة المتعارف عليه للمزوّد (انظر بيانات اعتماد المزوّدين).provider: <LLMProvider>- مزوّدك الخاص، أو مزوّد مدمج مضبوط، أو مزوّد وهمي. يمكنك أيضًا تمريرmodel(معرّف مجرد مثل'gpt-4o'): فيصبح نموذج هذا الوكيل، ويتقدّم على النموذج الافتراضي للمزوّد.- لا هذا ولا ذاك - يُحلّ من البيئة:
LOUSHO_MODEL(سلسلةprovider/model) إن كان مضبوطًا، وإلا فأول الموجود منOPENAI_API_KEYوANTHROPIC_API_KEYوOPENROUTER_API_KEYوOLLAMA_BASE_URL. وإذا لم يكن أي منها مضبوطًا رمى خطأً يسرد الحلول.
npm install الدقيق.
إعادة المحاولة والنماذج الاحتياطية
يعيدcreateAgent() محاولة استدعاء النموذج الفاشل (تجاوز حدّ المعدّل، انتهاء المهلة، خطأ شبكة، خطأ 5xx) مرتين افتراضيًا، ومع fallbackModels ينتقل إلى النموذج التالي حين يستمر فشل الاستدعاء:
model وكل نموذج احتياطي مع تعطيل إعادة المحاولة الخاصة بحزمة ai، فتكون retry طبقة إعادة المحاولة الوحيدة. أما كائن provider فلا يُغلَّف إلا حين تضبط retry. يبلّغ agent.stream() عن الحدثين provider.retry وprovider.fallback. التفاصيل في إعادة المحاولة والبديل الاحتياطي للمزوّد.
أي نموذج يعمل؟
بالترتيب:settings.model الخاص بالوكيل (يُضبط بـ AgentBuilder.setSettings({ model })، أو بـ model إلى جانب provider في createAgent())، ثم النموذج الذي بُني به المزوّد (resolveProvider('openai/gpt-4o-mini')، أو provider.model في ملف مواصفات، أو defaultModel)، ثم النموذج الافتراضي المدمج في المزوّد. لا يوجد نموذج احتياطي مثبَّت في الشيفرة.
الإدخال متعدد الوسائط
Message.content سلسلة نصية أو قائمة أجزاء: { type: 'text', text }، و{ type: 'image', image, mimeType? } (عنوان http(s)، أو عنوان data:، أو البايتات على هيئة Uint8Array) و{ type: 'file', data, mimeType, filename? }. تقبل agent.send() وagent.stream() وsession.send() / stream() وt.send() في التقييمات وsend() في خطّاف React كلها قيمة من نوع AgentInput: سلسلة نصية، أو قائمة أجزاء (تُرسَل كرسالة مستخدم واحدة)، أو Message[] (تُمرَّر كما هي). ويقبل AgentExecutor.execute() الرسائل نفسها في input:
- الصور تصل إلى النموذج ضمن رسائل
userمع كل المزوّدين المدمجين (مع Anthropic وOllama تنزّل حزمةaiالصورة من عنوانها أولًا). اختر نموذجًا يدعم الرؤية: Ollama يتجاهل الصور مع نموذج نصي فقط، وOpenRouter يرفضها معه. - الملفات لا يرسلها المزوّدون المدمجون، على أي إصدار رئيسي من
ai: يُرسَل جزء الملف كملاحظة نصية ([file report.pdf (application/pdf) not sent]) ويحذّر المزوّد مرة واحدة. الصنف الفرعي من مزوّد يقبل نموذجه الملفات يضبطprotected readonly acceptsFileParts = trueليرسلها كأجزاء ملفات بصيغةaiv4. - رسائل
systemوassistantوtoolتُرسَل بأجزائها النصية. - كل ما يقرأ نص الرسائل يستخدم
textOf():estimateTokens()(يُحتسب كل جزء صورة أو ملف 1,000 رمز ثابتة)، وضغط السياق، وأشرطة تسجيلrecordReplay()(التي تخزّن النص وبصمة كل صورة أو ملف، أو عنوانه) وmockModel(). يحفظFileSessionStoreالبايتات بترميز base64 ({ "$bytes": "..." }) ويعيد تحميلها على هيئةUint8Array؛ ويفعلSqliteStore(للجلسات ونقاط الحفظ) الشيء نفسه.
أصناف المزوّدين
لاستخدام خدمة خلفية أخرى، نفّذ الواجهة
LLMProvider (name وgenerate() وstream() وsupportsTools() وsupportsStreaming() وgetModels()، واختياريًا defaultModel) ومرِّر الكائن بوصفه provider، أو سجّل مصنعًا بـ LLMProviderRegistry.register(name, factory).
إصدارات Vercel AI SDK
المزوّدون المدمجون مهايئات فوق Vercel AI SDK (ai). ما يعمل اليوم على كل إصدار رئيسي:
نطاقات الاعتماديات النظيرة تقبل الإصدارات الرئيسية الثلاثة. قرِن كلًّا منها بحزم المزوّدين المناسبة له:
تلميح التثبيت لحزمة مزوّد ناقصة و
lousho doctor يذكران الإصدار المناسب لنسخة ai المثبَّتة لديك، وينبّه lousho doctor إلى الزوج غير المتوافق (مثلًا ai 7 مع @ai-sdk/openai 1.x). يحمّل OllamaProvider الحزمة ollama-ai-provider على ai 4 والحزمة ollama-ai-provider-v2 على ai 6/7؛ وحزمة v2 تعتمد اعتمادًا نظيرًا على zod 4، وهو ما تقبله الـ SDK، فثبّت zod 4 معها (مشاريع zod 3 تستخدم Ollama مع ai 4). ينشئ lousho init هيكل المشروع بـ ai@^7.0.0 مع @ai-sdk/*@^4.0.0 لـ OpenAI وAnthropic وOpenRouter، وبـ ai@^4.3.19 لـ Ollama.
يستخدم OpenRouter الحزمة @ai-sdk/openai موجَّهة إلى عنوان OpenRouter الأساسي. ابتداءً من @ai-sdk/openai 2، يستهدف الاستدعاء الافتراضي openai(modelId) واجهة Responses API، التي لا ينفّذها OpenRouter، ولذلك يطلب OpenRouterProvider نموذج Chat Completions (provider.chat(modelId)) على كل إصدار رئيسي؛ وهو يعمل على ai 4 و6 و7 مع الاقتران المذكور أعلاه.
يأخذ OllamaProvider عنوان الخادم الأساسي (baseURL، أو OLLAMA_BASE_URL في حالة resolveProvider()) ويُلحق /api بالمضيف المجرد، كما تتوقعه حزمتا Ollama كلتاهما: http://host:11434 وhttp://host:11434/ يصبحان http://host:11434/api. العنوان الذي ينتهي أصلًا بـ /api (أو /api/)، أو فيه أي مسار آخر مثل بادئة وكيل عكسي، يُستخدم كما هو.
يختار generate() وstream() شكل الاستدعاء بحسب وحدة ai المثبَّتة: حين تصدّر stepCountIs (الإصدار v5 وما بعده)، يُرسَل الطلب بشكل v6/v7 وتُقرأ النتيجة وتُحوَّل إلى GenerateResult أو StreamResult نفسيهما:
- تتحوّل الرسائل إلى كائنات
ModelMessage: وسائط استدعاء الأداة تصبحinputالخاص به، ونتيجة الأداة تصبحoutput(jsonأوtext، وerror-jsonأوerror-textحين تفشل الأداة)، وmimeTypeفي جزء الصورة أو الملف يصبحmediaType. تبقى رسائل النظام في مواضعها (allowSystemInMessages). - يُرسَل
maxTokensباسمmaxOutputTokens، والخطوة الواحدة بالشكلstopWhen: stepCountIs(1)، والأدوات باسمinputSchema(مخطط zod كما هو، ومخطط JSON Schema عبرjsonSchema()) دونexecute، وresponseFormatعلى هيئةoutputبوضع JSON لا يمسّ نص الرد. - يأتي الاستهلاك من
inputTokens/outputTokens/totalTokens، معcachedInputTokensمنinputTokenDetails.cacheReadTokensوreasoningTokensمنoutputTokenDetails.reasoningTokens. - يقرأ
stream()المجرىfullStreamالخاص بـ AI SDK على أي من الإصدارين الرئيسيين ويحوّله إلى القطع (chunks) نفسها:text-delta(في v6/v7 الحقلtext، وفي v4 الحقلtextDelta)، وtool-call(الاستدعاء الكامل الذي يرسله v6/v7 بعدtool-input-start/-delta/-end، أو استدعاء يُجمَّع من ذلك الإدخال حين لا يرسل النموذج استدعاءً كاملًا)، وfinishمع سبب الانتهاء الذي تعطيه AI SDK والاستهلاك المذكور أعلاه (في v6/v7 الحقلtotalUsage). جزءerrorيجعل المجرى يُرفض بخطئه، على v4 أيضًا (كان v4 ينهي مجرى كهذا بسبب الانتهاءerror)، وجزءabortيرفضه بسبب الإشارة. تغيّرات الاستدلال الجزئية (deltas) يُبلَّغ عنها قطعًا من النوعreasoning-deltaوتظهر أحداثًاreasoning.*(انظر الاستدلال).
0.0.x/1.x تنتج نماذج يرفضها ai v7. تُرسَل أجزاء الصور كأجزاء image، وهي ما يقبله ai v7 مع تحذير إهمال لكل جزء (globalThis.AI_SDK_LOG_WARNINGS = false يوقف تحذيرات ai). الإصدار ai v5 غير مدعوم.
أين يعمل كل مزوّد
كل المزوّدين يعملون على Node. هدف النشرcloudflare-worker يدعم mock وopenai وanthropic؛ أما ollama وopenrouter فيحتاجان إلى الهدف node-server أو docker (انظر النشر).