01
تجربة واحدة لكل run
لا pipeline ولا registry ولا discovery وقت التشغيل، ولا قواعد تضبط تفاعل عدة تجارب.
لا يتيح كل generation run إلا تجربة Rust واحدة، على أن تكون statically compiled. ومن خلالها يمكن مراقبة التنفيذ أو تعديل activation قائمة في موضعها، من دون أن يتحول ember إلى منصة plugins عامة. ويظل العقد في v0.1 غير مستقر عن قصد.
// observation
tensor.values()
output remains numerically unchanged
// intervention
tensor.values_mut()
tensor.zero()
output may change
لا تزال واجهة التجارب في Rust غير مستقرة ضمن ember v0.1؛ فهي لا تمثل plugin ABI ديناميكية ولا تضمن التوافق وفق semver.
في مسار generation العادي، يضع ember hooks عند حدود دلالية معتمدة؛ فتظل الفروق العددية بين المعماريات ظاهرة، ولا يحتاج تشغيل hook إلى نسخ tensors.
لا ينشئ المسار العادي ExperimentRunner. وعند
تفعيل التجارب، لا يضم الـ run سوى تنفيذ واحد لتجربة مجمّعة
مع البرنامج؛ ثم يستدعي الـ methods الخاصة بها عند الحدود
المعتمدة للطبقات والـ logits. ويقتصر السلوك الافتراضي على
observation، ولا يحدث أي تدخل إلا بوصول mutable وصريح إلى
activation قائمة. وهكذا تكفي واجهة الـ hooks لإجراء تجارب
فعلية من دون تحويل ember إلى منصة plugins عامة.
01
تجربة واحدة لكل run
لا pipeline ولا registry ولا discovery وقت التشغيل، ولا قواعد تضبط تفاعل عدة تجارب.
02
استعر، لا تنسخ
تستعير الـ contexts ما تحتاج إليه من metadata،
وتعرض TensorAccess الـ allocation في
صورة view، مع بقاء ملكيته للـ runtime.
03
المعمارية تبقى ظاهرة
أسماء الـ hooks المشتركة لا تمحو normalization أو RoPE أو ترتيب العمليات الخاص بكل عائلة.
TensorAccess<'_>values()
مراقبة؛ لا تغيّر الناتج العددي
values_mut() / zero()
تدخّل؛ قد يغيّر التنفيذ
لا يفرض نظام الأنواع في الواجهة سلوك observation-only؛
لذلك يتحمل تنفيذ التجربة مسؤولية هذا الضمان. يحافظ
استخدام values() على التنفيذ، في حين قد
يغيّره استخدام values_mut() أو
zero().
ابنِ ember مرة واحدة، ثم استخدم خيار تجربة واحداً مع أمر generation عادي. الأمثلة تفترض أن ملفات النموذج والـ tokenizer موجودة في المجلد الحالي.
cargo build --release
تظهر تنبيهات التجربة وملخصاتها في stderr،
فيما يحتفظ النص المولّد بتنسيق stdout الحالي.
وبما أن الـ run لا يقبل أكثر من تجربة نشطة، فلا يمكن جمع
الخيارين المدمجين.
عند كل tensor hook، يسجل L2 norm والقيمة المطلقة القصوى وfingerprint خفيفة.
تعرض جميع الـ tensor hooks في v0.1 activations من
نوع f32. ومن دون طلب mutable access، تستخرج
activation-stats من هذه القيم
L2 norm والقيمة المطلقة القصوى وfingerprint
خفيفة. فإذا اكتمل generation بنجاح، كتبت السجلات مرتبة
في artifact بصيغة JSON. ولا تمس هذه العملية
logits أو التوكنات المولدة.
target/release/ember \
--arch qwen3 \
--model Qwen3-0.6B-Q8_0.gguf \
--tokenizer tokenizer-qwen3.json \
--prompt "The capital of France is" \
--max-tokens 4 \
--temperature 0 \
--activation-stats activation-stats.json
prefill أو decodeتعتمد الـ fingerprint خوارزمية structured tracing نفسها المستخدمة في ember، وتأخذ عينة واحدة من كل 64 قيمة. لذا تفيد في تحديد موضع divergence لا في إثبات التطابق تشفيريًا. ولا يكتفي حساب الـ norm بالعينة، بل يفحص القيم كلها.
jq '.records[] | select(.stage == "after_layer") |
{phase, layer_index, sequence_length, l2_norm, fingerprint}' \
activation-stats.json
الـ observation يحافظ على الناتج العددي، لا على التوقيت. مسح activations وتخزين السجلات يضيفان عملاً؛ لذلك ينبغي قياس هذا الحمل في benchmark منفصل.
يصفّر مرحلة دلالية واحدة أثناء prefill، ومرة في كل تقييم decode أحادي التوكن يصل إلى الطبقة المختارة.
يتلقى الخيار رقم طبقة يبدأ من الصفر ومرحلة دلالية
بالصيغة LAYER:STAGE. وبعد تحميل النموذج،
يتحقق ember من الرقم، ثم يعدّل الـ tensor
نفسها في موضعها ويحصي التدخلات. ويجري التدخل مرة في
prefill، ثم مرة كلما بلغ تقييم decode الطبقة المختارة.
target/release/ember \
--arch gemma4 \
--model models/gemma-4-E2B-it.Q8_0.gguf \
--tokenizer tokenizer-gemma4.json \
--prompt "The capital of France is" \
--max-tokens 8 \
--temperature 0 \
--zero-layer-output 4:attention
| المرحلة | الـ tensor التي تُستبدل بالصفر | الموضع |
|---|---|---|
attention |
مساهمة attention | مباشرة قبل residual addition |
mlp |
مساهمة MLP | مباشرة قبل residual addition |
layer |
hidden state المكتملة | بعد اكتمال كل العمليات الخاصة بعائلة النموذج داخل الطبقة |
يفشل الأمر أثناء تحليل CLI إذا كان اسم المرحلة غير صالح. وإذا خرج رقم الطبقة عن نطاق النموذج المحمّل، تعرض رسالة الخطأ معرّف النموذج وعائلته والرقم المطلوب والنطاق الصحيح.
research experiment active: zero-layer-output layer=4 stage=attention; execution will be modified
experiment zero-layer-output: 8 intervention(s) at layer 4 stage attention
يشمل العداد تدخل prefill وكل تقييم decode لاحق يبلغ الطبقة؛ لذلك قد يظهر في ملخص generation run واحد أكثر من تدخل. ولا يدل هذا العدد على أن التجربة عدّلت عدة طبقات.
| الواجهة | من دون تجربة | مع تجربة نشطة |
|---|---|---|
stdout |
تنسيق النص المولّد الحالي | التنسيق نفسه |
stderr |
لا تنبيه خاص بالتجربة | تنبيه تفعيل، وملخص عند الاكتمال الناجح |
| run manifest | لا يوجد حقل للتجربة | الاسم، والإعدادات، وهل عدّلت التنفيذ |
| artifact | لا يوجد | activation-stats يكتب JSON |
يسجل الـ manifest عند استخدام
activation-stats القيمة
"modifies_execution": false. وعند إجراء
intervention، يسجل الطبقة والمرحلة والقيمة
"modifies_execution": true. وفي الحالتين، يبقى
artifact الخاص بالتجربة ملفًا منفصلًا عن run manifest
والنص المولّد.
| الواجهة | الحالة | ملاحظات |
|---|---|---|
| generation عادي لـ LLaMA وQwen3 وGemma 4 | مدعوم | دعم النموذج لا يعني تلقائياً دعم experiment hooks |
| generation لـ Qwen2.5 | experimental | لم تكتمل validation المعمارية والـ tokenizer، ولا يشمله سجل parity المتحقق منه |
| experiment hooks لـ LLaMA وQwen3 وGemma 4 | مدعوم | prefill وsingle-token decode عبر الحدود الدلالية نفسها |
| experiment hooks لـ GPT-2 | غير مدمج | لا يوجد له مسار experiment hooks في v0.1 |
| استخراج hidden states والـ probes | مرفوض مع تجربة نشطة | دلالات التمثيل غير معرّفة حتى الآن |
| layer/logit dumps | مرفوض مع تجربة نشطة | الواجهات العادية من دون تجربة لم تتغير |
| أوامر demo وinteractive وbenchmark الفرعية | مرفوض مع تجربة نشطة | التجارب تستهدف generation العادي حالياً |
لا يمكن استخدام التجارب النشطة عند استخراج hidden states أو probes أو layer dumps أو logits dumps، إذ لم يحدد ember بعد ما إذا كانت واجهات الفحص هذه ستعرض القيم قبل intervention أم بعده.
تأتي التجارب في صورة كود Rust يجمّعه ember ضمن البرنامج. فاحصر الإضافة في نطاق ضيق، ولا توسّع الإطار لخدمة تنفيذ واحد.
src/experiments/.Experiment، واترك الـ hooks غير المستخدمة على defaults الخاصة بها.TensorAccess فقط عند tensor hook معتمد.ExperimentError.اقرأ عقد الـ hooks قبل اختيار موضع الإدخال. ففيه توثيق لملكية tensors، والسلوك الخاص بكل عائلة، وحقول الـ context، وmetadata عند الفشل، والمسار المعطّل.
النطاق ضيق عمداً. لا توجد plugins ديناميكية بصيغة
.so أو .dll، ولا
WASM hooks، ولا Python bindings، ولا discovery
وقت التشغيل. كذلك لا توجد عدة تجارب متزامنة أو async hooks
أو event bus عامة أو إمكانية لتعديل الأوزان اعتباطياً أو
tokenizers وexecution backends مخصصة. ولا يقدّم الإصدار
ادعاءً واسعاً عن ملاءمته لـ production inference.