مراقبة تطبيقات الذكاء الاصطناعي بـLangfuse على سيرفرك

سجلات التطبيق العادية لا تخبرك لماذا أجاب النموذج خطأً ولا كم كلّفك الطلب. Langfuse يتتبع كل استدعاء بمدخلاته ومخرجاته وزمنه وكلفته، ويعمل بـDocker Compose على سيرفر بـ4 أنوية و16GB، فتبقى المحادثات الحساسة داخل المملكة.
Langfuse منصة مفتوحة المصدر لمراقبة تطبيقات النماذج اللغوية، تسجّل كل طلب يمر على تطبيقك كـ"أثر" (trace) كامل: السؤال الذي كتبه المستخدم، والمقاطع التي جلبها نظام RAG، والتعليمات التي أُرسلت للنموذج، والجواب، وعدد التوكنات، والزمن، والكلفة. السبب الذي يجعلك تحتاجه: سجلات التطبيق العادية تقول لك إن الطلب نجح برمز 200 خلال 4 ثوانٍ، لكنها لا تقول لك إن الجواب كان خاطئاً لأن البحث جلب سياسة إجازات قديمة من 2023، ولا أن طلباً واحداً كلّف 40 هللة لأن أحدهم ألصق مستنداً من 30 صفحة. الجواب المختصر لطريقة التشغيل: انسخ مستودع Langfuse الرسمي، غيّر الأسرار المعلّمة في ملف docker-compose.yml، وشغّل docker compose up -d على سيرفر بـ4 أنوية و16GB ذاكرة، ثم أضف ثلاثة متغيرات بيئة ومزخرف @observe لدوال تطبيقك. خلال ساعة ترى كل طلب مفصّلاً خطوة بخطوة، مع لوحة كلفة لكل يوم ولكل مستخدم. لأن المحادثات تحتوي غالباً بيانات عملاء وأسئلة داخلية حساسة، فتشغيل Langfuse على سيرفر سعودي بدل النسخة السحابية الخارجية يحل مشكلة أين تُخزّن هذه البيانات من الأساس.
لماذا لا تكفي السجلات العادية
تطبيق الذكاء الاصطناعي ليس دالة واحدة، بل سلسلة: تضمين السؤال، ثم بحث في قاعدة المتجهات، ثم إعادة ترتيب، ثم بناء التعليمة، ثم استدعاء النموذج، وأحياناً استدعاء أداة ثم استدعاء النموذج مرة ثانية. حين يشتكي موظف من جواب سيئ، تحتاج أن ترى السلسلة كاملة لتعرف أين انكسرت. هناك أربعة أسئلة لا تجيب عنها سجلات Nginx أو Laravel:
- ماذا رأى النموذج فعلاً؟ النص الكامل للتعليمة بعد إدراج المقاطع، لا السؤال الأصلي فقط.
- أين ذهب الوقت؟ هل الثواني الست في البحث أم في توليد 900 توكن؟
- كم كلّف هذا الطلب؟ توكنات الإدخال والإخراج مضروبة في سعر النموذج.
- هل الجواب جيد؟ تقييم المستخدم بإبهام لأعلى أو لأسفل، أو تقييم آلي بنموذج آخر.
Langfuse يجيب عن الأربعة في شاشة واحدة، ويجمعها حسب المستخدم والجلسة ونسخة التعليمة، فتقارن مثلاً بين نسخة 3 ونسخة 4 من تعليمة النظام على 500 طلب حقيقي.
ماذا يحتاج التشغيل بالأرقام
النسخة الحالية من Langfuse (الإصدار 3) ليست حاوية واحدة، بل ست خدمات: تطبيق الويب، وعامل خلفي (worker)، وPostgreSQL للبيانات الوصفية والمستخدمين، وClickHouse لتخزين الآثار والتحليلات، وRedis للطوابير، وMinIO كتخزين كائنات متوافق مع S3 للأحداث الخام. ملف Docker Compose الرسمي يشغّلها كلها معاً، والتوصية الرسمية للتشغيل على سيرفر واحد 4 أنوية و16GB ذاكرة على الأقل، لأن ClickHouse وحده يستهلك من 3 إلى 6GB تحت الحِمل.
| الحِمل | المواصفات | الخيار على كلاود | السنوي شامل الضريبة |
|---|---|---|---|
| تجربة وفريق صغير، حتى 20 ألف أثر يومياً | 4 vCPU / 8GB | باقة أعمال | 11,500 ريال |
| إنتاج متوسط، حتى 100 ألف أثر يومياً | 4 vCPU / 16GB | أعمال + 4 إضافات RAM (8GB) | 13,900 ريال |
| إنتاج أكبر مع احتفاظ طويل | 8 vCPU / 16GB + 200GB | مؤسسة + 2 إضافة SSD | 19,000 ريال |
الحساب في الصف الثاني: باقة أعمال 11,500 ريال مع أربع إضافات ذاكرة كل واحدة 2GB بـ600 ريال، أي 2,400 ريال، فالمجموع 13,900 ريال سنوياً. التخزين يكبر مع الأثر: كل أثر RAG متوسط يأخذ من 5 إلى 20KB بعد ضغط ClickHouse، فمئة ألف أثر يومياً تعني نحو 1GB في اليوم قبل الضغط الإضافي، وهنا تحتاج سياسة احتفاظ واضحة.
التشغيل خطوة بخطوة
على خادم سحابي بـUbuntu 24.04 وDocker مثبت:
git clone https://github.com/langfuse/langfuse.git
cd langfuse
# غيّر كل قيمة بجانبها التعليق CHANGEME
grep -n CHANGEME docker-compose.yml
openssl rand -hex 32 # لـENCRYPTION_KEY
openssl rand -base64 32 # لـNEXTAUTH_SECRET و SALT
docker compose up -d
docker compose ps
لا تتجاوز خطوة الأسرار. كلمات المرور الافتراضية في الملف معروفة للجميع، وأي خدمة منها مكشوفة على الإنترنت تعني أن محادثات شركتك مقروءة. الأهم أن المنافذ الداخلية (5432 لـPostgreSQL و8123 لـClickHouse و6379 لـRedis و9000 لـMinIO) لا يجب أن تُنشر على الواجهة العامة أبداً. اربط واجهة الويب على 127.0.0.1:3000 وضعها خلف Nginx بشهادة SSL، وعطّل التسجيل الذاتي بمتغير AUTH_DISABLE_SIGNUP=true بعد إنشاء أول حساب، ثم أضف أعضاء الفريق بالدعوة.
server {
server_name langfuse.example.sa;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
ربطه بتطبيق RAG
من واجهة Langfuse أنشئ مشروعاً وخذ مفتاحيه العام والسري، ثم في تطبيقك:
pip install langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_HOST=https://langfuse.example.sa
from langfuse import observe
@observe()
def retrieve(question: str) -> list[str]:
return vector_search(question, k=5)
@observe(as_type="generation")
def answer(question: str, chunks: list[str]) -> str:
return llm.chat(build_prompt(question, chunks))
@observe()
def rag(question: str) -> str:
return answer(question, retrieve(question))
كل استدعاء لـrag ينتج أثراً واحداً فيه خطوتان متداخلتان، ترى في كل منهما المدخلات والمخرجات والمدة. إن كنت تستخدم مكتبة OpenAI أو LangChain أو LlamaIndex، فلـLangfuse تكاملات جاهزة تلتقط التوكنات والنموذج تلقائياً بسطر استيراد واحد. أضف معرّف المستخدم ومعرّف الجلسة للأثر، فتستطيع لاحقاً فتح كل ما سأله موظف معين حين يبلّغ عن مشكلة.
إخفاء البيانات الحساسة قبل الحفظ
حتى على سيرفرك، لا داعي لتخزين أرقام الهوية والجوالات كما هي. يدعم SDK دالة إخفاء (mask) تمر على كل مدخل ومخرج قبل الإرسال، فاستبدل فيها أي رقم من 10 خانات يبدأ بـ1 أو 2 برمز ثابت، وأي جوال يبدأ بـ05 بنفس الطريقة.
الكلفة بالريال لكل طلب
Langfuse يحسب الكلفة من جدول أسعار النماذج بالدولار، ويمكنك تعريف نماذجك الخاصة بسعر لكل توكن. للنماذج السحابية اضرب في 3.75 لتحصل على الريال، أو عرّف السعر مباشرة بعد التحويل. للنموذج المحلي عبر Ollama الحساب مختلف: الكلفة ثابتة لأنها السيرفر نفسه. سيرفر بـ18,000 ريال سنوياً يكلّف نحو 49 ريالاً في اليوم، فإن عالج 2 مليون توكن يومياً تكون الكلفة نحو 2.5 ريال لكل 100 ألف توكن، وكلما زاد الاستخدام نزلت كلفة الطلب الواحد. عرّف هذا السعر في Langfuse لتظهر لوحة واحدة تقارن الطلبات المحلية بالسحابية على نفس المقياس.
من لوحة Dashboards اعرض الكلفة مجمعة لكل يوم، ثم لكل شهر، ولكل مستخدم ولكل ميزة في تطبيقك، واضبط تنبيهاً حين يتجاوز مستخدم واحد 50 ريالاً في اليوم. هذا الرقم كافٍ غالباً لكشف سكربت يستدعي الواجهة في حلقة قبل أن يصلك كشف الحساب.
إدارة نسخ التعليمات
أغلب تحسينات تطبيقات RAG تأتي من تعديل تعليمة النظام لا من تغيير النموذج، والمشكلة أن التعليمة عادة نص مدفون في الكود، فكل تعديل يحتاج نشراً جديداً ولا أحد يتذكر أي نسخة كانت تعمل الأسبوع الماضي. Langfuse يضم قسماً لإدارة التعليمات: تحفظ التعليمة باسم ثابت مثل hr-assistant، وكل تعديل ينشئ نسخة مرقّمة، وتضع وسم production على النسخة المعتمدة. تطبيقك يجلب التعليمة بالاسم والوسم مع تخزين مؤقت محلي، فلا يضيف الجلب أكثر من بضعة ميلي ثوانٍ، وحين يعدّل مسؤول المحتوى صياغة التعليمة ينقل الوسم للنسخة الجديدة دون أن يلمس المطور الكود.
الفائدة الأكبر أن كل أثر يُربط تلقائياً برقم نسخة التعليمة التي استُخدمت فيه. فإذا نشرت النسخة 7 يوم الأحد ونزل متوسط التقييم من 0.82 إلى 0.71، ترى ذلك في لوحة واحدة وتعيد الوسم للنسخة 6 خلال دقيقة.
سياسة الاحتفاظ والنسخ الاحتياطي
الآثار تتراكم بسرعة، ولا قيمة كبيرة لأثر عمره سنة في الغالب. حدّد مدة احتفاظ تناسب حاجتك التشغيلية والتنظيمية، مثل 90 يوماً للآثار التفصيلية، مع إبقاء التقييمات والأرقام المجمعة مدة أطول. خذ نسخة احتياطية يومية من PostgreSQL بأمر pg_dump، ومن ClickHouse بأداة النسخ الخاصة به، واحفظها خارج السيرفر نفسه. إضافة النسخ الاحتياطي اليومي بـ7 أيام احتفاظ تكلّف 800 ريال سنوياً، وتغطي السيرفر كاملاً إن تعطل القرص أو حُذف مجلد بالخطأ.
قياس جودة الإجابات
الكلفة والزمن سهلان، أما الجودة فتحتاج قراراً. ابدأ بطريقتين: الأولى زر تقييم في واجهتك يرسل درجة 1 أو 0 مربوطة بمعرّف الأثر، والثانية تقييم آلي يستخدم نموذجاً لغوياً يقرأ السؤال والمقاطع والجواب ويحكم هل الجواب مستند للمقاطع أم مختلَق. Langfuse يشغّل هذه التقييمات على عينة، مثل 10% من الطلبات، فلا تتضاعف الكلفة. بعد أسبوعين سترى أي نوع من الأسئلة يحصل على أدنى تقييم، وغالباً تكتشف أن المشكلة في وثيقة ناقصة لا في النموذج.
لتشغيل النموذج المحلي نفسه على نفس البنية، راجع قوالب استضافة الذكاء الاصطناعي التي تأتي بـOllama وOpen WebUI مثبتين مسبقاً.
خطوات البدء
- جهّز سيرفراً بـ4 أنوية و16GB في الرياض، واختر الحجم من الأسعار والباقات.
- شغّل docker compose بعد تغيير كل قيم CHANGEME، واربط كل المنافذ على 127.0.0.1 ما عدا Nginx.
- أضف @observe لدوال البحث والتوليد، مع معرّف المستخدم والجلسة ودالة إخفاء للأرقام الحساسة.
- عرّف أسعار نماذجك بالريال، وتنبيهاً عند 50 ريالاً لكل مستخدم في اليوم.
- فعّل التقييم الآلي على 10% من الطلبات، وراجع أدنى الأسئلة تقييماً كل أسبوع.


