تشريح زمن استجابة النماذج اللغوية: قياس TTFT وتتبع التدفق واقتصاديات الوحدات
دليل هندسي لتفكيك طلبات النماذج اللغوية وتدفقات RAG عبر التتبع الموزع، لعزل زمن أول رمز مميز وتتبع معدل التوليد وحماية اقتصاديات الوحدات.
PowerTraces Editorial ·

التعامل مع طلبات النماذج اللغوية الكبيرة (LLMs) كنطاقات HTTP تقليدية موحدة يحجب تفاصيل الأداء الحرجة عن فرق الهندسة؛ إذ إن قياس زمن البداية والنهاية الإجمالي يخفي الفارق بين معالجة المدخلات وبدء التوليد، مما يجعل حماية اتفاقيات مستوى الخدمة (SLOs) وضبط اقتصاديات الوحدات ضرباً من التخمين.
فخ النطاقات الأحادية: لماذا تفشل مقاييس HTTP التقليدية أمام تدفق الذكاء الاصطناعي؟
اعتادت بنى الخدمات المصغرة ومراقبة الويب قياس زمن استجابة واجهات البرمجة من خلال نطاق HTTP أحادي يبدأ بوصول الطلب وينتهي بإغلاق مقبس الاتصال. هذا النمط الهندسي ينهار بالكامل عند الانتقال إلى واجهات التوليد التفاعلية القائمة على تدفق الرموز (Streaming LLM Responses). وفقاً لتوثيق OpenTelemetry Semantic Conventions for Generative AI Metrics، فإن حصر القياس في المدة الإجمالية للطلب يحجب التباين الجوهري بين مرحلة المعالجة المسبقة للمدخلات ومرحلة توليد الرموز المتعاقبة.
تتكون دورة معالجة النموذج اللغوي من مرحلتين منفصلتين تقنياً: مرحلة الملء المسبق (Prefill Phase) التي يقرأ فيها النموذج كامل السياق والمدخلات دفعة واحدة لحساب مصفوفات الانتباه، ومرحلة فك الترميز التكرارية (Autoregressive Decoding Phase) حيث يُنتج النموذج رمزاً واحداً تلو الآخر عبر حلقات استدلال متتالية. زمن الانتظار الإجمالي (End-to-End Latency) لا يمثل تجربة المستخدم؛ فالعميل في واجهات المحادثة يبدأ بالقراءة الفعلية بمجرد ظهور أول رمز مميز على شاشته.
إذا استغرق استدعاء النموذج اللغوي 12 ثانية لتوليد إجابة من 400 رمز، فإن قياس HTTP العام سيسجل فقط 12 ثانية كنطاق أحادي. لكن هذا الرقم لا يكشف ما إذا كان المستخدم قد انتظر 8 ثوانٍ حتى رأى الرمز الأول وظل يحدق في مؤشر تحميل متوقف، أم أنه انتظر 350 مللي ثانية وبدأ القراءة بسلاسة بينما استمر التوليد في الخلفية. الاعتماد على المتوسطات والمقاييس الموحدة يحرم فرق هندسة موثوقية المواقع (SRE) من تشخيص الاختناقات الحقيقية.
يؤدي هذا القصور التحليلي إلى تآكل صامت في هوامش الربحية للبرمجيات كخدمة (SaaS). فعندما يرتفع زمن الاستدعاء الكلي، تفترض فرق التطوير تلقائياً أن النموذج أصبح أبطأ، في حين قد تكون المشكلة تضخماً غير مبرر في عدد الرموز المسترجعة من قواعد البيانات الشعاعية، مما يرفع تكلفة الرموز الناتجة ويزيد فترات المعالجة دون داعٍ تجاري.
تفكيك المؤشرات الحيوية: زمن أول رمز مميز (TTFT) ومعدل توليد الرموز (TPOT)
يتطلب الرصد الدقيق فصل خطوط التقييم إلى مقياسين أساسيين يعكسان المراحل الحسابية داخل النموذج وسلوك المستهلك أمام الشاشة.
المقياس الأول هو «زمن أول رمز مميز» (Time-to-First-Token - TTFT). يقيس هذا المؤشر الفارق الزمني المنقضي بين لحظة إرسال طلب المستخدم ووصول أول رمز نصي صالح إلى واجهة العميل. يتأثر TTFT مباشرة بثلاثة عوامل: مدة الانتظار في طوابير جدولة كروت الرسوميات (GPU Queue Time)، وحجم موجه المدخلات وسياق الاسترجاع (Prompt Length)، وسرعة معالجة مصفوفات الانتباه في مرحلة الـ Prefill. يحدد توثيق OpenTelemetry GenAI Metrics أداة قياس مخصصة باسم gen_ai.server.time_to_first_token كمدرج إحصائي (Histogram) بوحدة الثواني لعزل هذا المكون بالذات.
المقياس الثاني هو «زمن توليد الرمز الواحد» (Time Per Output Token - TPOT)، أو ما يُعبر عنه بمعدل الرموز في الثانية. يقيس هذا المؤشر وتيرة بث الرموز المتتالية خلال مرحلة فك الترميز المستمرة بعد وصول أول رمز وحتى إغلاق التدفق. يرتبط TPOT بقدرة معالج الاستدلال الحسابية، وحجم النموذج المعماري، ومستوى ازدحام الدفعات المتزامنة (Batch Size) على البنية التحتية للخادم.
| المؤشر المتري | المرحلة الحسابية | العوامل المؤثرة | التأثير التجاري المباشر |
|---|---|---|---|
| TTFT | Prefill وطوابير الجدولة | طول السياق، زمن استرجاع المتجهات، ازدحام المزود | إدراك المستخدم لسرعة النظام وتفاعلية الواجهة |
| TPOT | Decoding التكراري | معمارية النموذج، حجم كروت الشاشة، التزامن الحسابي | سلاسة تدفق القراءة واستقرار تجربة العميل |
| E2E Duration | العملية المكتملة | مجموع TTFT مضافاً إليه (عدد الرموز × TPOT) | تكلفة الموارد الإجمالية وحجز قنوات الاتصال المفتوحة |
فصل اختناقات بنية الاسترجاع المعزز (RAG): تتبع المتجهات بموازاة الاستدلال
في خطوط إنتاج الاسترجاع المعزز بالتوليد (RAG)، يزداد زمن الاستجابة تعقيداً؛ فالطلب لا يذهب مباشرة إلى خادم الاستدلال، بل يمر عبر سلسلة معالجة تمتد من تحويل استعلام العميل إلى متجه عددي (Query Embedding)، ثم البحث الدلالي في قاعدة بيانات شعاعية (Vector Search)، وتطبيق خوارزميات إعادة الترتيب (Reranking)، وصولاً إلى بناء الموجه النهائي وإرساله إلى النموذج اللغوي.

وفقاً لمعايير OpenTelemetry Semantic Conventions for Retrieval Operations، فإن دمج هذه العمليات داخل نطاق واحد يُعد خطأً معمارياً يعمي المهندسين عن مصدر التأخير الحقيقي. توجب المواصفة إنشاء نطاقات فرعية مستقلة تمثل عمليات الاسترجاع تحت مسمى gen_ai.retrieval، لتوثيق محددات البحث الدلالي وتقييم الوثائق المسترجعة ونقاط تشابهها.
عندما تشتكي فرق الدعم من تراجع أداء النظام، فإن غياب تفكيك مسار RAG يجعل المهندسين يلقون اللوم تلقائياً على مزود النموذج اللغوي الخارجي. لكن التدقيق عبر النطاقات الموزعة يكشف غالباً أن التدهور ناتج عن بطء فهرسة المتجهات في قاعدة البيانات، أو استرجاع سياقات ضخمة غير مفلترة تجاوزت آلاف الرموز، مما يرفع حجم نافذة السياق (Context Window Overhead) ويضاعف زمن الـ TTFT لدى النموذج اللغوي اللاحق بصورة طردية.
بناء أدوات القياس لتدفق الأحداث من الخادم (SSE) باستخدام OpenTelemetry
تستخدم معظم واجهات التخاطب مع النماذج اللغوية بروتوكول الأحداث المرسلة من الخادم (Server-Sent Events - SSE) لضخ النتائج تدريجياً عبر مقبس HTTP مفتوح. لمراقبة هذه العملية بدقة متناهية، يجب التدخل في دورة حياة المكرر غير المتزامن (Async Stream Iterator).
تنص وثيقة OpenTelemetry Semantic Conventions for Generative AI Client Inference على ضرورة فتح نطاق العميل gen_ai.client.inference عند إطلاق الطلب الشبكي الأولي. وعند وصول أول حزمة جزئية (First Chunk)، يُسجل حدث نطاق مخصص (Span Event) أو يُقاس الفارق الزمني لتسجيل TTFT، مع الاحتفاظ بالنطاق مفتوحاً لتلقي التدفق كاملاً.
الرموز المميزة للمدخلات والمخرجات (gen_ai.usage.input_tokens و gen_ai.usage.output_tokens) لا يجوز تسجيلها مع كل حزمة جزئية لتجنب تشويش مصفوفات القياس، بل تُجمع وتُسند كسمات رسمية للنطاق عند وصول الحزمة النهائية الحاوية لبيانات الإنهاء الإحصائية، أو عبر تجميع الرموز الناتجة داخلياً قبل إغلاق النطاق.
يجب التعامل بصرامة مع حالات انقطاع الاتصال المفاجئ من جهة العميل (Client Disconnects). إذا أغلق المستخدم نافذة المتصفح في منتصف التدفق، فيجب التقاط استثناء الإلغاء، وتوثيق عدد الرموز التي تم توليدها وبثها بالفعل حتى لحظة القطع داخل سمات النطاق، وتسجيل سبب الإنهاء بدقة لتفادي تشويه حسابات التكلفة ومعدلات استهلاك الرموز.
اقتصاديات الوحدات: تمرير هوية المستأجر عبر سياق التتبع لتخصيص التكلفة
في بيئات البرمجيات الخدمية متعددة المستأجرين (Multi-tenant SaaS)، يُعد ربط استهلاك البنية التحتية بالعميل الفعلي ركيزة أساسية لضمان سلامة نموذج العمل التجاري. لا يمكن للشركات الاستمرار في بيع اشتراكات ثابتة القيمة بينما تتباين تكاليف استهلاك الرموز والنماذج بين مستخدم وآخر بآلاف المرات.

لتحقيق ذلك عبر البنى الموزعة دون إرهاق واجهات البرمجة بتعديل هياكل الحمولات البرمجية، نعتمد على معيار W3C Baggage. يتيح هذا المعيار حقن سمات متقاطعة مثل معرف المستأجر (tenant.id) وفئة الاشتراك (customer.tier) عند بوابة الدخول (API Gateway)، لتنتقل تلقائياً عبر سياق التتبع إلى كافة الخدمات اللاحقة.
بالمثل، يضمن معيار W3C Trace Context عبر ترويسات traceparent الحفاظ على ترابط النطاقات عبر العمليات غير المتزامنة وموزعات الحمل وبوابات الـ SSE، مما يضمن تدفق سياق التتبع بسلاسة وصولاً إلى نطاق استدعاء النموذج اللغوي.
بمجرد وصول هذه السمات إلى نطاق الاستدلال، تُربط أعداد الرموز المسجلة (gen_ai.usage.input_tokens و gen_ai.usage.output_tokens) بهوية المستأجر مباشرة، مما يمكن منصات التحليل من حساب التكلفة الفعلية لكل معاملة ولحظياً استناداً إلى تسعير كل ألف رمز لكل نموذج معتمد، واكتشاف العملاء الذين يستهلكون موارد جائرة تؤثر على جيرانهم في النظام (Noisy Neighbors).
مثال تطبيقي: بناء ممر ترصّد كامل لخدمة RAG متدفقة
يوضح النموذج التالي في لغة Python كيفية إنشاء معالج وسيط يعتمد مكتبة OpenTelemetry لتنفيذ التفكيك المنهجي: فتح نطاق أب لمعالجة طلب RAG، واستدعاء نطاق استرجاع المتجهات، ثم بدء نطاق استدلال تدفقي يلتقط TTFT فورياً ويسجل استهلاك الرموز وهوية المستأجر المنقولة عبر Baggage.
import time
from typing import AsyncGenerator
from opentelemetry import trace, baggage
from opentelemetry.trace import Status, StatusCode
tracer = trace.get_tracer("rag.stream.engine")
async def retrieve_context(query: str) -> list[str]:
# نطاق فرعي لعمليات الاسترجاع وقواعد بيانات المتجهات
with tracer.start_as_current_span("gen_ai.retrieval") as span:
span.set_attribute("gen_ai.system", "custom_vector_db")
span.set_attribute("gen_ai.retrieval.query", query)
# محاكاة زمن الاستعلام الشعاعي وإعادة الترتيب
start_time = time.monotonic()
# استرجاع الوثائق من الفهرس الشعاعي
documents = ["Doc chunk 1", "Doc chunk 2"]
search_duration = time.monotonic() - start_time
span.set_attribute("gen_ai.retrieval.duration_seconds", search_duration)
span.set_attribute("gen_ai.retrieval.documents_count", len(documents))
return documents
async def mock_llm_stream(prompt: str) -> AsyncGenerator[str, None]:
# محاكاة استجابة الخادم وتدفق الرموز مع تأخير مرحلة الـ Prefill
time.sleep(0.180) # زمن TTFT الخاص بالنموذج وطوابير المعالجة
tokens = ["Telemetry ", "deconstructs ", "streaming ", "LLM ", "latency ", "accurately."]
for token in tokens:
yield token
time.sleep(0.040) # زمن توليد كل رمز (TPOT)
async def handle_rag_stream(user_query: str) -> AsyncGenerator[str, None]:
# استخراج هوية المستأجر من سياق W3C Baggage
tenant_id = baggage.get_baggage("tenant.id") or "anonymous_tenant"
customer_tier = baggage.get_baggage("customer.tier") or "standard"
# نطاق المعالجة الشامل لطلب RAG
with tracer.start_as_current_span("rag.request.process") as root_span:
root_span.set_attribute("tenant.id", tenant_id)
root_span.set_attribute("customer.tier", customer_tier)
# 1. تنفيذ الاسترجاع الدلالي كـ Child Span
context_documents = await retrieve_context(user_query)
combined_prompt = f"Context: {' '.join(context_documents)} Query: {user_query}"
# 2. بدء نطاق العميل للاستدلال المتدفق
inference_span = tracer.start_span("gen_ai.client.inference")
inference_span.set_attribute("gen_ai.system", "openai")
inference_span.set_attribute("gen_ai.request.model", "gpt-4o")
inference_span.set_attribute("tenant.id", tenant_id)
first_chunk_received = False
stream_start_time = time.monotonic()
output_tokens_count = 0
try:
stream = mock_llm_stream(combined_prompt)
async for chunk in stream:
if not first_chunk_received:
ttft_seconds = time.monotonic() - stream_start_time
# تسجيل مقياس TTFT فور وصول أول رمز
inference_span.add_event(
"first_token_received",
attributes={"gen_ai.server.time_to_first_token": ttft_seconds}
)
inference_span.set_attribute("gen_ai.server.time_to_first_token", ttft_seconds)
first_chunk_received = True
output_tokens_count += 1
yield chunk
# توثيق أعداد الرموز الرسمية عند اكتمال التدفق
estimated_input_tokens = len(combined_prompt.split()) * 2
inference_span.set_attribute("gen_ai.usage.input_tokens", estimated_input_tokens)
inference_span.set_attribute("gen_ai.usage.output_tokens", output_tokens_count)
inference_span.set_status(Status(StatusCode.OK))
except Exception as exc:
inference_span.record_exception(exc)
inference_span.set_status(Status(StatusCode.ERROR, str(exc)))
raise
finally:
inference_span.end()
إدارة أهداف مستوى الخدمة (SLOs) عبر توزيعات المئينات بدلاً من المتوسطات
الخطأ الأكثر شيوعاً في تقييم أداء تطبيقات الذكاء الاصطناعي هو استخدام المتوسطات الحسابية (Mean Latency) كمعيار لإقرار جودة الخدمة. المتوسطات الحسابية تخفي خلفها تدهوراً حاداً في ذيل التوزيع الإحصائي (Tail Latency)، حيث يعاني قطاع كبير من المستخدمين من تجارب بطيئة للغاية بينما يظل المتوسط العام يبدو مقبولاً للإدارة.
Most metrics are better thought of as distributions rather than averages. For example, for a latency SLI, some requests will be serviced quickly, while others will invariably take longer—sometimes much longer.
Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy, Site Reliability Engineering: How Google Runs Production Systems
«من الأفضل النظر إلى معظم المقاييس كتوزيعات إحصائية بدلاً من متوسطات. ففي مؤشر زمن الاستجابة على سبيل المثال، ستتم خدمة بعض الطلبات بسرعة، بينما ستستغرق طلبات أخرى وقتاً أطول حتماً، وأحياناً أطول بكثير.» هذا المبدأ المذكور في كتاب Site Reliability Engineering: Service Level Objectives يكتسب أهمية مضاعفة عند مراقبة تدفقات النماذج التوليدية.
For example, client-side latency is often the more user-relevant metric, but it might only be possible to measure latency at the server.
Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy, Site Reliability Engineering: How Google Runs Production Systems
«على سبيل المثال، غالباً ما يكون زمن الاستجابة المقاس من جهة العميل هو المقياس الأكثر صلة بالمستخدم، لكن قد لا يمكن قياس زمن الاستجابة إلا عند الخادم.» لهذا السبب بالتحديد يجب على الخوادم عزل قياس زمن أول رمز مميز ليكون أقرب تمثيل تقني لإدراك المستخدم اللحظي.
تتطلب منهجية هندسة موثوقية المواقع (SRE) صياغة أهداف مستوى خدمة منفصلة تماماً لكل مرحلة من مراحل الاستدلال:
- هدف TTFT المئيني (p95): أن يبدأ تدفق الرمز الأول في أقل من 1.2 ثانية لـ 95% من الطلبات خلال نافذة زمنية مدتها 30 يوماً. هذا الهدف يراقب كفاءة استرجاع المتجهات وطوابير جدولة النماذج وحجم نصوص المدخلات.
- هدف وتيرة التوليد المئيني (p95 TPOT): ألا يتجاوز زمن توليد الرمز الواحد 40 مللي ثانية (بما يعادل 25 رمزاً في الثانية على الأقل) لـ 95% من الرموز المولدة، لضمان سلاسة حركة النص أمام القارئ دون تقطع ملحوظ.
إدارة ميزانيات الأخطاء (Error Budget Burn Rates) وفق هذه المؤشرات تتيح إطلاق التنبيهات الاستباقية عندما تتسبب استعلامات معقدة في حرق ميزانية زمن المعالجة المسبقة، مما يوجه الفريق لإعادة ضبط عدد مقاطع الاسترجاع (Top-K Chunks) في مرحلة البحث الدلالي لتحقيق التوازن بين جودة المحتوى المسترجع وسرعة التوليد.
توفر منصات المراقبة المتقدمة مثل PowerTraces إمكانية ترجمة هذه المقاييس إلى لوحات تحكم ومؤشرات أداء واضحة، متيحة لفرق الهندسة ضبط تنبيهات ميزانيات أخطاء الـ SLOs ومتابعة الحوادث التلقائية فور تجاوز مئينات TTFT الحدود المقبولة، مما يربط تتبع الأداء التقني مباشرة برضا المستخدم وسلامة الإنفاق.
قائمة التحقق الهندسية: جاهزية القياس لمشاريع الذكاء الاصطناعي في الإنتاج
قبل إطلاق أو توسيع نطاق خدمات الذكاء الاصطناعي التوليدي أو تطبيقات RAG المعتمدة على البث المباشر، تحقق من استيفاء المعايير التالية داخل بنية التتبع والترصّد الخاصة بنظامك:
- تفتيت مسارات RAG: هل تم فصل مرحلة استرجاع المتجهات (
gen_ai.retrieval) عن استدعاء النموذج اللغوي في نطاقات فرعية مستقلة مع ربطها بنفس معرف التتبع (traceparent)؟ - دقة التقاط TTFT: هل يتم رصد أول حزمة متدفقة (First Chunk) وتسجيلها كحدث رسمي في النطاق وحساب
gen_ai.server.time_to_first_tokenبدقة المللي ثانية؟ - حساب الرموز عند الإغلاق: هل تقتصر إضافة سمات
gen_ai.usage.input_tokensوgen_ai.usage.output_tokensعلى مرحلة اكتمال التدفق لتفادي تلويث مصفوفات البيانات؟ - توثيق الانقطاعات المفاجئة: هل يتعامل مكرر التدفق مع حالات إلغاء الاتصال من العميل ويسجل حجم الرموز التي استهلكت حتى لحظة القطع مع بيان سبب الإلغاء؟
- تمرير هوية المستأجر: هل تم تفعيل معيار W3C Baggage لتمرير
tenant.idوcustomer.tierوربطهما بنطاق الاستدلال لاحتساب التكلفة اللحظية لكل مستأجر؟ - اعتماد المئينات لأهداف الخدمة: هل تم بناء لوحات المتابعة والتنبيهات بالاعتماد على توزيعات p95 و p99 لمؤشري TTFT و TPOT بدلاً من متوسطات زمن الاستجابة الكلية؟
References
- OpenTelemetry Semantic Conventions for Generative AI Metrics
- OpenTelemetry Semantic Conventions for Generative AI Client Inference
- OpenTelemetry Semantic Conventions for Retrieval Operations
- Propagation format for distributed context: Baggage
- W3C Trace Context Level 2
- Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy, Site Reliability Engineering: How Google Runs Production Systems (Service Level Objectives)