الانتقال إلى المحتوى الرئيسي

title: “مجموعة التقييم” description: “توثيق مجموعة التقييم في AgentEye.”

تقيّم AgentEye جلسات الوكيل المكتملة بإرسال نسخ حدث المعاملة الكاملة عبر POST إلى خدمة تقييم واحدة مملوكة للعميل. تُرجع خدمة التقييم النتائج إما بصيغة مضمنة أو بإرجاع job_id لتستطلعها AgentEye. يتم تخزين النتائج وعرضها في لوحة التحكم. يغطي هذا الدليل:
  1. كيفية الكشف عن إكمال الجلسة.
  2. عقد HTTP الذي يجب أن تطبقه خدمة التقييم.
  3. تكوين خادم AgentEye.
  4. عرض النتائج.
  5. استكشاف الأخطاء.
للحصول على مساعد Python الذي يطبق العقد لك، اطّلع على حزمة agenteye-evaluator على PyPI.

كيفية العمل

عند إصدار SDK في AgentEye لحدث agent_end الخاص بجلسة ما، يجدول الخادم تقييمًا. ثم يرسل نسخة حدث المعاملة الكاملة إلى خدمة التقييم الخاصة بك، والتي يمكنها:
  • إرجاع النتيجة بصيغة مضمنة مع {"status":"done", "scores":{...}, "reasoning":{...}, "summary":"..."}. يتم إلحاق النتيجة بخط زمني التقييم للجلسة. reasoning و summary اختيارية.
  • تأجيل مع {"status":"pending", "job_id":"abc-123"}. ثم تستدعي AgentEye GET {EVALUATOR_ENDPOINT}/evaluate/abc-123 حتى تُرجع خدمة التقييم الخاصة بك {"status":"done", ...} أو {"status":"error", "error":"..."}. دورة الاستطلاع لكل وظيفة: قد تتضمن استجابة pending next_poll_secs لتجاوز ذلك؛ وإلا تستخدم AgentEye قيمة default_poll_interval_secs من GET /config؛ وإلا يعود الخادم إلى EVALUATOR_POLLING_INTERVAL_SECS (الافتراضي 10s). يتم تقييد جميع القيم إلى [1s, 1h].
الجلسات التي لا تصدر أبدًا agent_end (على سبيل المثال، عملية وكيل متعطلة) يمكن أيضًا التقاطها: قد يُرجع GET /config الخاص بخدمة التقييم {"inactivity_timeout_secs": 1800}، وستقيّم AgentEye أي جلسة ظلت خاملة لتلك المدة. اضبط الحقل على null أو احذفه لتعطيل هذا البديل. خط الأنابيب هو عدم تشغيل كامل عند عدم تعيين EVALUATOR_ENDPOINT. يمكن للجلسة أن تتراكم فيها تقييمات نهائية متعددة بمرور الوقت: كل حدث agent_end (وكل إعادة تقييم يدوية من لوحة التحكم) يُلحق صف تقييم جديد. هذه هي الطريقة المدعومة لتقييم محادثة استُؤنفت: ينهي المستخدم وكيلاً، يعود لاحقًا، يرسل المزيد من الأحداث، ينهي الوكيل مرة أخرى، وينفذ التقييم الثاني مقابل نسخة المعاملة المحدثة الكاملة. تُظهر لوحة التحكم أحدث تقييم كعنوان أساسي والتقييمات السابقة كخط زمني قابل للطي. أثناء تشغيل تقييم واحد لجلسة ما، يتم تجاهل أحداث agent_end الإضافية لتلك الجلسة؛ الحدث التالي بعد انتهاء التقييم قيد التشغيل سيضع تقييمًا جديدًا في قائمة الانتظار كالمعتاد. يعاود البديل الخامل الاشتباك على الجلسات المستأنفة أيضًا: إذا وصلت أحداث جديدة بعد تقييم نهائي سابق وظلت الجلسة خاملة بعد ذلك inactivity_timeout_secs، يتم وضع تقييم جديد في قائمة الانتظار. يتم إعادة محاولة الأخطاء العابرة (5xx, 429, timeouts, أخطاء الشبكة) مع تراجع أسي حتى EVALUATOR_MAX_ATTEMPTS؛ استجابات 4xx نهائية. من الآمن تشغيل AgentEye مع عدة نسخ خادم موزعة أفقيًا؛ يتم تقسيم العمل بحيث لا يتم أبدًا إرسال نفس الجلسة مرتين في نفس الوقت.

عقد HTTP

كل مسار مصرح يستخدم مصادقة رمز المتحمل. يجب تكوين نفس القيمة على كلا الجانبين:
  • خادم AgentEye: متغير بيئي EVALUATOR_TOKEN
  • خدمة التقييم: مكونة بنفس الطريقة (يقرأ SDK agenteye-evaluator EVALUATOR_TOKEN بموجب الاتفاقية)
إذا لم يتم تعيين EVALUATOR_TOKEN، لا يرسل الخادم رأس Authorization؛ قد تقبل خدمة التقييم طلبات مجهولة الهوية بعد ذلك، وهذا حسن لشبكة داخلية فقط لكن غير موصى به على الإنترنت العام.

المسارات التي يجب أن تخدمها خدمة التقييم

المسارالجسد / المعاملاتالاستجابة
GET /healthبدون{"status":"ok"} (مفتوح، بدون مصادقة)
GET /configبدون{"inactivity_timeout_secs": <int> | null, "default_poll_interval_secs": <int> | omitted}
POST /evaluateEvalRequest JSON{"status":"done", ...} أو {"status":"pending", "job_id":"..."}
GET /evaluate/{id}بدوننفس شكل الاستجابة مثل /evaluate

جسم EvalRequest الذي يرسله الخادم

أشكال الاستجابة

متزامن (منتهي):
reasoning (خريطة تبرير لكل نتيجة) و summary (سرد واحد شامل فقرة واحدة) كلاهما اختياري. يجب أن تعكس المفاتيح في reasoning المفاتيح في scores؛ تُظهر لوحة التحكم كل مدخل مضمنًا تحت شريط النتيجة الخاص به. تابع خدمات التقييم الأقدم التي تُرجع فقط scores تعمل بدون تغيير؛ reasoning و summary ببساطة تُقرأ على أنها null و لا يتم حذف تسهيلات الواجهة المستخدمة المقابلة. غير متزامن (مؤجل):
next_poll_secs اختياري؛ إذا تم حذفه، يعود الخادم إلى default_poll_interval_secs لخدمة التقييم من /config، ثم إلى متغير البيئة الخاص به EVALUATOR_POLLING_INTERVAL_SECS. خطأ نهائي من جانب خدمة التقييم:
يعامل الخادم أي جسم 2xx آخر كخطأ بروتوكول وينسجل error نهائي للجلسة.

كتابة خدمة تقييم مع SDK

تمنحك حزمة Python agenteye-evaluator غلافًا FastAPI مكتوبًا بشكل ثابت يطبق عقد HTTP أعلاه. ثبتها من PyPI:
خدمة تقييم بحد أدنى من القابلية:
نسخة app قابلة للاستدعاء ASGI، لذا يقوم uvicorn module:app بتشغيلها. لخدمات التقييم التي تحتاج إلى تأجيل عمل مكلف، أرجع JobPending بدلاً من ذلك وسجل معالج @app.job_lookup؛ الخادم AgentEye يستطلع GET /evaluate/{job_id} حتى تُرجع حالة نهائية أو يمر حد EVALUATOR_MAX_POLL_DURATION_SECS (الافتراضي 1 ساعة). مرجع API الكامل، النمط غير المتزامن، ومخطط الحدث: ملف README الخاص بـ agenteye-evaluator يُشحن داخل كل نسخة من صفحة إصدارات agenteye-enterprise، أو يمكنك قراءته على صفحة PyPI للحزمة.

تشغيل خدمة تقييم على Kubernetes

خدمة التقييم هي خدمتك: لا تشحن AgentEye خدمة تقييم افتراضية في حاوية. تتضمن النسخة مظاهر Kubernetes مرجعية تحت deploy/examples/evaluator/ التي يمكنك تطبيقها كما هي بعد استبدال صورتك ورمز متحمل مشترك.

1. تجميع خدمة التقييم الخاصة بك

ملف Dockerfile الحد الأدنى لخدمة التقييم الخاصة بك:
runAsNonRoot (UID 10001) يحافظ على توافق الحاوية مع ملفات تعريف أمان Pod المقيدة.

2. إنشاء رمز المتحمل المشترك

استخدم نفس القيمة مثل EVALUATOR_TOKEN على خادم AgentEye. يرسل الخادم Authorization: Bearer <token> على كل طلب؛ يستخدم SDK hmac.compare_digest للفحص الثابت الوقت ويرفض عدم التطابق مع HTTP 401.

3. تطبيق مظاهر الأمثلة

يتضمن المثال:
  • نشر بـ 2 نسخة مع runAsNonRoot ونظام ملفات الجذر للقراءة فقط، جميع القدرات محذوفة، liveness + readiness على /health
  • خدمة ClusterIP على المنفذ 9000
  • نموذج secret.example.yaml (مستبعد بقصد من Kustomization؛ أنشئ الرمز الحقيقي خارج النطاق حتى لا يوجد رمز في git)

4. ربط AgentEye به

على خادم AgentEye، اضبط:
يُوزع الخادم EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH طلبات متزامنة عبر جميع حبات خدمة التقييم (الافتراضيات: 2 × 4 = 8). مقياس replicas وحدود الموارد لكل حبة بالتزامن مع هذه عناصر التحكم من جانب الخادم.

التحقق

بعد تشغيل وكيل من البداية إلى النهاية، يجب أن يُرجع GET /evaluations على خادم AgentEye صف بـ status: "done" والنتائج التي أنتجتها خدمة التقييم الخاصة بك.

تكوين خادم AgentEye

اضبط على عملية الخادم:
متغير البيئةالمعنى
EVALUATOR_ENDPOINTعنوان URL الأساسي لخدمة التقييم الخاصة بك (http://evaluator:9000). لم يتم التعيين = خط الأنابيب معطل.
EVALUATOR_TOKENرمز متحمل. يجب أن تساوي القيمة التي تم تكوين خدمة التقييم بها.
EVALUATOR_WORKERSمهام عامل لكل نسخة خادم (الافتراضي 2).
EVALUATOR_CLAIM_BATCHصفوف مطالب بة لكل دورة عاملة (الافتراضي 4). تتم معالجة الدفعات بشكل متزامن؛ التزامن الفعلي على نقطة نهاية خدمة التقييم الخاصة بك هو EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH.
EVALUATOR_POLL_IDLE_SECSالمدة التي تنام بها العامل بين محاولات الإرسال عندما لا يكون التقييم مستحقًا (الافتراضي 2s).
EVALUATOR_POLLING_INTERVAL_SECSالبديل النهائي لإيقاع GET /evaluate/{id} عندما لا يكون كل من next_poll_secs لكل استجابة ولا default_poll_interval_secs لخدمة التقييم مضبوطًا (الافتراضي 10s).
EVALUATOR_REQUEST_TIMEOUT_MSمهلة زمنية لكل طلب (الافتراضي 30000).
EVALUATOR_MAX_ATTEMPTSبعد هذا العدد من الأخطاء العابرة يتم تسجيل النتيجة كـ error نهائي (الافتراضي 5).
EVALUATOR_CONFIG_REFRESH_SECSدورة GET /config (الافتراضي 300).
EVALUATOR_MAX_POLL_DURATION_SECSأقصى وقت جدار زمني قد تبقى فيه جلسة في قائمة انتظار الاستطلاع قبل إنهاؤها كـ timeout (الافتراضي 3600s). يحمي من خدمة تقييم تستمر في إرجاع pending للأبد.
لتشغيل النقاط التلقائية عبر النسخة الكاملة، جهز سر agenteye-evaluator مع كلا المفاتيح المضبوطة. على مظاهر Kubernetes المجمعة، يقرأ الخادم EVALUATOR_ENDPOINT و EVALUATOR_TOKEN من هذا السر الاختياري. أنشئه عبر عملية إدارة الأسرار القياسية في مؤسستك، ثم أعد تشغيل نشر الخادم لالتقاط التغيير. عناصر التحكم في الضبط أعلاه لم تُربط بشكل افتراضي؛ اكشف متغيرات البيئة المقابلة على حاوية الخادم في مظهر النشر الخاص بك إذا كنت بحاجة إلى تجاوز الافتراضيات. اطّلع على deployment.md لجدول متغيرات البيئة الكامل.

مرجع API

الطريقةالمسارالإذن المطلوبالغرض
GET/evaluationsevaluations:readنتائج نهائية للاستعلام. يدعم session_id, agent_id, environment, status (done/error/timeout), ts_from, ts_to, cursor, limit, score_filters, latest_per_session. limit افتراضي إلى 50 وقبعة عند 200 (لاحظ أن هذا يختلف عن /events، والذي يقبع عند 1000). environment يقبل قائمة مفصولة بفواصل (على سبيل المثال environment=prod,staging؛ تعمل القيم الفردية أيضًا. مع latest_per_session=true تحتوي الاستجابة على صف واحد على الأكثر لكل session_id (الأحدث حسب completed_at) يستخدمه صفحة قائمة الجلسات لطي خط زمني التقييم الخاص بالجلسة إلى عنوانها الحالي. الافتراضي كاذب (يُرجع السجل الكامل).
GET/evaluations/aggregateevaluations:readصحة تقييم مجتمعة لشريحة مفلترة: عد إجمالي، تفصيل done/error/timeout، إحصائيات لكل مفتاح نتيجة (العد/المتوسط/الحد الأدنى/الحد الأقصى/p50 عبر مفاتيح scores التعسفية)، وخط زمني محدد بوقت. يقبل نفس معاملات الفلتر مثل /evaluations بالإضافة إلى featured_keys (CSV لمفاتيح النتيجة للاتجاه) و latest_per_session. يدعم ميزة لوحات التحكم؛ المقاييس دقيقة على جميع المجموعة المطابقة، لا مأخوذة العينات.
GET/evaluations/environmentsevaluations:readقيم بيئة مميزة من جدول evaluations. يستخدم لملء منسدلات الفلتر المحصورة في بيانات التقييم القابلة للقراءة.
GET/evaluation-jobsevaluations:readرؤية إلى التقييمات قيد الطيران. الفلتر حسب status (pending/polling).
GET/eventsevents:readدفق الأحداث الخام للجلسة. يدعم session_id, agent_id, event_type (CSV), environment (CSV), ts_from, ts_to, cursor, limit, و order. order يكون desc (الأحدث أولاً، الافتراضي) أو asc (الأقدم أولاً)؛ قيمة غير معروفة تعود إلى desc. استطلع الصفحات عبر next_cursor (معرف حدث) في الاستجابة: أرجعها كـ cursor للحصول على الصفحة التالية؛ مع asc الصفحة التالية هي الأحداث بعد معرف الهوية، مع desc الأحداث قبلها. limit افتراضي إلى 50 وقبعة عند 1000.
GET/sessions/:session_id/exportevents:readيُرجع جسم JSON الدقيق الذي ستتلقاه خدمة التقييم لهذه الجلسة، يتم تقديمه كمرفق قابل للتنزيل باسم session-<id>.json. مفيد لإعادة تشغيل جلسات الإنتاج عبر agenteye-evaluator للاختبار غير المتصل. البايتات متطابقة بايت إلى ما يرسله خط أنابيب خدمة التقييم.
POST/sessions/:session_id/re-evaluateevaluations:triggerاضطر لتقييم طازج لجلسة؛ يعمل سواء كان هناك تقييم سابق أم لا. يتم إلحاق النتيجة الجديدة بخط زمني تقييم الجلسة بدلاً من الكتابة فوق الجلسة السابقة، لذا تبقى النتائج السابقة مرئية كسجل. يُرجع 202 عند الطلب، 404 لجلسة غير معروفة، 409 إذا كان تقييم قيد الطيران بالفعل. استخدم هذا بعد نشر خدمة تقييم جديدة، أو للجلسات التي لم تصدر أبدًا agent_end.

الفلترة حسب نطاق النتيجة: score_filters

يقبل GET /evaluations معامل score_filters اختياري يضيق النتائج حسب القيم الرقمية داخل كائن scores. المعامل عبارة عن قائمة مفصولة بفواصل من إدخالات key:min..max؛ قد يكون كلا الحدين محذوفًا. تتحد إدخالات متعددة بـ AND منطقي. الصفوف حيث يكون المفتاح المسمى غائبًا أو غير رقمي يتم استبعاده. قد يحمل الطلب ما يصل إلى 20 إدخال فلتر؛ يعود تجاوز ذلك HTTP 400. أمثلة:
لكل كائن استجابة /evaluations هذه الحقول:
الحقلالنوعالملاحظات
evaluation_idسلسلة (UUID)المعرف الكنسي لهذا التقييم النهائي. يحصل كل تقييم نهائي على UUID جديد؛ يمكن للجلسة الواحدة أن تحتفظ بعدة.
idسلسلة (UUID)اسم مستعار للتوافق العكسي يحمل نفس القيمة مثل evaluation_id.
session_idسلسلةالجلسة التي انطلقت هذا التقييم عليها. يمكن للجلسة أن تحتوي على تقييمات متعددة في الخط الزمني.
agent_idسلسلةيحدد الوكيل الذي أنتج الجلسة.
environmentسلسلةتسمية البيئة المنسوخة من الجلسة.
statusالتعدادواحد من "done", "error", "timeout".
scoresكائن | nullالنتائج التي أرجعتها خدمة التقييم الخاصة بك.
reasoningكائن | nullخريطة تبرير اختيارية لكل نتيجة أرجعتها خدمة التقييم الخاصة بك. عادة ما تعكس المفاتيح تلك الموجودة في scores. تُظهر لوحة التحكم كل مدخل تحت شريط النتيجة الخاص به.
summaryسلسلة | nullسرد اختياري لفقرة واحدة يُرجع من قبل خدمة التقييم الخاصة بك. تُظهر لوحة التحكم هذا فوق تفصيل لكل نتيجة كعنوان التقييم.
errorسلسلة | nullمعبأ على "error" / "timeout" فقط.
attempt_countعدد صحيحعدد محاولات الإرسال (≥ 1).
duration_msعدد صحيح | nullمدة المحاولة الأخيرة.
completed_atسلسلة (ISO 8601 UTC)عندما تم تسجيل النتيجة النهائية. يتم ترتيب النتائج حسب completed_at (الأحدث أولاً).
created_atسلسلة (ISO 8601 UTC)يحمل نفس الطابع الزمني مثل completed_at (دلالات الكتابة مرة واحدة).

الأذونات

الإذنالأذونات
evaluations:readنتائج التقييم قائمة، عرض النتائج في لوحة التحكم، وتحميل مقاييس صحة لوحة التحكم.
evaluations:triggerضع تقييمًا يدويًا في قائمة الانتظار لجلسة عبر POST /sessions/:session_id/re-evaluate أو زر لوحة التحكم لإعادة التقييم.
dashboards:readعرض لوحات التحكم المحفوظة (تحتاج أيضًا إلى evaluations:read لتحميل مقاييسها).
dashboards:writeإنشاء وتعديل لوحات التحكم.
dashboards:deleteحذف لوحات التحكم.
المسؤول التمهيدي (ADMIN_KEY, ADMIN_EMAIL) يتلقى هذه تلقائيًا.

عرض النتائج

  • /sessions/<id>: خط زمني للأحداث + عمود يميني يعرض النتائج والأخطاء من محاولة الإرسال. إذا كان مفتاحك يحتوي على evaluations:trigger، يظهر زر re-evaluate بجانب زر التصدير، مفيد للجلسات التي لم تصدر أبدًا agent_end، أو لتحديث النتائج بعد نشر خدمة تقييم جديدة. تستطلع لوحة التحكم النتيجة الجديدة وتحدث العمود الأيمن عند وصوله.
  • /sessions: شبكة جلسة قابلة للفلترة؛ يعرض عمود النتيجة حالة التقييم والنتائج لكل جلسة على الفور.
  • /dashboards: طرق صحة التقييم المحفوظة (اطّلع على لوحات التحكم أدناه).
شبكة الجلسات مع حبوب حالة التقييم لكل جلسة وشارات النتيجة المشفرة بالألوان (helpfulness, factuality, tool_efficiency, safety, coherence) تعرض شبكة الجلسات حالة التقييم والنتائج لكل عملية تشغيل على الفور؛ تجعل شارات أحمر/كهرمان/أخضر النتائج المنخفضة بارزة. عرض تفصيل الجلسة مع درجات التقييم وحالة الإرسال في العمود الأيمن يعرض فتح جلسة الخط الزمني الكامل بجانب درجات التقييم وأي خطأ في المرسل في العمود الأيمن.

لوحات التحكم

تسمح صفحة لوحات التحكم (/dashboards) بحفظ مزيج من فلاتر التقييم كعرض مسمى وقابل لإعادة الاستخدام ومشاهدة أداء تلك الشريحة من التقييمات بضربة واحدة. يتم مشاركة لوحات التحكم عبر مؤسستك بأكملها؛ كل شخص لديه dashboards:read يرى نفس المجموعة. تثبت كل لوحة تحكم:
  • الفلاتر: نفس الضوابط الموجودة على صفحة الجلسات: البيئة، الحالة، الوكيل، نافذة زمنية متدحرجة، وفلاتر نطاق النتيجة (key:min..max).
  • تكوين العرض: مفاتيح النتيجة المراد عرضها، حدود صحة أخضر/كهرمان/أحمر، اللوحات المراد عرضها، وما إذا كان يجب طي أحدث تقييم لكل جلسة.
تعرض كل بطاقة عدد الجلسات المطابقة، تفصيل done/error/timeout، متوسط كل نتيجة متميزة، وخط زمني صغير في الاتجاه. يعرض فتح لوحة تحكم اللوحات بالحجم الكامل؛ استخدم الجلسات تنقلك إلى صفحة الجلسات مع التصفية المسبقة إلى تلك الشريحة بالضبط. يتم حساب المقاييس من جانب الخادم على جميع المجموعات المطابقة (عبر GET /evaluations/aggregate)، لذا تكون الأرقام دقيقة بدلاً من المعاينة. لوحة تحكم صحة التقييم مع أشرطة متوسط النتيجة لكل بعد مقيّم، وتفصيل أداة ok مقابل خطأ، وأفضل الأدوات، واتجاه الأحداث في الساعة الأذونات: يتطلب العرض كل من dashboards:read و evaluations:read؛ ينشئ ويعدل يتطلب dashboards:write؛ حذف يتطلب dashboards:delete. يتلقى المسؤول التمهيدي كل هذه تلقائيًا.

استكشاف الأخطاء

توجد جلسات لكن لم يتم إنشاء تقييمات. أكد أن EVALUATOR_ENDPOINT معيّن على عملية الخادم، أن الخادم وخدمة التقييم يشتركان في نفس قيمة EVALUATOR_TOKEN، وأن نقطة نهاية /health الخاصة بخدمة التقييم يمكن الوصول إليها من الخادم. مع عدم تعيين EVALUATOR_ENDPOINT خط الأنابيب هو عدم تشغيل. التقييمات قيد الطيران تتراكم. استعلم GET /evaluation-jobs لعرض قائمة الانتظار قيد الطيران. فحص attempt_count, next_attempt_at, و last_error على كل صف. الأسباب الشائعة: خدمة المقيّم غير قابلة للوصول أو تُرجع 5xx (أعيدت المحاولة مع التراجع)، خطأ في EVALUATOR_TOKEN (401 نهائي)، أو مقيّم غير متزامن يُرجع pending إلى الأبد (انظر أدناه). انتهت الجلسات لكن لم يتم تقييم نهائي. استعلم GET /evaluation-jobs?status=polling؛ قد تبقى النتيجة قيد الطيران. إذا كانت وظيفة عالقة في pending، يواجه الخادم مشكلة في الوصول إلى خدمة التقييم؛ تحقق من أن خدمة التقييم قيد التشغيل وأن EVALUATOR_TOKEN تطابق. HTTP 401 من خدمة التقييم: رمز متحمل غير صالح. EVALUATOR_TOKEN على الخادم لا يتطابق مع القيمة التي تم تكوين خدمة التقييم بها. يجب أن تكون متطابقة. مقيّم غير متزامن يُرجع pending إلى الأبد. يستطلع الخادم GET /evaluate/{job_id} حتى تُرجع خدمة التقييم done أو error، أو حتى EVALUATOR_MAX_POLL_DURATION_SECS (الافتراضي 1 ساعة) ينقضي. بعد الحد الأقصى يتم تسجيل التقييم كـ timeout وإزالته من قائمة الانتظار قيد الطيران. ارفع EVALUATOR_MAX_POLL_DURATION_SECS إذا كانت خدمة التقييم الخاصة بك تحتاج بشرعية إلى وقت أطول من الافتراضي.