مراقبة أداء التطبيقات: تتبع استهلاك الرموز (Tokens) والتكلفة لكل مستخدم عبر LangSmith

دقائق القراءة: 5

لماذا تصبح مراقبة Tokens والتكلفة ضرورة هندسية وليست رفاهية؟

عند الانتقال من تجربة محلية بسيطة إلى تطبيق فعلي مبني على LangChain ويعتمد على LLMs، تظهر مشكلة تشغيلية أساسية: من يستهلك الموارد؟ وكم يكلف كل طلب؟ وكم تبلغ تكلفة كل مستخدم على حدة؟ هذه الأسئلة لا تتعلق بالمحاسبة فقط، بل تمس جودة المنتج، وسرعة الاستجابة، واستدامة البنية السحابية.

في الأنظمة التوليدية، لا تأتي التكلفة من عدد الطلبات فقط، بل من حجم prompt tokens وcompletion tokens، ومن طول السياق، واستدعاءات الأدوات، وعدد خطوات السلسلة Chain أو الوكيل Agent. لهذا السبب يبرز LangSmith كطبقة Observability تسمح بتتبع التنفيذ، وتحليل الكلفة، وربط كل عملية بالمستخدم أو الجلسة أو البيئة التشغيلية.

ما هو LangSmith داخل معمارية تطبيق الذكاء الاصطناعي؟

LangSmith ليس مجرد لوحة رسوم بيانية، بل هو نظام تتبع تشغيلي يسجل ما يحدث داخل التطبيق خطوة بخطوة. عند تنفيذ سلسلة مبنية عبر LangChain Chain أو نظام RAG أو وكيل يستخدم أدوات، يقوم بتخزين آثار التنفيذ Traces مع معلومات دقيقة مثل:

  • المدخلات والمخرجات لكل خطوة.
  • عدد tokens المستهلكة.
  • زمن الاستجابة latency.
  • النموذج المستخدم والإصدار.
  • البيانات الوصفية metadata مثل user_id وplan وfeature_name.

معمارياً، يوضع LangSmith بين منطق التطبيق وطبقة التحليل التشغيلي. التطبيق يرسل الطلب إلى مزود النموذج، لكن في الوقت نفسه يسجل أثر التنفيذ ويربطه بسياقه التجاري. بهذه الطريقة لا تبقى التكاليف أرقاماً عامة، بل تتحول إلى مؤشرات مفهومة على مستوى المستخدم والميزة والبيئة.

تدفق البيانات من طلب المستخدم إلى حساب التكلفة

المسار التشغيلي القياسي

  1. المستخدم يرسل سؤالاً من الواجهة أو من Chat UI.
  2. الخادم ينشئ طلباً يتضمن session_id وuser_id.
  3. إذا كان التطبيق يعتمد على دمج السياق المسترجع مع الـ LLM، تُسترجع المقاطع ذات الصلة من قاعدة متجهة عبر Retriever.
  4. تُبنى الرسالة النهائية باستخدام قالب برومبت منظم، كما شرحنا في Prompt Engineering داخل الكود.
  5. يُرسل الطلب إلى النموذج عبر LangChain مع تفعيل التتبع.
  6. يسجل LangSmith عدد الرموز، والمدة، والمخرجات، وربطها بالمستخدم.
  7. يمكن لاحقاً تجميع السجلات لحساب تكلفة كل مستخدم أو كل فريق أو كل نقطة نهاية endpoint.

لماذا هذا مهم في تطبيقات الإنتاج؟

لأن متوسط التكلفة قد يكون مضللاً. ربما 10% من المستخدمين يستهلكون 70% من ميزانية النماذج بسبب أسئلة طويلة، أو استخدام متكرر لميزة Summary Memory، أو كثرة البحث في قاعدة المعرفة. التتبع الدقيق يكشف هذه الأنماط ويساعدك على اتخاذ قرارات مثل:

  • تحديد سقف استخدام يومي لكل مستخدم.
  • تقليل طول السياق.
  • اختيار نموذج أقل تكلفة للمهام البسيطة.
  • تمييز الخطط المجانية عن المدفوعة.

إعداد البيئة وتفعيل التتبع

قبل البدء، يفترض أنك أنهيت إعداد بيئة العمل وتثبيت المكتبات الأساسية وسبق لك تنفيذ أول اتصال بـ API. الآن نضيف طبقة المراقبة.

import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "YOUR_LANGSMITH_API_KEY"
os.environ["LANGCHAIN_PROJECT"] = "production-support-bot"
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"

model = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=0.2
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a precise support assistant. Answer briefly and accurately."),
    ("human", "User question: {question}")
])

chain = prompt | model

response = chain.invoke(
    {"question": "How can I reduce token costs in my AI app?"},
    config={
        "metadata": {
            "user_id": "user_1042",
            "plan": "pro",
            "feature_name": "support_chat",
            "environment": "production"
        },
        "tags": ["chat", "cost-monitoring", "openai"]
    }
)

print(response.content)

هنا قمنا بتمرير بيانات وصفية مهمة داخل config. هذه الخطوة هي الأساس في حساب التكلفة لكل مستخدم، لأن الأثر التشغيلي بدون metadata يصبح مجرد سجل تقني غير قابل للربط التجاري.

تتبع تطبيقات RAG وحساب تكلفة الاسترجاع والتوليد معاً

في تطبيقات RAG المصغرة لا تكفي مراقبة استدعاء النموذج فقط، لأن التكلفة الفعلية ترتبط أيضاً بطول المقاطع المسترجعة، وعدد الوثائق الممررة، وسلوك MMR أو أي استراتيجية استرجاع أخرى. إذا كانت المقاطع طويلة جداً فسيزداد استهلاك context window بسرعة.

from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer only from the provided context. If missing, say you do not know."),
    ("human", "Context:\n{context}\n\nQuestion:\n{question}")
])

rag_chain = (
    {
        "context": retriever | format_docs,
        "question": RunnablePassthrough()
    }
    | rag_prompt
    | model
    | StrOutputParser()
)

answer = rag_chain.invoke(
    "What are the invoice approval rules?",
    config={
        "metadata": {
            "user_id": "user_1042",
            "feature_name": "rag_knowledge_base",
            "department": "finance"
        },
        "tags": ["rag", "kb", "finance"]
    }
)

print(answer)

ميزة هذا الأسلوب أنك تستطيع من خلال trace رؤية أين تذهب الرموز: هل في السؤال الأصلي؟ أم في المستندات المسترجعة؟ أم في الإجابة نفسها؟ وهذا يفتح الباب لتحسينات دقيقة مثل تقليل حجم المقاطع، أو إعادة صياغة البرومبت، أو تعديل سياسة الاسترجاع.

كيف تحسب التكلفة لكل مستخدم بشكل عملي؟

في منصة LangSmith تستطيع فلترة السجلات عبر user_id أو feature_name ثم جمع الاستهلاك على فترة محددة. عملياً، تحتاج إلى ثلاثة مستويات من التحليل:

  • تكلفة الطلب الواحد cost per request.
  • تكلفة الجلسة الواحدة cost per session.
  • تكلفة المستخدم الشهرية monthly cost per user.

اجعل كل طلب يمرر الحقول التالية على الأقل: user_id، session_id، feature_name، plan، environment. بدون هذه الحقول ستفقد القدرة على بناء لوحات تكلفة دقيقة أو ربط المصروفات بسلوك المنتج.

إذا كنت قد قرأت سابقاً مقال حساب التكلفة وإدارة الرموز قبل الإرسال، فاعلم أن LangSmith يكمله بعد الإرسال. الأول يفيد في التقدير المسبق، والثاني يفيد في القياس الفعلي بعد التنفيذ.

أفضل الممارسات الهندسية لتقليل الاستهلاك بعد المراقبة

1) تحسين البرومبت والسياق

كل كلمة إضافية قد تتكرر آلاف المرات يومياً. راجع إعدادات Temperature وقلل التعليمات المتكررة غير الضرورية.

2) استخدام مخرجات مهيكلة

عند إجبار النموذج على الرد بصيغة منضبطة كما في Output Parsers وJSON، تقل الإطالة غير المفيدة وتصبح الاستجابات أكثر كفاءة.

3) تقصير الذاكرة التراكمية

إذا كان التطبيق محادثياً، فاختر بين Buffer Memory وSummary Memory حسب نوع الحمل التشغيلي.

4) مراقبة الميزات الأعلى كلفة

ليس كل جزء في التطبيق متساوياً. قد تكون ميزة Text-to-SQL أو البحث داخل ملفات المؤسسة أغلى بكثير من الدردشة العامة، لذلك افصلها في metadata منفصلة.

خلاصة تشغيلية لبناء نظام مراقبة موثوق

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

ناتج متوقع من نظام المراقبة الجيد: تعرف أي المستخدمين الأعلى استهلاكاً، وأي الميزات تستنزف أكبر عدد من tokens، وأي البرومبتات تسبب تضخماً في التكلفة، ثم تحول هذه المعرفة إلى قرارات هندسية قابلة للتنفيذ.

1 comment

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *