تشكل نماذج اللغة الكبيرة (LLMs) تحولاً في كيفية بناء التطبيقات، لكن الاعتماد فقط على واجهات برمجة التطبيقات المستندة إلى السحابة ليس دائماً مثالياً. غالباً ما تدفع التأخيرات والتكاليف وخصوصية البيانات والحاجة إلى القدرات غير المتصلة المطورين نحو تشغيل النماذج محلياً. ظهرت "Ollama" كأداة رائعة لتشغيل نماذج LLMs مفتوحة المصدر القوية مثل "Llama 3" و"Mistral" و"Phi-3" بسهولة مباشرة على جهازك (macOS، Linux، Windows).
ومع ذلك، يتطلب التفاعل مع نماذج LLMs مختلفة، سواء كانت محلية أو بعيدة، غالباً كتابة كود محدد للنموذج. هنا يأتي دور "LiteLLM". توفر "LiteLLM" واجهة موحدة وخفيفة الوزن للتفاعل مع أكثر من 100 واجهة برمجة تطبيقات مختلفة لـ LLM، بما في ذلك "Ollama" و"OpenAI" و"Anthropic" و"Cohere" والعديد غيرها. من خلال استخدام "LiteLLM"، يمكنك كتابة الكود مرة واحدة والتبديل بسلاسة بين نماذج ومزودين مختلفين - بما في ذلك نماذج "Ollama" المحلية الخاصة بك - مع تغييرات قليلة جداً.
يوفر هذا البرنامج التعليمي دليلًا تفصيليًا خطوة بخطوة عن كيفية إعداد واستخدام "LiteLLM" للتفاعل مع نماذج "Ollama" التي تعمل على جهازك المحلي. سنغطي كل شيء من التثبيت والتكوين الأساسي إلى إجراء مكالمات API، وتدفق الاستجابات، واستخدام ميزات "LiteLLM" الأكثر تقدمًا.
هل ترغب في منصة متكاملة، شاملة لكل شيء لفريق المطورين الخاص بك للعمل معًا بأقصى إنتاجية؟
تقدم "Apidog" جميع متطلباتك، وتحل محل Postman بأسعار أكثر تنافسية!
مقدمة: لماذا "LiteLLM" و"Ollama"؟
قبل أن نبدأ في الخطوات الفنية، دعنا نفهم الأدوات التي نعمل بها ولماذا يعتبر دمجها قوياً.
ما هي "LiteLLM"؟
"LiteLLM" هي مكتبة بايثون خفيفة الوزن تعمل كواجهة موحدة للتفاعل مع مجموعة واسعة من واجهات برمجة تطبيقات LLM. بدلاً من تعلم وتنفيذ SDKs أو تنسيقات طلبات API المختلفة لـ "OpenAI" و"Anthropic" و"Cohere" و"Google Gemini" و"Azure OpenAI" و"Replicate" و"Hugging Face" ووالنموذج المحلي مثل "Ollama"، تستخدم استدعاء وظيفة واحد، متسق: litellm.completion()
. تتولى "LiteLLM" تعقيد تحويل طلبك إلى التنسيق المحدد المطلوب من مزود النموذج المستهدف.
الميزات الرئيسية لـ "LiteLLM":
- واجهة موحدة: مكالمات API متسقة (
litellm.completion
،litellm.embedding
) عبر أكثر من 100 مزود LLM. - محايدة للمزود: تغيير سهل بين النماذج (على سبيل المثال، من
gpt-4o
إلىollama/llama3
) عن طريق تغيير سلسلة نموذج واحدة. - متانة: دعم مدمج للتوقيتات، وإعادة المحاولة، والنسخ الاحتياطي.
- قابلية المراقبة: تسجيلات مضمنة، استدعاءات راجعة، ودعم لمنصات مثل "Langfuse" و"Helicone" و"PromptLayer".
- خادم وكيل: توفير خادم وكيل مستقل لإدارة مفاتيح API المركزية، وتوازن الحمل، والتوجيه، والوصول المتسق عبر تطبيقات أو خدمات مختلفة.
- تتبع التكاليف: يساعد على مراقبة الإنفاق عبر واجهات برمجة تطبيقات LLM المختلفة.
لماذا استخدام "LiteLLM" مع "Ollama"؟
يوفر دمج "Ollama" و"LiteLLM" عدة مزايا:
- التقييس: اكتب منطق التطبيق باستخدام واجهة "LiteLLM" القياسية، مما يتيح لك التبديل بسلاسة بين نموذج "Ollama" المحلي (للتطوير، والخصوصية، والاستخدام غير المتصل) ونموذج سحابي قوي (للإنتاج، والقدرات المحددة) دون إعادة كتابة الكود الأساسي.
- تكامل محلي مبسط: تجعل "LiteLLM" التفاعل مع واجهة برمجة تطبيقات "Ollama" مباشراً داخل تطبيقات بايثون الخاصة بك، وتعالج تنسيق الطلب وتحليل الاستجابة.
- مرونة: جرب بسهولة نماذج محلية مختلفة متاحة عبر "Ollama" فقط بتغيير اسم النموذج في استدعاء "LiteLLM" الخاص بك (على سبيل المثال،
ollama/llama3
مقابلollama/mistral
). - استغلال ميزات "LiteLLM": الاستفادة من ميزات "LiteLLM" مثل إعادة المحاولة، والنسخ الاحتياطي، والتسجيل، وتتبع التكاليف، حتى عند استخدام نماذج "Ollama" المحلية.
- أساليب هجينة: بناء تطبيقات يمكنها توجيه الطلبات بذكاء إما إلى نماذج "Ollama" المحلية أو واجهات برمجة التطبيقات البعيدة استناداً إلى عوامل مثل التكلفة، والتأخير، أو متطلبات المهمة، وكلها تدار من خلال "LiteLLM" (خصوصاً عبر وكيلها).
التحضير لاستخدام "LiteLLM" و"Ollama"
قبل أن نبدأ، تأكد من تثبيت الأدوات اللازمة وإعدادها.
"LiteLLM" هي مكتبة بايثون، لذا تحتاج إلى تثبيت بايثون على نظامك. يتطلب "LiteLLM" بايثون 3.8 أو أعلى.
- تحقق من التثبيت: افتح الطرفية أو موجه الأوامر الخاص بك وقم بتشغيل:
python --version
# أو
python3 --version
- التثبيت: إذا لم يكن لديك بايثون أو تحتاج إلى إصدار أحدث، قم بتنزيله من موقع بايثون الرسمي (python.org) أو استخدم مدير حزم مثل Homebrew (macOS)، apt (Debian/Ubuntu)، أو Chocolatey (Windows).
- Pip: تأكد من أن لديك
pip
، مثبت حزم بايثون. وعادة ما يأتي مع بايثون. يمكنك التحقق من ذلك باستخدامpip --version
أوpip3 --version
.
تثبيت وإعداد "Ollama"
تحتاج إلى تثبيت "Ollama" وتشغيلها على نفس الجهاز الذي تخطط لتشغيل كود "LiteLLM" بايثون الخاص بك عليه (أو الوصول إليها عبر الشبكة إذا كانت تعمل على جهاز مختلف).
- تنزيل وتثبيت: زر موقع "Ollama" (ollama.com) وقم بتنزيل المثبت لنظام التشغيل لديك (macOS، Linux، Windows). اتبع تعليمات التثبيت.
- تحقق من التثبيت: بعد التثبيت، افتح نافذة طرفية جديدة وقم بتشغيل:
ollama --version
يجب أن تعرض هذه النسخة المثبتة من "Ollama".
سحب نموذج "Ollama"
تحتاج "Ollama" إلى تنزيل نموذج واحد على الأقل لتكون قادرة على خدمة الطلبات. دعنا نسحب نموذجاً شائعاً مثل "Llama 3" (نسخة تعليمية 8B).
- أمر السحب: في الطرفية الخاصة بك، قم بتشغيل:
ollama pull llama3
سيؤدي ذلك إلى تنزيل ملفات نموذج "Llama 3". قد يستغرق ذلك بعض الوقت اعتماداً على سرعة اتصالك بالإنترنت وحجم النموذج. يمكنك استبدال llama3
بنماذج أخرى متاحة في مكتبة "Ollama" (مثل mistral
، phi3
، gemma:2b
). تحقق من موقع "Ollama" للحصول على قائمة كاملة.
تثبيت "LiteLLM"
مع إعداد بايثون و"Ollama"، قم بتثبيت "LiteLLM" باستخدام pip.
- أمر التثبيت: افتح الطرفية أو موجه الأوامر الخاص بك وقم بتشغيل:
pip install litellm
# أو إذا كنت تستخدم pip3
# pip3 install litellm
- التحقق (اختياري): يمكنك التحقق من التثبيت عن طريق استيراد "LiteLLM" في مفسر بايثون:
python # أو python3
>>> import litellm
>>> litellm.__version__
# يجب أن تظهر هذه النسخة المثبتة بدون أخطاء.
>>> exit()
تشغيل "Ollama" محلياً
تحتاج "LiteLLM" إلى الاتصال بخادم API "Ollama". يجب عليك التأكد من تشغيل "Ollama".
التحقق من تشغيل "Ollama"
- تطبيقات سطح المكتب لـ macOS/Windows: إذا قمت بتثبيت التطبيق المكتبي، فإن "Ollama" عادة ما تعمل تلقائياً في الخلفية بعد التثبيت. يجب أن ترى رمز "Ollama" في شريط القائمة (macOS) أو في منطقة النظام (Windows).
- Linux / بدء يدوي: على Linux، أو إذا كنت تفضل التحكم اليدوي، قد تحتاج إلى بدء خادم "Ollama" صراحة. افتح طرفية وقم بتشغيل:
ollama serve
سيبدأ هذا الأمر الخادم، وعادة ما يستمر في العمل في نافذة الطرفية تلك حتى توقفه (Ctrl+C). قد ترغب في تشغيل هذا في الخلفية أو كخدمة نظام للاستخدام على المدى الطويل.
- تحقق من الحالة: يمكنك التحقق مما إذا كان الخادم يستجيب من خلال محاولة الوصول إلى نقطة النهاية الافتراضية الخاصة به باستخدام
curl
(إذا كان متاحاً) أو متصفح الويب:
curl http://localhost:11434
يجب أن تحصل على استجابة مثل Ollama is running
. إذا تلقيت خطأ "تم رفض الاتصال"، فمن المحتمل أن "Ollama" ليست قيد التشغيل أو أنها مُعدة على منفذ/عنوان مختلف.
بشكل افتراضي، تعرض "Ollama" واجهتها البرمجية على:
- URL:
http://localhost:11434
تم تكوين "LiteLLM" مسبقاً لمعرفة هذا العنوان الافتراضي. إذا كانت مثيل "Ollama" الخاص بك يعمل على مضيف أو منفذ مختلف (مثل داخل حاوية Docker مع تخطيط المنفذ، أو على خادم بعيد)، ستحتاج إلى إخبار "LiteLLM" بمكان العثور عليه (مغطى في قسم التكوين). بالنسبة لمعظم الإعدادات المحلية القياسية، يعمل الافتراضي من الصندوق.
قم بإجراء أول مكالمة "LiteLLM" إلى "Ollama"
الآن، دعنا نكتب سكريبت بايثون بسيط لإرسال طلب إلى نموذج llama3
الذي يعمل عبر "Ollama"، باستخدام "LiteLLM".
سكريبت بايثون الأساسي
قم بإنشاء ملف بايثون جديد (على سبيل المثال، ollama_test.py
) وأضف الكود التالي:
import litellm
import os
# اختياري: تعيين تسجيل مفصل لـ LiteLLM لرؤية ما يحدث
# litellm.set_verbose = True
# تحديد اسم النموذج - مهم: قم بالبادئة بـ "ollama/"
# تأكد من أن "llama3" هو النموذج الذي سحبته مع `ollama pull llama3`
model_name = "ollama/llama3"
# تحديد الرسائل لإكمال المحادثة
messages = [
{"role": "system", "content": "أنت مساعد مفيد."},
{"role": "user", "content": "لماذا السماء زرقاء؟"}
]
try:
print(f"--- إرسال الطلب إلى {model_name} ---")
# استدعاء وظيفة litellm.completion
response = litellm.completion(
model=model_name,
messages=messages
)
# طباعة الاستجابة
print("--- الاستجابة ---")
# يعكس كائن الاستجابة هيكل OpenAI
# للوصول إلى محتوى الرسالة على النحو التالي:
message_content = response.choices[0].message.content
print(message_content)
# يمكنك أيضاً طباعة كائن الاستجابة الكامل للفحص
# print("\n--- كائن الاستجابة الكامل ---")
# print(response)
except Exception as e:
print(f"حدث خطأ: {e}")
لنحلل الوظيفة:
litellm.completion()
: هذه هي الوظيفة الأساسية في "LiteLLM" لتوليد إكمالات النص (بما في ذلك إكمالات الطراز المحادثاتي).model
: يحدد هذا المعامل أي نموذج/مزود لاستخدامه. من المهم، بالنسبة لنماذج "Ollama"، أنك يجب أن تسبق اسم النموذج (كما تعرفه "Ollama") بـollama/
. لذا، فإنllama3
يصبحollama/llama3
، وmistral
يصبحollama/mistral
، وما إلى ذلك. هذا يخبر "LiteLLM" بتوجيه الطلب إلى نقطة نهاية متوافقة مع "Ollama".messages
: يتبع هذا تنسيق إكمال الدردشة القياسي لـ OpenAI - قائمة من القواميس، لكل منهاrole
(system
،user
، أوassistant
) وcontent
.- قيمة الإرجاع: يكافئ كائن
response
الذي عاد عن طريقlitellm.completion
هيكل كائن الرد API لـ OpenAI. تعتبر هذه الثبات ميزة رئيسية لـ "LiteLLM". يمكنك عادة الوصول إلى النص المولد عبرresponse.choices[0].message.content
.
مع وضع هذه النقاط في الاعتبار، دعنا نشغّل الوظيفة:
تأكد من أن "Ollama" تعمل (كما تم التحقق في الخطوة 4) وأن لديك نموذج llama3
محمولاً. ثم، قم بتشغيل السكريبت من الطرفية الخاصة بك:
python ollama_test.py
يجب أن ترى مخرجات مشابهة لما يلي (النص الدقيق سيتغير بناءً على استجابة النموذج):
--- إرسال الطلب إلى ollama/llama3 ---
--- الاستجابة ---
تظهر السماء زرقاء بسبب ظاهرة تُعرف باسم تشتت رايلي. يتكون ضوء الشمس الذي يصل إلى الغلاف الجوي للأرض من ألوان مختلفة من الضوء، والتي لها أطوال موجية مختلفة. يحتوي الضوء الأزرق والبنفسجي على أطوال موجية أقصر، بينما يحتوي الضوء الأحمر والبرتقالي على أطوال موجية أطول.
بينما يسافر ضوء الشمس عبر الغلاف الجوي، يتصادم مع جزيئات الغاز الصغيرة (معظمها نيتروجين وأكسجين). تشتت هذه الجزيئات ضوء الشمس في جميع الاتجاهات. تشتت الأطوال الموجية الأقصر (الأزرق والبنفسجي) بشكل أكثر فعالية من الأطوال الموجية الأطول (الأحمر والبرتقالي).
تكون أعيننا أكثر حساسية للون الأزرق من البنفسجي، ويتم امتصاص بعض الضوء البنفسجي في أعلى الغلاف الجوي، لذا ندرك أن السماء زرقاء في الغالب خلال النهار عندما تكون الشمس عالية.
عند شروق الشمس وغروبها، يمر ضوء الشمس عبر مزيد من الغلاف الجوي ليصل إلى أعيننا. يتم تشتت معظم الضوء الأزرق بعيداً، مما يسمح لوصول المزيد من الضوء الأحمر والبرتقالي ذي الطول الموجي الأطول، وهو السبب في أن الشروق والغروب غالباً ما يبدوان محمرين أو برتقاليين.
تهانينا! لقد استخدمت بنجاح "LiteLLM" للتواصل مع نموذج "Ollama" المحلي الخاص بك.
قم بإجراء استجابات متدفقة
بالنسبة لتطبيقات التفاعل (مثل الروبوتات الدردشة) أو عند توليد استجابات طويلة، قد يؤدي انتظار الإكمال الكامل إلى تجربة مستخدم سيئة. يسمح التدفق لك بتلقي الاستجابة توكن بتوكن أثناء توليدها. تجعل "LiteLLM" هذا سهلاً.
لماذا التدفق؟
- تحسين الأداء المدرك: يرى المستخدمون المخرجات على الفور، مما يجعل التطبيق يبدو أكثر استجابة.
- معالجة الاستجابات الطويلة: معالجة أجزاء من الاستجابة دون الانتظار للكل، مفيد لتوليد النصوص الطويلة جداً.
- التفاعل في الوقت الفعلي: يتيح إنشاء واجهات محادثة في الوقت الفعلي.
تنفيذ التدفق مع "LiteLLM"
قم بتعديل السكريبت السابق (ollama_test.py
) لتمكين التدفق:
import litellm
import os
# litellm.set_verbose = True # اختياري للتصحيح
model_name = "ollama/llama3"
messages = [
{"role": "system", "content": "أنت شاعر مختصر."},
{"role": "user", "content": "اكتب هايكو قصير عن قطة."}
]
try:
print(f"--- إرسال الطلب المتدفق إلى {model_name} ---")
# تعيين stream=True
response_stream = litellm.completion(
model=model_name,
messages=messages,
stream=True # تمكين التدفق
)
print("--- الاستجابة المتدفقة ---")
full_response = ""
# التكرار عبر قطع التدفق
for chunk in response_stream:
# كل قطعة تشبه هيكل القطعة المتدفقة لـ OpenAI
# للوصول إلى دلتا المحتوى هكذا:
content_delta = chunk.choices[0].delta.content
if content_delta: # تحقق مما إذا كان هناك محتوى جديد في هذه القطعة
print(content_delta, end="", flush=True) # طباعة فورية بدون سطر جديد
full_response += content_delta
print("\n--- نهاية التدفق ---")
# print(f"\nالاستجابة الكاملة المعاد بنائها:\n{full_response}") # اختياري: عرض الاستجابة الكاملة في النهاية
except Exception as e:
print(f"\nحدث خطأ: {e}")
التغييرات:
stream=True
: تمت إضافة هذه المعلمة إلى استدعاءlitellm.completion
.- التكرار: الآن تعيد الوظيفة متسلسلاً (
response_stream
). نقوم بالتكرار عبر هذا المتسلسل. - التعامل مع القطع: كل
chunk
في الحلقة يمثل جزءً صغيرًا من الاستجابة. نحن نصل إلى الجزء النصي الجديد باستخدامchunk.choices[0].delta.content
. تحتوي الخاصيةdelta
على الفرق عن القطعة السابقة (عادةً ما تكون بضع أحرف أو كلمة). print(..., end="", flush=True)
: يطبع محتوى القطعة على الفور دون إضافة سطر جديد، مع تفريغ المخزن المؤقت للإخراج للتأكد من ظهوره في الطرفية على الفور.
قم بتشغيل هذا السكريبت المحدث:
python ollama_test.py
سترى الهايكو يظهر كلمة بكلمة أو حرف بحرف في الطرفية الخاصة بك، مما يُظهر سلوك التدفق.
تكوين إعداد "LiteLLM" + "Ollama"
بينما تعمل "LiteLLM" مع إعدادات "Ollama" الافتراضية من الصندوق، قد تحتاج إلى تكوينها إذا كان إعدادك ينحرف عن القياسي http://localhost:11434
.
السلوك الافتراضي (localhost)
كما تم ذكره، تفترض "LiteLLM" تلقائياً أن "Ollama" تعمل على http://localhost:11434
عند استخدام بادئة ollama/
. إذا كان هذا هو إعدادك، فلا حاجة لتكوين إضافي.
استخدام متغيرات البيئة (اختياري)
إذا كانت "Ollama" تعمل على مضيف أو منفذ مختلف، يمكنك إخبار "LiteLLM" بمكان العثور عليها باستخدام متغيرات البيئة. تقوم "LiteLLM" بالتحقق من متغيرات البيئة المحددة لتكوين نقاط النهاية للـ API. بالنسبة لنموذج "Ollama" محدد (أو جميع نماذج "Ollama" إذا كنت ترغب في تجاوز عام)، يمكنك تعيين عنوان URL الأساسي الخاص به.
على سبيل المثال، إذا كانت مثيل "Ollama" لديك تعمل على http://192.168.1.100:11434
، يمكنك تعيين متغير بيئة قبل تشغيل السكريبت بايثون الخاص بك:
Linux/macOS:
export OLLAMA_API_BASE="http://192.168.1.100:11434"
python your_script.py
Windows (موجه الأوامر):
set OLLAMA_API_BASE=http://192.168.1.100:11434
python your_script.py
Windows (PowerShell):
$env:OLLAMA_API_BASE = "http://192.168.1.100:11434"
python your_script.py
الآن، عندما يستدعي سكريبتك litellm.completion(model="ollama/llama3", ...)
، ستبحث "LiteLLM" عن متغير البيئة OLLAMA_API_BASE
وتستخدم تلك العنوان URL بدلاً من الافتراضي localhost
.
ملاحظة: تعيين OLLAMA_API_BASE
يتجاوز عنوان URL الأساسي لجميع النماذج التي تبدأ بـ ollama/
. استشر وثائق "LiteLLM" لمزيد من تحكمات متغير البيئة المفصلة إذا لزم الأمر (مثل: تعيين عنوان URL الأساسي لاسم نموذج محدد).
استخدام ملف تكوين (اختياري)
لإعدادات أكثر تعقيدًا تتضمن عدة نماذج، وإعدادات مخصصة، أو لتجنب متغيرات البيئة، تدعم "LiteLLM" ملف تكوين (config.yaml
أو مسار محدد).
قم بإنشاء ملف config.yaml
في نفس الدليل مثل سكريبتك (أو في مكان آخر، وأشر لـ "LiteLLM" إليه):
# config.yaml
model_list:
- model_name: ollama/llama3 # الاسم الذي تستخدمه في litellm.completion
litellm_params:
model: ollama/llama3 # المعرف الفعلي للنموذج لمزود
api_base: "http://localhost:11434" # الافتراضي، قم بتغييره إذا لزم الأمر
- model_name: ollama/mistral-remote # مثال: اسم مستعار لنموذج "Ollama" عن بُعد
litellm_params:
model: ollama/mistral # يتوقع "Ollama" 'mistral'
api_base: "http://192.168.1.100:11434"
- model_name: gpt-4o-mini # مثال: تضمين نموذج غير "Ollama"
litellm_params:
model: gpt-4o-mini
api_key: "os.environ/OPENAI_API_KEY" # اقرأ بأمان من متغير البيئة
general_settings:
# اختياري: إعداد إعدادات عامة مثل المهلات
# timeout: 300 # 5 دقائق
# يمكنك أيضًا تعريف متغيرات البيئة المخصصة ضمن التكوين
environment_variables:
OPENAI_API_KEY: "" # تعريف عناصر نائب أو مفاتيح فعلية (أقل أمانًا)
لاستخدام هذا الملف التكويني، تحتاج إلى إخبار "LiteLLM" بتحميله، عادةً في بداية تطبيقك:
import litellm
import os
# تحميل التكوين من config.yaml في الدليل الحالي
# يمكنك أيضًا تقديم مسار مطلق: litellm.load_config("path/to/your/config.yaml")
try:
litellm.load_config()
print("تم تحميل تكوين LiteLLM بنجاح.")
except Exception as e:
print(f"تحذير: لم يتمكن من تحميل تكوين LiteLLM. باستخدام القيم الافتراضية. خطأ: {e}")
# الآن يمكن استخدام أسماء النماذج المحددة في التكوين
try:
# استخدام النموذج القياسي ollama/llama3 الذي قد يلتقط ال api_base من التكوين
response_local = litellm.completion(model="ollama/llama3", messages=[{"role": "user", "content": "اختبار محلي"}])
print("استجابة Llama3 المحلية:", response_local.choices[0].message.content[:50], "...") # طباعة مقتطف
# استخدام الاسم المستعار المحدد لنموذج "mistral" البعيد
# response_remote = litellm.completion(model="ollama/mistral-remote", messages=[{"role": "user", "content": "اختبار بعيد"}])
# print("استجابة Mistral البعيدة:", response_remote.choices[0].message.content[:50], "...")
except Exception as e:
print(f"حدث خطأ أثناء الإكمال: {e}")
يوفر ملف التكوين طريقة منظمة لإدارة الإعدادات لعدة نماذج، بما في ذلك مثيلات "Ollama" التي تعمل ربما على آلات مختلفة.
بجانب المكالمات الأساسية والتدفق، تقدم "LiteLLM" ميزات تعزز المتانة وقابلية المراقبة، والتي تعمل بسلاسة مع "Ollama".
تسمية النماذج المستعار
بينما يتيح لك ملف التكوين تعريف الأسماء المستعارة، يمكنك أيضاً تسجيلها بشكل برمجي. هذا مفيد لتبسيط أسماء النماذج أو ربط أسماء عامة بنماذج "Ollama" محددة.
import litellm
# تعريف اسم مستعار: ربط "my-local-llm" إلى "ollama/llama3"
litellm.register_model({
"my-local-llm": {
"model": "ollama/llama3",
# يمكنك أيضاً تحديد api_base هنا إذا لزم الأمر لهذا الاسم المستعار بالتحديد
# "api_base": "http://localhost:11434"
}
})
# الآن استخدم الاسم المستعار في استدعاء الإكمال الخاص بك
messages = [{"role": "user", "content": "أخبرني عن تسميات النماذج."}]
response = litellm.completion(model="my-local-llm", messages=messages)
print(response.choices[0].message.content)
التعامل مع الأخطاء وإعادة المحاولة
يمكن أن تحدث مشاكل مؤقتة في الشبكة أو مشاكل في "Ollama". تحتوي "LiteLLM" على منطق إعادة محاولة مضمن.
import litellm
import time
# مثال: جعل "Ollama" غير متاحة مؤقتاً (مثل، توقف "ollama serve")
print("إيقاف "Ollama" لمدة 10 ثواني (إذا أمكن)... قد تحتاج إلى القيام بذلك يدوياً.")
# os.system("ollama stop") # قد لا يكون هذا الأمر موجودًا؛ التوقف اليدوي أكثر أمانًا
# time.sleep(10)
# print("إعادة تشغيل "Ollama"... قد تحتاج إلى القيام بذلك يدوياً.")
# os.system("ollama serve &") # البدء في الخلفية
# time.sleep(5) # اعطها وقتًا للإقلاع
messages = [{"role": "user", "content": "هل تعمل إعادة المحاولة؟"}]
try:
# ستقوم "LiteLLM" تلقائياً بإعادة المحاولة على أخطاء الاتصال المحددة
# يمكنك تكوين عدد إعادة المحاولات، عامل البايس، وما إلى ذلك.
response = litellm.completion(
model="ollama/llama3",
messages=messages,
num_retries=3, # محاولة حتى 3 إعادة محاولات
timeout=10 # تعيين مهلة لكل محاولة طلب (بالثواني)
)
print("نجاح بعد إعادة المحاولات (أو في المحاولة الأولى):")
print(response.choices[0].message.content)
except Exception as e:
# سيقوم هذا بالتقاط الأخطاء التي تستمر بعد إعادة المحاولات (مثل: النموذج غير موجود، خطأ في التكوين)
# أو إذا فشلت جميع إعادة المحاولات لأخطاء الاتصال.
print(f"حدث خطأ بعد إعادة المحاولات: {e}")
تعيد "LiteLLM" بذكاء محاولة التشغيل لأخطاء الشبكة المؤقتة الشائعة. يمكنك تخصيص سلوك إعادة المحاولة عالمياً أو لكل مكالمة.
التسجيل والاستدعاءات
توفر "LiteLLM" نقاط توصيل لتسجيل بيانات الطلب/الاستجابة أو لتحفيز وظائف مخصصة (استدعاءات راجعة) عند المكالمات الناجحة أو الأخطاء. هذا لا يقدر بثمن للمتابعة، وتصحيح الأخطاء، وتتبع التكاليف (على الرغم من أن تتبع التكاليف أقل صلة بـ "Ollama" إلا إذا قمت بتعيين تكاليف افتراضية).
import litellm
import logging
# تكوين تسجيل بسيط
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
logger = logging.getLogger(__name__)
# تعريف وظيفة استدعاء راجعة بسيطة عند النجاح
def log_success(kwargs, completion_response, start_time, end_time):
"""يسجل التفاصيل حول مكالمة LLM الناجحة."""
model = kwargs.get("model", "unknown_model")
input_text = kwargs.get("messages", [])[-1]['content'] if kwargs.get("messages") else "N/A"
output_text = completion_response.choices[0].message.content[:50] + "..." # مقتطف
duration = (end_time - start_time).total_seconds()
logger.info(f"نجاح! النموذج: {model}, المدة: {duration:.2f}s, المدخل: '{input_text[:30]}...', المخرجات: '{output_text}'")
# تعريف وظيفة استدعاء راجعة بسيطة عند الفشل
def log_failure(kwargs, exception, start_time, end_time):
"""يسجل التفاصيل حول مكالمة LLM التي فشلت."""
model = kwargs.get("model", "unknown_model")
duration = (end_time - start_time).total_seconds()
logger.error(f"فشل! النموذج: {model}, المدة: {duration:.2f}s, الخطأ: {exception}")
# تسجيل الاستدعاءات مع "LiteLLM"
litellm.success_callback = [log_success]
litellm.failure_callback = [log_failure]
# الآن قم بإجراء مكالمة - ستحدث الاستدعاءات تلقائياً
messages = [{"role": "user", "content": "كيف تعمل الاستدعاءات في "LiteLLM"؟"}]
try:
response = litellm.completion(model="ollama/llama3", messages=messages)
# print(response.choices[0].message.content) # يمكنك استخدام الاستجابة
except Exception as e:
pass # لقد تعامل استدعاء الفشل بالفعل مع تسجيل
# مثال على مكالمة قد تفشل (مثل: النموذج غير محمول)
# try:
# response_fail = litellm.completion(model="ollama/nonexistent-model", messages=messages)
# except Exception as e:
# pass # سيسجل استدعاء الفشل
قم بتشغيل هذا السكريبت، وسترى رسائل INFO أو ERROR تم تسجيلها بواسطة وظائف الاستدعاء الخاصة بك، مما يوفر رؤية في تفاعلات LLM. تتكامل "LiteLLM" أيضًا مع منصات مثل "Langfuse" و"Helicone" و"PromptLayer"، وما إلى ذلك، من أجل المزيد من القابلية للمراقبة المتقدمة.
إدارة مفاتيح API
بينما لا تتطلب "Ollama" عادةً مفاتيح API للوصول المحلي، إذا كانت تطبيقك يستخدم أيضاً مزودين سحابيين (مثل "OpenAI"، "Anthropic"، إلخ) عبر "LiteLLM"، ستحتاج إلى إدارة تلك المفاتيح. تبحث "LiteLLM" عن المفاتيح في متغيرات البيئة القياسية (مثل OPENAI_API_KEY
، ANTHROPIC_API_KEY
) أو يمكن تعيينها في config.yaml
أو تمريرها مباشرة إلى استدعاء completion
(أقل توصية لأسباب أمنية). يعد استخدام config.yaml
أو متغيرات البيئة النهج المفضل.
كيفية استخدام خادم وكيل LiteLLM (موصى به للمتانة)
بينما يعد استخدام مكتبة litellm
مباشرة في كود بايثون الخاصة بك رائعًا للسكريبتات البسيطة أو التطبيقات الفردية، يوفر وكيل LiteLLM حلاً أكثر متانة وقابلية للتوسع، خاصةً للميكروسيرفيسات أو عندما تحتاج عدة تطبيقات إلى الوصول إلى LLMs (بما في ذلك "Ollama").
ما هو وكيل LiteLLM؟
وكيل LiteLLM هو خادم مستقل يمكنك تشغيله بشكل منفصل. تقوم تطبيقاتك بعد ذلك بإجراء طلبات API متوافقة مع OpenAI إلى نقطة نهاية الوكيل. يتولى الوكيل، المُكون بتفاصيل نموذجك (بما في ذلك مثيلات "Ollama" ومفاتيح API لمقدمي السحابة، إلخ)، توجيه الطلب إلى LLM الصحيح، إدارة المفاتيح، تطبيق حدود المعدل، والتسجيل، وإعادة المحاولة، والمزيد.
إعداد الوكيل مع "Ollama"
تثبيت اعتمادات الوكيل:
pip install 'litellm[proxy]'
إنشاء ملف تكوين الوكيل (proxy_config.yaml
):
يخبر هذا الملف الوكيل بنماذجك المتاحة.
# proxy_config.yaml
model_list:
- model_name: local-llama3 # كيف سيقوم المستخدمون باستدعاء هذا النموذج عبر الوكيل
litellm_params:
model: ollama/llama3 # تخبر الوكيل أن هذا يستخدم سائق "ollama" لـ 'llama3'
api_base: "http://localhost:11434" # تأكد من أن هذا يشير إلى "Ollama" الخاصة بك
- model_name: local-mistral
litellm_params:
model: ollama/mistral
api_base: "http://localhost:11434" # بافتراض نفس مثيل "Ollama"
# مثال: إضافة نموذج OpenAI إلى جانب "Ollama"
- model_name: cloud-gpt4o
litellm_params:
model: gpt-4o-mini
api_key: "os.environ/OPENAI_API_KEY" # يقرأ الوكيل متغير البيئة
litellm_settings:
# اختياري: تعيين إعدادات على مستوى الوكيل
# drop_params: True # يزيل المعلمات غير المدعومة قبل الإرسال إلى النموذج
# set_verbose: True # تمكين تسجيل تفصيلي للوكيل
pass
# environment_variables: # تعريف متغيرات البيئة للوكيل إذا لزم الأمر
# OPENAI_API_KEY: "your_openai_key_here" # أقل أمان - يفضل استخدام متغيرات البيئة الحقيقية
تشغيل خادم الوكيل:
افتح طرفية، تأكد من تعيين متغير البيئة OPENAI_API_KEY
الخاص بك (إذا كنت تستخدم نماذج OpenAI)، وتشغيل:
litellm --config /path/to/proxy_config.yaml --port 8000
# استبدل /path/to/proxy_config.yaml بالمسار الفعلي
# --port 8000 يحدد المنفذ الذي يستمع إليه الوكيل (الافتراضي هو 4000)
سيبدأ خادم الوكيل وسيسجل المعلومات، مما يشير إلى أنه جاهز لتلقي الطلبات.
إجراء مكالمات عبر الوكيل
الآن، بدلاً من استخدام litellm.completion
مباشرة، يقوم كود التطبيق الخاص بك (الذي يمكن أن يكون حتى بلغة مختلفة) بإجراء مكالمات API قياسية إلى نقطة نهاية الوكيل (http://localhost:8000
في هذا المثال). يمكنك استخدام مكتبة openai
بايثون أو requests
بسيطة.
استخدام مكتبة openai
:
أولاً، قم بتثبيتها: pip install openai
import openai
import os
# توجيه عميل OpenAI إلى نقطة نهاية وكيل LiteLLM
client = openai.OpenAI(
base_url="http://localhost:8000", # عنوان URL لوكيل LiteLLM الخاص بك
api_key="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # مطلوبة من عميل OpenAI، لكن وكيل LiteLLM يتجاهلها افتراضياً
)
# تحديد الرسائل
messages = [
{"role": "system", "content": "أنت مساعد مدعوم بالوكيل."},
{"role": "user", "content": "اشرح فائدة استخدام وكيل لاستدعاءات LLM."}
]
try:
print("--- إرسال الطلب عبر وكيل LiteLLM ---")
# استخدم اسم النموذج المحدد في proxy_config.yaml ('local-llama3')
response = client.chat.completions.create(
model="local-llama3", # استخدام الاسم المستعار من proxy_config.yaml
messages=messages,
stream=False # تعيين إلى True للتدفق عبر الوكيل
)
print("--- الاستجابة من الوكيل ---")
print(response.choices[0].message.content)
# مثال على التدفق عبر الوكيل
print("\n--- التدفق عبر الوكيل ---")
stream_response = client.chat.completions.create(
model="local-llama3",
messages=messages,
stream=True
)
for chunk in stream_response:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="", flush=True)
print("\n--- نهاية التدفق ---")
except openai.APIConnectionError as e:
print(f"خطأ في الاتصال: لم نتمكن من الاتصال بوكيل LiteLLM في {client.base_url}. هل هو قيد التشغيل؟")
except openai.APIStatusError as e:
print(f"خطأ في API: Status={e.status_code}, Response={e.response}")
except Exception as e:
print(f"حدث خطأ غير متوقع: {e}")