<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LLM on kenji.blog</title><link>http://kenji.blog/ar/categories/llm/</link><description>Recent content in LLM on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 16:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/categories/llm/index.xml" rel="self" type="application/rss+xml"/><item><title>كيفية ضبط TinyLLaMA بأسرع طريقة في بيئة محلية</title><link>http://kenji.blog/ar/p/tinyllama-on-premises-fast-tuning-guide/</link><pubDate>Fri, 11 Sep 2026 16:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/tinyllama-on-premises-fast-tuning-guide/</guid><description>&lt;img src="http://kenji.blog/p/tinyllama-on-premises-fast-tuning-guide/img/eyecatch.jpg" alt="Featured image of post كيفية ضبط TinyLLaMA بأسرع طريقة في بيئة محلية" />&lt;h2 id="1-مقدمة-لماذا-tinyllama-والبيئة-المحلية-الآن">1. مقدمة: لماذا TinyLLaMA والبيئة المحلية الآن؟
&lt;/h2>&lt;p>يتقدم تطور النماذج اللغوية الكبيرة (LLMs) بسرعة هائلة، ومع ذلك يستمر عدد معلمات النماذج (Parameters) في التضخم ليصل إلى مئات المليارات. في حين أن النماذج الضخمة مثل GPT-4 و Claude 3 تتمتع بأداء لا مثيل له، إلا أن التكلفة الحسابية اللازمة للاستنتاج (Inference) والتدريب، بالإضافة إلى المخاوف المتعلقة بالأمان وخصوصية البيانات عند استخدام واجهات برمجة التطبيقات (APIs) الخارجية، تشكل عقبات كبيرة للشركات. خاصة في الأعمال التي تتعامل مع بيانات داخلية سرية للغاية أو معلومات شخصية، فإن إرسال البيانات إلى واجهات برمجة تطبيقات LLM عامة على السحابة (Cloud) غالباً ما يكون غير مقبول من منظور الامتثال (مثل GDPR و APPI).&lt;/p>
&lt;p>لذلك، تتجه الأنظار نحو &lt;strong>النماذج اللغوية الصغيرة (SLM: Small Language Models)&lt;/strong> و &lt;strong>التشغيل المحلي في بيئات محلية (On-premises)&lt;/strong>. من بينها، يتميز &amp;ldquo;&lt;strong>TinyLLaMA&lt;/strong>&amp;rdquo; بحجمه المدمج الذي يبلغ 1.1 مليار معلمة فقط (1.1B)، إلا أنه تم تدريبه مسبقًا على مجموعة بيانات ضخمة تبلغ حوالي 3 تريليون رمز (Tokens)، مما يجعله يظهر أداءً مذهلاً مقارنة بالنماذج من نفس الفئة.&lt;/p>
&lt;p>في هذا المقال، سنقدم دليلاً كاملاً للضبط الدقيق (Fine-tuning) لـ TinyLLaMA في بيئة محلية (خادم محلي أو محطة عمل) للمهام الخاصة بشركتك، بـ &amp;ldquo;أسرع وأعلى كفاءة&amp;rdquo;. سنشرح كل شيء بشمولية، بدءًا من الخلفية الرياضية وتقنيات التحسين الحديثة، وصولاً إلى أكواد التنفيذ الفعلية باستخدام PyTorch.&lt;/p>
&lt;hr>
&lt;h2 id="2-بنية-tinyllama-وخصائصه">2. بنية TinyLLaMA وخصائصه
&lt;/h2>&lt;p>يعتمد TinyLLaMA على بنية LLaMA (Large Language Model Meta AI) التي طورتها شركة Meta. على الرغم من إبقاء عدد المعلمات عند 1.1B، إلا أنه يستخدم نفس حزمة التقنيات المستخدمة في LLaMA 2، مما يتميز بتوافق عالٍ جداً مع النظام البيئي.&lt;/p>
&lt;h3 id="مكونات-البنية-الأساسية">مكونات البنية الأساسية
&lt;/h3>&lt;ol>
&lt;li>&lt;strong>RMSNorm (Root Mean Square Normalization):&lt;/strong>
تقنية تطبيع (Normalization) تعمل على تحسين الكفاءة الحسابية عن طريق حذف طرح المتوسط من حسابات LayerNorm التقليدية. إنها تزيد من الإنتاجية مع الحفاظ على استقرار التدريب.&lt;/li>
&lt;li>&lt;strong>دالة التنشيط SwiGLU:&lt;/strong>
في شبكة التغذية الأمامية (Feed Forward Network - FFN)، يتم استخدام SwiGLU بدلاً من ReLU أو GELU التقليدية. يتم التعبير عن هذا رياضياً على النحو التالي:
$$ \text{SwiGLU}(x, W, V) = \text{Swish}(xW) \otimes (xV) $$
هنا، يمثل $\otimes$ الضرب على مستوى العناصر (Hadamard product)، ودالة Swish هي $\text{Swish}(z) = z \cdot \sigma(\beta z)$. هذا يحسن من القدرة التعبيرية بشكل كبير.&lt;/li>
&lt;li>&lt;strong>RoPE (Rotary Position Embedding):&lt;/strong>
طريقة تجمع بين مزايا التضمين الموضعي المطلق (Absolute position encoding) والنسبي (Relative position encoding). تتمتع بأداء تعميمي عالٍ حتى عند تمديد طول التسلسل.&lt;/li>
&lt;li>&lt;strong>Grouped Query Attention (GQA):&lt;/strong>
نهج وسط بين Multi-Head Attention (MHA) و Multi-Query Attention (MQA)، ومن خلال تجميع رؤوس المفاتيح (Keys) والقيم (Values)، فإنه يوفر عرض النطاق الترددي للذاكرة ويزيد من سرعة الاستنتاج بشكل كبير.&lt;/li>
&lt;/ol>
&lt;p>يوضح مخطط Mermaid أدناه تدفق البيانات العام لـ TinyLLaMA وبنية كتلة المحول (Transformer block).&lt;/p>
&lt;div class="mermaid">graph TD
A["النص المدخل"] --> B["المرمز (BPE)"]
B --> C["طبقة التضمين"]
C --> D["كتل المحول (22 طبقة لـ TinyLLaMA)"]
D --> E["RMSNorm (نهائي)"]
E --> F["الإسقاط الخطي (حجم المفردات)"]
F --> G["احتمالات المخرجات (Softmax)"]
subgraph "تشريح كتلة المحول"
D1["حالة الإخفاء المدخلة"] --> D2["RMSNorm"]
D2 --> D3["انتباه الاستعلام المجمع (GQA)"]
D3 --> D4["إضافة متبقية"]
D4 --> D5["RMSNorm"]
D5 --> D6["SwiGLU FFN"]
D6 --> D7["إضافة متبقية"]
D7 --> D8["المخرجات للطبقة التالية"]
D1 -.-> D4
D4 -.-> D7
end&lt;/div>
&lt;hr>
&lt;h2 id="3-اختراق-في-الضبط-الدقيق-lora-و-qlora">3. اختراق في الضبط الدقيق: LoRA و QLoRA
&lt;/h2>&lt;p>لإجراء ضبط دقيق كامل المعلمات (Full parameter fine-tuning) في بيئة محلية، حتى بالنسبة لنموذج 1.1B، فإنه يستهلك عشرات الجيجابايت من ذاكرة VRAM (ذاكرة الفيديو) للاحتفاظ بحالة المحسن (Optimizer) والتدرجات (Gradients). لتحقيق تدريب فعال بموارد محدودة، من الضروري استخدام طريقة &lt;strong>PEFT (Parameter-Efficient Fine-Tuning)&lt;/strong> وهي &amp;ldquo;&lt;strong>LoRA&lt;/strong>&amp;rdquo; وامتداد التكميم (Quantization) الخاص بها &amp;ldquo;&lt;strong>QLoRA&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;h3 id="31-الخلفية-الرياضية-لـ-lora-low-rank-adaptation">3.1 الخلفية الرياضية لـ LoRA (Low-Rank Adaptation)
&lt;/h3>&lt;p>LoRA هي طريقة تقوم بتجميد (Freeze) مصفوفات الأوزان المدربة مسبقًا، وتقريب مقدار تحديث الوزن ($\Delta W$) كحاصل ضرب مصفوفتين صغيرتين منخفضتي الرتبة (Low-rank).&lt;/p>
&lt;p>لنفترض أن الأوزان المدربة مسبقًا هي $W_0 \in \mathbb{R}^{d \times k}$. في الضبط الدقيق الكامل، يتم تحديث $W_0$ نفسها لتصبح $W_0 + \Delta W$، ولكن في LoRA يتم تحليل مصفوفة التحديث $\Delta W$ على النحو التالي:&lt;/p>
$$ \Delta W = B \times A $$
&lt;p>هنا، $B \in \mathbb{R}^{d \times r}$، و $A \in \mathbb{R}^{r \times k}$، و $r$ هي معلمة فائقة (Hyperparameter) تسمى الرتبة (Rank)، وهي قيمة صغيرة جداً (عادة 8، 16، 32، وما إلى ذلك) تلبي $r \ll \min(d, k)$.&lt;/p>
&lt;p>يكون حساب التمرير الأمامي (Forward pass) على النحو التالي:&lt;/p>
$$ h = W_0 x + \Delta W x = W_0 x + B A x $$
&lt;p>في الحالة الأولية، تتم تهيئة المصفوفة $A$ بشكل عشوائي بتوزيع طبيعي (Gaussian distribution)، وتتم تهيئة المصفوفة $B$ كمصفوفة صفرية. وبسبب هذا، تكون $\Delta W$ في بداية التدريب صفراً، مما يسمح ببدء التدريب مع الاحتفاظ بمخرجات النموذج الأساسي (Base model) بالكامل.&lt;/p>
&lt;div class="mermaid">graph LR
X["متجه الإدخال x"] --> W0["الوزن المجمد المدرب مسبقًا (W_0)"]
X --> A["مصفوفة LoRA القابلة للتدريب A (r x k)"]
A --> B["مصفوفة LoRA القابلة للتدريب B (d x r)"]
W0 --> Add["جمع المتجهات"]
B --> Add
Add --> Y["متجه الإخراج h"]&lt;/div>
&lt;h3 id="32-ابتكار-qlora-quantized-lora">3.2 ابتكار QLoRA (Quantized LoRA)
&lt;/h3>&lt;p>تدفع QLoRA بنهج LoRA خطوة أبعد، وهي طريقة تقوم بتكميم (Quantize) النموذج الأساسي $W_0$ إلى دقة 4-bit (NormalFloat 4, NF4) وتحميله في الذاكرة. هذا يقلل بشكل كبير من استهلاك VRAM.&lt;/p>
&lt;p>تتضمن QLoRA ثلاث تقنيات مهمة:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>تكميم 4-bit NormalFloat (NF4):&lt;/strong> نوع بيانات مثالي نظرياً ومحسن للأوزان التي تتبع توزيعاً طبيعياً.&lt;/li>
&lt;li>&lt;strong>التكميم المزدوج (Double Quantization):&lt;/strong> يوفر المزيد من الذاكرة عن طريق تكميم ثوابت التكميم (معاملات المقياس - Scale factors) نفسها.&lt;/li>
&lt;li>&lt;strong>Paged Optimizers:&lt;/strong> آلية تستخدم ميزة الذاكرة الموحدة من NVIDIA لتفريغ (Evict) حالة المحسن مؤقتاً إلى ذاكرة الوصول العشوائي (RAM) الخاصة بوحدة المعالجة المركزية (CPU) عند نفاد VRAM.&lt;/li>
&lt;/ol>
&lt;p>نتيجة لذلك، فإن الضبط الذي يتطلب عادةً من 16 جيجابايت إلى 24 جيجابايت من VRAM يمكن إجراؤه بسهولة على وحدات معالجة رسومات استهلاكية (مثل RTX 3060 12GB أو RTX 4070).&lt;/p>
&lt;hr>
&lt;h2 id="4-متطلبات-الأجهزة-والإعداد-في-البيئة-المحلية">4. متطلبات الأجهزة والإعداد في البيئة المحلية
&lt;/h2>&lt;p>تعتبر متطلبات الأجهزة لضبط TinyLLaMA (1.1B) باستخدام QLoRA منخفضة جداً.&lt;/p>
&lt;h3 id="مواصفات-الأجهزة-الموصى-بها">مواصفات الأجهزة الموصى بها
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>وحدة معالجة الرسومات (GPU):&lt;/strong> NVIDIA RTX 3060 (12GB) أو RTX 3090/4090 (24GB) أو NVIDIA A10G/A100 وغيرها. تعمل إذا كان هناك 8 جيجابايت من VRAM على الأقل، ولكن يوصى بـ 12 جيجابايت أو أكثر لزيادة حجم الدفعة (Batch size).&lt;/li>
&lt;li>&lt;strong>وحدة المعالجة المركزية (CPU):&lt;/strong> وحدة معالجة مركزية حديثة بـ 8 نوى أو أكثر (Intel Core i7/i9، AMD Ryzen 7/9)&lt;/li>
&lt;li>&lt;strong>ذاكرة الوصول العشوائي (RAM):&lt;/strong> 32 جيجابايت أو أكثر (مهمة كوجهة إخلاء من VRAM عند استخدام Paged Optimizers)&lt;/li>
&lt;li>&lt;strong>مساحة التخزين:&lt;/strong> NVMe SSD (لتسريع قراءة مجموعة البيانات وحفظ النموذج)&lt;/li>
&lt;/ul>
&lt;h3 id="إعداد-بيئة-البرامج">إعداد بيئة البرامج
&lt;/h3>&lt;p>هذه إرشادات الإعداد بفرض استخدام بيئة Ubuntu 22.04 LTS. سنستخدم Python 3.10 أو أحدث.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># إنشاء بيئة افتراضية وتفعيلها&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m venv tinyllama_env
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">source&lt;/span> tinyllama_env/bin/activate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># تثبيت PyTorch (لـ CUDA 12.1)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># تثبيت المكتبات المتعلقة بالمحولات (Transformers)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install transformers datasets peft trl accelerate bitsandbytes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="5-تقنيات-التحسين-للحصول-على-أسرع-ضبط">5. تقنيات التحسين للحصول على أسرع ضبط
&lt;/h2>&lt;p>لإكمال الضبط بـ &amp;ldquo;أسرع&amp;rdquo; طريقة، لا يكفي مجرد تشغيل النص البرمجي، بل يجب الجمع بين تقنيات التحسين التالية.&lt;/p>
&lt;h3 id="51-flash-attention-2">5.1 Flash Attention 2
&lt;/h3>&lt;p>في آلية الانتباه (Attention) القياسية، يكون التعقيد الزمني والمكاني $O(N^2)$ بالنسبة لطول التسلسل $N$. تعمل تقنية Flash Attention 2 على تحسين الوصول إلى الذاكرة بين SRAM و HBM (الذاكرة ذات النطاق الترددي العالي) في GPU، مما يزيل اختناقات الإدخال/الإخراج (IO bottlenecks) دون تقليل كمية الحسابات، ويرفع سرعة التدريب عدة مرات، ويقلل استهلاك الذاكرة بشكل كبير.&lt;/p>
&lt;h3 id="52-gradient-checkpointing-نقاط-فحص-التدرج">5.2 Gradient Checkpointing (نقاط فحص التدرج)
&lt;/h3>&lt;p>بدلاً من حفظ جميع التنشيطات الوسيطة (Intermediate activations) المحسوبة في التمرير الأمامي في VRAM، تقوم هذه الطريقة بحفظ جزء منها فقط، وإعادة حسابها عند الحاجة في التمرير الخلفي (Backward pass). يزداد وقت الحساب بنسبة 20٪ تقريبًا، ولكن يمكن تقليل استهلاك الذاكرة بشكل كبير، مما يسمح بتعيين حجم دفعة (Batch size) أكبر، وبالتالي تحسين الإنتاجية الإجمالية.&lt;/p>
&lt;h3 id="53-mixed-precision-training-التدريب-بالدقة-المختلطة-و-bfloat16">5.3 Mixed Precision Training (التدريب بالدقة المختلطة) و Bfloat16
&lt;/h3>&lt;p>لتحقيق أقصى استفادة من Tensor Cores في GPU، نستخدم &lt;code>bfloat16&lt;/code> (Brain Floating Point) للحسابات أثناء التدريب. بالمقارنة مع &lt;code>float16&lt;/code>، فإن طول البت للأس هو نفسه في &lt;code>float32&lt;/code>، لذلك يكون خطر تجاوز السعة (Overflow) وانخفاض السعة (Underflow) منخفضًا جدًا، مما يجعل التدريب مستقرًا.&lt;/p>
&lt;hr>
&lt;h2 id="6-عملي-كود-الضبط-الدقيق-qlora-لـ-tinyllama">6. عملي: كود الضبط الدقيق QLoRA لـ TinyLLaMA
&lt;/h2>&lt;p>الآن، سنشرح نص PyTorch المخصص لأسرع ضبط، والذي يتضمن جميع التحسينات المذكورة أعلاه. هنا نستخدم &lt;code>SFTTrainer&lt;/code> من مكتبة &lt;code>trl&lt;/code> (Transformer Reinforcement Learning) الخاصة بـ Hugging Face.&lt;/p>
&lt;h3 id="61-تجهيز-مجموعة-البيانات-وتحميل-النموذج">6.1 تجهيز مجموعة البيانات وتحميل النموذج
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datasets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">load_dataset&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">transformers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">AutoModelForCausalLM&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">AutoTokenizer&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">BitsAndBytesConfig&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">TrainingArguments&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">peft&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">LoraConfig&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_peft_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">prepare_model_for_kbit_training&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">trl&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">SFTTrainer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. تحديد النموذج والمرمز (Tokenizer)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;TinyLlama/TinyLlama-1.1B-Chat-v1.0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. إعدادات تكميم 4-bit لـ QLoRA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">bnb_config&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BitsAndBytesConfig&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">load_in_4bit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bnb_4bit_use_double_quant&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bnb_4bit_quant_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;nf4&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bnb_4bit_compute_dtype&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bfloat16&lt;/span> &lt;span class="c1"># إجراء الحسابات باستخدام bfloat16&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. تحميل النموذج (تفعيل Flash Attention 2)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Loading model...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AutoModelForCausalLM&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_pretrained&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">quantization_config&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">bnb_config&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device_map&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;auto&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">use_flash_attention_2&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span> &lt;span class="c1"># مفتاح التسريع&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. تحميل المرمز (Tokenizer)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AutoTokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">trust_remote_code&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pad_token&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">eos_token&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">padding_side&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;right&amp;#34;&lt;/span> &lt;span class="c1"># التعيين إلى right لتجنب الأخطاء أثناء التدريب باستخدام fp16/bf16&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-تطبيق-محول-lora-وتنسيق-مجموعة-البيانات">6.2 تطبيق محول LoRA وتنسيق مجموعة البيانات
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 5. التحضير لتدريب k-bit وتفعيل نقاط فحص التدرج&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gradient_checkpointing_enable&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">prepare_model_for_kbit_training&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 6. إعدادات LoRA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">peft_config&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">LoraConfig&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">r&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># الرتبة&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lora_alpha&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># معامل التحجيم&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lora_dropout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.05&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bias&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;none&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">task_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;CAUSAL_LM&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">target_modules&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;q_proj&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;k_proj&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;v_proj&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;o_proj&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;gate_proj&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;up_proj&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;down_proj&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># استهداف جميع الطبقات الخطية يحسن الأداء&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_peft_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">peft_config&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">print_trainable_parameters&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># مثال للمخرجات: trainable params: 14,286,848 || all params: 1,114,335,232 || trainable%: 1.282%&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 7. تحميل مجموعة البيانات (نستخدم هنا مجموعة بيانات Instruction باللغة اليابانية كمثال)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># في الواقع، ستقوم بتحميل ملف JSONL خاص بك من البيئة المحلية&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dataset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">load_dataset&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;kunishou/databricks-dolly-15k-ja&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">split&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;train&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">format_instruction&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sample&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> تنسيق السلسلة لتتناسب مع تنسيق ChatML أو قالب الموجه (Prompt template)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;|im_start|&amp;gt;user&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">sample&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;instruction&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sample&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">sample&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;input&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;|im_end|&amp;gt;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;lt;|im_start|&amp;gt;assistant&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">sample&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;output&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;lt;|im_end|&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">prompt&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dataset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dataset&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">format_instruction&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="63-تنفيذ-التدريب">6.3 تنفيذ التدريب
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 8. إعداد وسائط التدريب&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">training_args&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TrainingArguments&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output_dir&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;./tinyllama-lora-output&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">per_device_train_batch_size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># يمكن زيادته إذا كانت هناك مساحة في VRAM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">gradient_accumulation_steps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># حجم الدفعة الفعلي = 8 * 2 = 16&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">optim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;paged_adamw_32bit&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># توفير VRAM باستخدام Paged Optimizer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">save_steps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logging_steps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">learning_rate&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">2e-4&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">fp16&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bf16&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># التدريب بالدقة المختلطة (bfloat16)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_grad_norm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.3&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_steps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 500 خطوة للاختبار. في الإنتاج، حدد عدد الحقبات (Epochs)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">warmup_ratio&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.03&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">group_by_length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lr_scheduler_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cosine&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 9. بدء التدريب باستخدام SFTTrainer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">trainer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SFTTrainer&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">train_dataset&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">dataset&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">peft_config&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">peft_config&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">dataset_text_field&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_seq_length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1024&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># تعديل ليناسب طول الإدخال المتوقع&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokenizer&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">tokenizer&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">args&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">training_args&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Starting training...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">trainer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">train&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 10. حفظ محول LoRA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">trainer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;./tinyllama-lora-final&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;./tinyllama-lora-final&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Training complete and model saved.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-تقييم-الأداء-واستكشاف-الأخطاء-وإصلاحها">7. تقييم الأداء واستكشاف الأخطاء وإصلاحها
&lt;/h2>&lt;p>إليك المشكلات الشائعة والحلول الخاصة بها عند تشغيل التدريب في بيئة محلية.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>حدوث OOM (Out Of Memory):&lt;/strong>
&lt;ul>
&lt;li>قلل &lt;code>per_device_train_batch_size&lt;/code> إلى &lt;code>1&lt;/code>.&lt;/li>
&lt;li>قم بزيادة &lt;code>gradient_accumulation_steps&lt;/code> للحفاظ على حجم الدفعة الفعلي.&lt;/li>
&lt;li>قم بتقصير &lt;code>max_seq_length&lt;/code> من &lt;code>2048&lt;/code> إلى &lt;code>1024&lt;/code> أو &lt;code>512&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>الخسارة (Loss) لا تنخفض أو تتباعد:&lt;/strong>
&lt;ul>
&lt;li>قد يكون معدل التعلم (&lt;code>learning_rate&lt;/code>) مرتفعًا جدًا. حاول تقليله من &lt;code>2e-4&lt;/code> إلى حوالي &lt;code>5e-5&lt;/code>.&lt;/li>
&lt;li>إذا كنت تستخدم Float16 بدلاً من Bfloat16، فقد يحدث انخفاض في سعة التدرجات (Underflow). تحقق من &lt;code>bf16=True&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>توليد سلاسل نصية غامضة أثناء الاستنتاج:&lt;/strong>
&lt;ul>
&lt;li>تأكد من تعيين &lt;code>padding_side=&amp;quot;right&amp;quot;&lt;/code> بشكل صحيح. بالإضافة إلى ذلك، تحقق مما إذا كان تنسيق مجموعة البيانات (مثل الرموز المميزة الخاصة &lt;code>&amp;lt;|im_start|&amp;gt;&lt;/code>) متوافقًا مع التنسيق المستخدم أثناء التدريب المسبق للنموذج الأساسي.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-نشر-النموذج-بعد-الضبط-deployment">8. نشر النموذج بعد الضبط (Deployment)
&lt;/h2>&lt;p>عند اكتمال الضبط، ما يتم حفظه ليس &amp;ldquo;النموذج الأساسي بأكمله&amp;rdquo;، بل فقط &amp;ldquo;&lt;strong>محول LoRA (أوزان الفروق)&lt;/strong>&amp;rdquo; الذي يبلغ حجمه بضعة ميغابايت إلى عشرات الميغابايت. لإجراء الاستنتاج بسرعة، يجب دمج (Merge) أوزان LoRA هذه في النموذج الأساسي الأصلي وتصديرها كنموذج واحد.&lt;/p>
&lt;h3 id="نص-دمج-النموذج-merge-script">نص دمج النموذج (Merge script)
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">peft&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AutoPeftModelForCausalLM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">transformers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AutoTokenizer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">output_dir&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./tinyllama-lora-final&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># تحميل النموذج والمحول باستخدام FP16/BF16&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AutoPeftModelForCausalLM&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_pretrained&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output_dir&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device_map&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;auto&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">torch_dtype&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bfloat16&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AutoTokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output_dir&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># دمج الأوزان وحفظها&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">merged_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merge_and_unload&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">merged_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;./tinyllama-merged&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">safe_serialization&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;./tinyllama-merged&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Model merged and saved successfully!&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="تشغيل-خادم-استنتاج-فائق-السرعة-باستخدام-vllm">تشغيل خادم استنتاج فائق السرعة باستخدام vLLM
&lt;/h3>&lt;p>عند النشر في بيئة محلية، ولتحقيق أقصى قدر من سرعة الاستنتاج (الرموز في الثانية - Tokens per second)، يوصى بشدة باستخدام &lt;strong>vLLM&lt;/strong> أو &lt;strong>TGI (Text Generation Inference)&lt;/strong> بدلاً من خط الأنابيب القياسي (&lt;code>pipeline&lt;/code>) الخاص بـ Hugging Face. يستخدم vLLM تقنية PagedAttention لمنع تجزئة ذاكرة GPU، مما يحسن من قدرة معالجة الطلبات المتزامنة بشكل كبير.&lt;/p>
&lt;p>يوضح مخطط Mermaid أدناه مسار العمل (Pipeline) من التدريب إلى نشر خادم الاستنتاج.&lt;/p>
&lt;div class="mermaid">graph TD
A["بيانات خاصة خام"] --> B["المعالجة المسبقة والتنسيق (JSONL)"]
B --> C["الضبط الدقيق QLoRA (باستخدام SFTTrainer)"]
C --> D["أوزان محول LoRA (.safetensors)"]
D --> E["الدمج مع النموذج الأساسي TinyLLaMA 1.1B"]
E --> F["النموذج المدمج"]
F --> G["النشر عبر خادم vLLM"]
G --> H["نقطة نهاية API / واجهة مستخدم (مثال: روبوت دردشة)"]&lt;/div>
&lt;p>يمكن إكمال بدء تشغيل خادم API باستخدام vLLM بأمر واحد فقط:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">python -m vllm.entrypoints.openai.api_server &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --model ./tinyllama-merged &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --host 0.0.0.0 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --port &lt;span class="m">8000&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --max-model-len &lt;span class="m">2048&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --dtype bfloat16
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بهذا، يتم بناء نقطة نهاية متوافقة مع OpenAI API في البيئة المحلية، مما يسمح باستخدام الذكاء الاصطناعي المحلي بشكل آمن وسريع.&lt;/p>
&lt;hr>
&lt;h2 id="9-الخلاصة">9. الخلاصة
&lt;/h2>&lt;p>في هذا المقال، شرحنا كيفية إجراء ضبط دقيق (Fine-tuning) لنموذج &amp;ldquo;TinyLLaMA&amp;rdquo;، الذي يتميز بأداء عالٍ على الرغم من خفة وزنه (1.1 مليار معلمة)، بأسرع طريقة وأكثرها كفاءة في استخدام الذاكرة في بيئة محلية (On-premises).&lt;/p>
&lt;ul>
&lt;li>من خلال &lt;strong>LoRA / QLoRA&lt;/strong>، أصبح من الممكن إجراء ضبط لـ LLM بشكل احترافي حتى على وحدات معالجة الرسومات المخصصة للمستهلكين.&lt;/li>
&lt;li>من خلال الاستفادة من &lt;strong>Flash Attention 2&lt;/strong> و &lt;strong>Gradient Checkpointing&lt;/strong>، قمنا بتحسين وقت التدريب واستهلاك VRAM إلى أقصى حد.&lt;/li>
&lt;li>من خلال النشر باستخدام &lt;strong>vLLM&lt;/strong>، حققنا إنتاجية عالية حتى في بيئة الإنتاج.&lt;/li>
&lt;/ul>
&lt;p>لا يحافظ تشغيل LLM المحلي في بيئة محلية على سرية البيانات فحسب، بل يعمل أيضاً كأقوى سلاح لبناء ذكاء اصطناعي متخصص في مجالات معينة (مثل الشؤون القانونية والطبية واللوائح الداخلية) بتكلفة منخفضة. نأمل أن تستخدم هذا الدليل كمرجع لتدريب نموذج TinyLLaMA الخاص بشركتك.&lt;/p></description></item><item><title>دليل تطوير نماذج الذكاء الاصطناعي الصغيرة (مثل TinyLLaMA) باستخدام C++</title><link>http://kenji.blog/ar/p/cpp-small-ai-model-tinyllama-dev-guide/</link><pubDate>Fri, 11 Sep 2026 14:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/cpp-small-ai-model-tinyllama-dev-guide/</guid><description>&lt;img src="http://kenji.blog/p/cpp-small-ai-model-tinyllama-dev-guide/img/eyecatch.jpg" alt="Featured image of post دليل تطوير نماذج الذكاء الاصطناعي الصغيرة (مثل TinyLLaMA) باستخدام C++" />&lt;h1 id="دليل-تطوير-نماذج-الذكاء-الاصطناعي-الصغيرة-مثل-tinyllama-باستخدام-c">دليل تطوير نماذج الذكاء الاصطناعي الصغيرة (مثل TinyLLaMA) باستخدام C++
&lt;/h1>&lt;p>في الآونة الأخيرة، ازداد الاهتمام بشكل سريع بتشغيل النماذج اللغوية الكبيرة (LLM) في البيئات المحلية. على وجه الخصوص، يمكن للنماذج الصغيرة مثل TinyLLaMA (بحجم 1.1 مليار معلمة) إجراء الاستدلال بسرعة عملية حتى على الأجهزة الطرفية ذات الموارد المحدودة أو أجهزة الكمبيوتر المحمولة العادية (بما في ذلك بيئات Windows). بينما يعتبر التطوير باستخدام Python و PyTorch هو السائد، إلا أنه عند السعي لتحقيق الأداء الأمثل وكفاءة الذاكرة، يصبح الجمع بين C++ ومكتبة التنسور &amp;ldquo;ggml&amp;rdquo; المعتمدة على لغة C هو المعيار الفعلي.&lt;/p>
&lt;p>في هذا المقال، سنشرح خطوات تطوير مفصلة للغاية لبناء محرك استدلال من الصفر (أو فهم البنية الداخلية لـ llama.cpp الحالية بعمق) لتحميل TinyLLaMA وتوليد النصوص باستخدام C++.&lt;/p>
&lt;hr>
&lt;h2 id="1-لماذا-c-و-ggml">1. لماذا C++ و ggml؟
&lt;/h2>&lt;p>في مرحلة تدريب الذكاء الاصطناعي، تتفوق Python بفضل مرونتها ونظامها البيئي الغني. ومع ذلك، في مرحلة النشر أو &amp;ldquo;الاستدلال (Inference)&amp;quot;، تصبح C++ خياراً قوياً للأسباب التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>تقليل النفقات العامة (Overhead)&lt;/strong>: يمكن القضاء تماماً على قفل المترجم العالمي (GIL) والنفقات العامة لوقت التشغيل في Python.&lt;/li>
&lt;li>&lt;strong>كفاءة الذاكرة وتخصيص الساحة (Arena Allocation)&lt;/strong>: نظراً لإمكانية التحكم اليدوي في تخصيص وتحرير الذاكرة، يمكن منع الزيادات غير المتوقعة الناتجة عن جمع القمامة (Garbage Collection).&lt;/li>
&lt;li>&lt;strong>الوصول المباشر إلى الأجهزة&lt;/strong>: استدعاء الوظائف المضمنة لـ SIMD (Intrinsics) مباشرة مثل AVX-512 و AVX2 و ARM NEON، مما يتيح استغلال قدرات الحوسبة لوحدة المعالجة المركزية إلى أقصى حد.&lt;/li>
&lt;li>&lt;strong>التخلص من التبعيات&lt;/strong>: ggml هي مكتبة C/C++ خالية من التبعيات (Zero dependencies)، ويمكن بناؤها بسهولة حتى في بيئة MSVC على Windows بمجرد توفر مترجم.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="2-النظرة-العامة-على-البنية">2. النظرة العامة على البنية
&lt;/h2>&lt;p>يوضح مخطط Mermaid التالي سير العمل في خط أنابيب الاستدلال بالكامل. إنها سلسلة من العمليات تبدأ من النص المدخل من قبل المستخدم وصولاً إلى توليد الرمز (Token) التالي.&lt;/p>
&lt;div class="mermaid">graph TD
A["نص إدخال المستخدم"] --> B["BPE Tokenizer"]
B --> C["مصفوفة معرفات الرموز (Token IDs)"]
C --> D["البحث في طبقة التضمين (Embedding Layer Lookup)"]
D --> E["كتل المحول (Transformer Blocks)"]
E --> F["RMSNorm"]
F --> G["طبقة رأس LM (LM Head Layer)"]
G --> H["مصفوفة اللوغاريتمات (Logits)"]
H --> I["وحدة أخذ العينات (Sampler)"]
I --> J["معرف الرمز التالي (Next Token ID)"]
J --> K["Detokenizer"]
K --> L["قطعة النص المخرجة"]
J -.-> |"إضافة إلى السياق"| C&lt;/div>
&lt;p>نظراً لأنه نموذج انحدار ذاتي (Autoregressive)، تتم إضافة الرموز المخرجة مرة أخرى إلى السياق، وتدور كمدخلات لتوقع الرمز التالي (الجزء المتقطع في المخطط).&lt;/p>
&lt;hr>
&lt;h2 id="3-تنسيق-النموذج-وتخطيط-الذاكرة-mmap">3. تنسيق النموذج وتخطيط الذاكرة (mmap)
&lt;/h2>&lt;p>تعد القراءة/الكتابة على القرص واستهلاك الذاكرة العائق الأكبر عند التعامل مع أوزان الشبكات العصبية الضخمة. في تطبيقات C++، يتم حل ذلك باستخدام &lt;strong>تخطيط الذاكرة (Memory Mapping - mmap)&lt;/strong>.&lt;/p>
&lt;h3 id="31-كيفية-عمل-تخطيط-الذاكرة-وتطبيقه-في-windows">3.1 كيفية عمل تخطيط الذاكرة وتطبيقه في Windows
&lt;/h3>&lt;p>باستخدام mmap، يمكن تعيين محتويات الملف مباشرة إلى مساحة الذاكرة الافتراضية للعملية.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>نسخ صفري (Zero-copy)&lt;/strong>: يتم تحميل البيانات مباشرة من القرص إلى ذاكرة التخزين المؤقت للصفحات في النواة (Kernel)، ولا يحدث نسخ إضافي إلى مساحة المستخدم.&lt;/li>
&lt;li>&lt;strong>التحميل عند الطلب (Page Fault)&lt;/strong>: في اللحظة التي تصل فيها وحدة المعالجة المركزية فعلياً إلى عنوان الذاكرة ذلك، يحدث خطأ في الصفحة (Page Fault)، ويتم تحميل الكتلة المطلوبة فقط (عادة 4 كيلوبايت) في الذاكرة الفعلية.&lt;/li>
&lt;/ul>
&lt;p>في بيئة Windows، بدلاً من &lt;code>mmap&lt;/code> الخاصة بـ POSIX، يتم استخدام واجهات برمجة تطبيقات Win32 &lt;code>CreateFileMapping&lt;/code> و &lt;code>MapViewOfFile&lt;/code>.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant OS["نظام التشغيل Windows"]
participant RAM["الذاكرة الفعلية (Physical Memory)"]
participant App["تطبيق C++"]
App->>OS: "CreateFileMapping / MapViewOfFile"
OS-->>App: "مؤشر عنوان الذاكرة الافتراضية"
App->>App: "قراءة بيانات التنسور عند المؤشر"
OS->>RAM: "Page Fault / تحميل الصفحة من القرص"
RAM-->>App: "البيانات جاهزة لحسابات SIMD"&lt;/div>
&lt;h3 id="32-البنية-الثنائية-لتنسيق-gguf">3.2 البنية الثنائية لتنسيق GGUF
&lt;/h3>&lt;p>يعد &lt;strong>GGUF (GPT-Generated Unified Format)&lt;/strong>، المحول من تنسيقات مثل &lt;code>.safetensors&lt;/code> الخاصة بـ Hugging Face، التنسيق النهائي للاستدلال. يحتوي على المخطط الثنائي الصارم التالي:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>البتات السحرية (Magic Bytes)&lt;/strong>: &lt;code>0x46554747&lt;/code> (GGUF).&lt;/li>
&lt;li>&lt;strong>الإصدار (Version)&lt;/strong>: رقم إصدار التنسيق.&lt;/li>
&lt;li>&lt;strong>عدد التنسورات وعدد البيانات الوصفية (Tensor &amp;amp; Metadata Count)&lt;/strong>: عدد التنسورات وأزواج المفتاح-القيمة للبيانات الوصفية.&lt;/li>
&lt;li>&lt;strong>البيانات الوصفية (Metadata)&lt;/strong>: مفاتيح ببادئات طول السلسلة وقيم محددة النوع.&lt;/li>
&lt;li>&lt;strong>معلومات التنسور (Tensor Info)&lt;/strong>: اسم كل تنسور، عدد الأبعاد، نوع البيانات (FP16، Q4_K، إلخ)، وموقع الإزاحة داخل الملف.&lt;/li>
&lt;li>&lt;strong>الحشو (Padding)&lt;/strong>: حشوات مدرجة لمحاذاة بيانات التنسور مع حدود معينة (عادة 32 بايت أو 64 بايت). هذا ضروري للوصول السريع للذاكرة في تعليمات SIMD (وخاصة AVX).&lt;/li>
&lt;li>&lt;strong>بيانات التنسور (Tensor Data)&lt;/strong>: مصفوفة بيانات الأوزان الفعلية المحاذاة.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="4-الأساس-الرياضي-لـ-tinyllama-وخوارزميات-c">4. الأساس الرياضي لـ TinyLLaMA وخوارزميات C++
&lt;/h2>&lt;p>يعتمد TinyLLaMA بعض الابتكارات المعمارية المتقدمة لزيادة الكفاءة. سنشرح التمثيلات الرياضية لتنفيذها بشكل صحيح في C++.&lt;/p>
&lt;h3 id="41-التقييس-الجذري-لمتوسط-المربعات-rmsnorm">4.1 التقييس الجذري لمتوسط المربعات (RMSNorm)
&lt;/h3>&lt;p>يقلل التكلفة الحسابية عن طريق حذف مركزة المتوسط من LayerNorm وتنفيذ قياس التباين فقط.&lt;/p>
$$ \text{RMSNorm}(x) = \frac{x}{\sqrt{\frac{1}{d}\sum_{i=1}^{d} x_i^2 + \epsilon}} \odot \gamma $$
&lt;p>حيث $d$ هو عدد الأبعاد، و $\gamma$ هو تنسور المقياس المُدرَّب.
عند التنفيذ بـ C++، نقوم أولاً بحساب مجموع مربعات المصفوفة بسرعة باستخدام &lt;code>_mm256_fmadd_ps&lt;/code> في AVX2، وتحسينه عن طريق ضربه بالجذر التربيعي العكسي (مثل تعليمة &lt;code>_mm256_rsqrt_ps&lt;/code>).&lt;/p>
&lt;h3 id="42-التضمين-الموضعي-الدوار-rope">4.2 التضمين الموضعي الدوار (RoPE)
&lt;/h3>&lt;p>هي تقنية لتطبيق معلومات موقع الرمز كدوران (Rotate) في مساحة التنسور. يمكن اعتبارها دوراناً على مستوى الأعداد المركبة، ويتم تطبيق الدوران التالي على الأزواج البعدية المتجاورة $(x_1, x_2)$ للمتجه $x$:&lt;/p>
$$ \text{RoPE}(x, m) = \begin{pmatrix} x_{1} \cos(m\theta) - x_{2} \sin(m\theta) \\ x_{1} \sin(m\theta) + x_{2} \cos(m\theta) \end{pmatrix} $$
&lt;p>حيث $m$ هو المؤشر الموضعي المطلق للرمز، و $\theta$ هو التردد الأساسي المحسوب مسبقاً. في ggml، يتم تنفيذه بالتوازي ببساطة عن طريق إضافة عامل &lt;code>ggml_rope&lt;/code> أثناء بناء رسم الاستدلال البياني.&lt;/p>
&lt;h3 id="43-الانتباه-المجمع-للاستعلام-grouped-query-attention---gqa">4.3 الانتباه المجمع للاستعلام (Grouped-Query Attention - GQA)
&lt;/h3>&lt;p>في الانتباه متعدد الرؤوس (MHA) العادي، يوجد نفس عدد الرؤوس لكل من Query و Key و Value. ومع ذلك، لتقليل استهلاك عرض النطاق الترددي للذاكرة وذاكرة التخزين المؤقت KV بشكل كبير، يعتمد TinyLLaMA &lt;strong>Grouped-Query Attention (GQA)&lt;/strong>.&lt;/p>
$$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V $$
&lt;p>في GQA، تشترك عدة رؤوس Query في رأس Key/Value واحد. في تطبيق C++، قبل إجراء ضرب المصفوفات &lt;code>ggml_mul_mat&lt;/code>، من الضروري إجراء عملية بث (Broadcast) لتنسورات KV لتتناسب مع عدد Query.&lt;/p>
&lt;h3 id="44-دالة-التنشيط-swiglu">4.4 دالة التنشيط SwiGLU
&lt;/h3>&lt;p>في طبقة الشبكة المغذية للأمام (FFN)، يتم استخدام SwiGLU بدلاً من GELU.&lt;/p>
$$ \text{SwiGLU}(x) = \text{Swish}(x W_{\text{gate}}) \otimes (x W_{\text{up}}) $$
$$ \text{Swish}(z) = z \cdot \sigma(z) = z \cdot \frac{1}{1 + e^{-z}} $$
&lt;p>يتم تمثيله في الرسم البياني الحسابي بدمج عاملي &lt;code>ggml_silu&lt;/code> و &lt;code>ggml_mul&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="5-بناء-الرسم-البياني-الحسابي-وإدارة-الذاكرة-باستخدام-ggml">5. بناء الرسم البياني الحسابي وإدارة الذاكرة باستخدام ggml
&lt;/h2>&lt;p>تعتمد ggml نهج &amp;ldquo;التحديد والتنفيذ (Define-and-Run)&amp;quot;، حيث تقوم ببناء رسم بياني حسابي ثابت للاستدلال ثم تقييمه (evaluate) لاحقاً.&lt;/p>
&lt;h3 id="51-ggml_context-ومخصص-الساحة-arena-allocator">5.1 ggml_context ومخصص الساحة (Arena Allocator)
&lt;/h3>&lt;p>الميزة الأكثر تميزاً في ggml هي &amp;ldquo;تخصيص الساحة&amp;rdquo;، الذي لا ينفذ أي تخصيص ديناميكي للذاكرة (&lt;code>malloc&lt;/code> أو &lt;code>new&lt;/code>) داخل حلقة الاستدلال.
يتم تخصيص منطقة ذاكرة متصلة ضخمة (الساحة) عند التهيئة، وفي كل مرة يتم فيها استدعاء &lt;code>ggml_new_tensor&lt;/code> وغيره، يزداد مؤشر هذه المنطقة. عند اكتمال خطوة استدلال واحدة، يتم فقط إعادة تعيين مؤشر التخصيص إلى الموضع الأولي، وبذلك يكتمل تخصيص الذاكرة لخطوة الاستدلال التالية على الفور.&lt;/p>
&lt;h3 id="52-مثال-عملي-لبناء-الرسم-البياني">5.2 مثال عملي لبناء الرسم البياني
&lt;/h3>&lt;p>في كل خطوة استدلال، يتم تجميع الرسم البياني الحسابي التالي في الذاكرة.&lt;/p>
&lt;div class="mermaid">graph TD
A["معرف رمز الإدخال (Tokens Input ID)"] --> B["البحث عن التضمين (Embed Lookup)"]
B --> C["ggml_rms_norm"]
C --> D["إسقاطات Q / K / V"]
D --> E["ggml_rope Positional"]
E --> F["حفظ في KV Cache"]
E --> G["تحميل من KV Cache"]
G --> H["الانتباه الذاتي (Self Attention)"]
H --> I["المقياس و Softmax"]
I --> J["مخرجات الانتباه (Attention Output)"]
J --> K["الإسقاط الخارجي (Out Projection)"]
K --> L["إضافة المتبقي (Add Residual)"]&lt;/div>
&lt;hr>
&lt;h2 id="6-التكميم-quantization-وتحسين-windows--simd">6. التكميم (Quantization) وتحسين Windows / SIMD
&lt;/h2>&lt;p>يتطلب التعامل مع TinyLLaMA (1.1B) بصيغة FP16 حوالي 2.2 جيجابايت من الذاكرة، ولكن باستخدام تكميم 4-بت (مثل Q4_K) يمكن ضغطه بشكل كبير إلى حوالي 600 ميجابايت.&lt;/p>
&lt;h3 id="61-بنية-التكميم-الكتلي-block-quantization">6.1 بنية التكميم الكتلي (Block Quantization)
&lt;/h3>&lt;p>لا تقوم ggml بتكميم التنسور بأكمله بشكل موحد، بل يتم ذلك على أساس &amp;ldquo;الكتلة&amp;rdquo;.
في تنسيق &lt;code>Q4_0&lt;/code>، يتم تجميع 32 قيمة FP16 في كتلة واحدة.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>عامل المقياس (Scale Factor)&lt;/strong>: قيمة واحدة FP16 (2 بايت)&lt;/li>
&lt;li>&lt;strong>البيانات المكممة&lt;/strong>: 32 قيمة 4-بت (16 بايت)
هذا يقلل من تأثير القيم المتطرفة المحلية.&lt;/li>
&lt;/ul>
&lt;h3 id="62-تسريع-الضرب-النقطي-باستخدام-avx2">6.2 تسريع الضرب النقطي باستخدام AVX2
&lt;/h3>&lt;p>عند البناء لأحدث وحدات المعالجة المركزية x86 في بيئة Windows، مع الاستفادة من علامات المترجم مثل &lt;code>/arch:AVX2&lt;/code>، تتم معالجة SIMD عبر التدفق التالي:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>التحميل (Load)&lt;/strong>: تحميل بيانات التكميم 4-بت من الذاكرة إلى سجلات AVX بحجم 256 بت.&lt;/li>
&lt;li>&lt;strong>التوسيع وفك الحزم (Unpack)&lt;/strong>: استخدام أقنعة البت (Bitmasks) وعمليات الإزاحة لتوسيع قيم 4-بت إلى Int8 أو Int16.&lt;/li>
&lt;li>&lt;strong>إلغاء التكميم (Dequantize)&lt;/strong>: الضرب في عامل المقياس للتحويل إلى فاصلة عائمة.&lt;/li>
&lt;li>&lt;strong>عمليات FMA&lt;/strong>: تنفيذ عمليات الضرب والجمع بالتوازي على قيم التنشيط باستخدام &lt;code>_mm256_fmadd_ps&lt;/code> (Fused Multiply-Add).&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="7-تفاصيل-تنفيذ-ذاكرة-التخزين-المؤقت-kv-kv-cache">7. تفاصيل تنفيذ ذاكرة التخزين المؤقت KV (KV Cache)
&lt;/h2>&lt;p>في التوليد التلقائي الانحداري، تعد &amp;ldquo;ذاكرة التخزين المؤقت KV&amp;rdquo; لتجاوز حسابات Key و Value للرموز السابقة ميزة أساسية.&lt;/p>
&lt;p>فيما يلي النقاط الرئيسية عند تنفيذ ذلك بـ C++:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>التخصيص المسبق للتنسور&lt;/strong>: تهيئة تنسور ضخم لذاكرة التخزين المؤقت KV بحجم الحد الأقصى لطول السياق (مثال: 2048 رمزاً) (يُفضل FP16).&lt;/li>
&lt;li>&lt;strong>نسخ الإزاحة (Offset Copy)&lt;/strong>: عند الحساب للموضع الرمزي $N$، يتم تخزين متجهات K و V الناتجة في تلك الخطوة في الصف $N$ من تنسور التخزين المؤقت KV باستخدام دوال مثل &lt;code>ggml_cpy&lt;/code>.&lt;/li>
&lt;li>&lt;strong>إنشاء مشهد (View) أثناء الانتباه&lt;/strong>: عند حساب الانتباه، يتم تمرير &amp;ldquo;مشهد&amp;rdquo; يشير فقط إلى أجزاء الرموز من 0 إلى $N$ لضرب المصفوفات.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-bpe-tokenizer-وفك-التشفير-decoding">8. BPE Tokenizer وفك التشفير (Decoding)
&lt;/h2>&lt;p>تتم معالجة السلسلة المدخلة كتسلسل بايتات UTF-8 وتتم مطابقتها مع مفردات محددة مسبقاً. في C++، لتسريع البحث في المفردات، يتم تنفيذ خوارزميات مثل &lt;strong>شجرة البادئة (Trie Tree)&lt;/strong> أو قوائم الانتظار ذات الأولوية.&lt;/p>
&lt;p>من سجلات Logits الناتجة عن LM Head، يتم قياس الاحتمالات باستخدام معلمة درجة الحرارة (Temperature)، ويتم تضييق المرشحين باستخدام استخراج Top-K أو أساليب Top-P (Nucleus Sampling)، ويتم تحديد الرمز التالي النهائي باستخدام أرقام عشوائية.&lt;/p>
&lt;hr>
&lt;h2 id="9-إعداد-مشروع-c-بيئة-windows--powershell">9. إعداد مشروع C++ (بيئة Windows / PowerShell)
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.14&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">TinyLLaMACpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">17&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># إعدادات التحسين وعلامات AVX2 لـ Windows (MSVC)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MSVC&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">add_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">/O2&lt;/span> &lt;span class="s">/arch:AVX2&lt;/span> &lt;span class="s">/fp:fast&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">add_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">/STACK:8388608&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">else&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">add_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">-O3&lt;/span> &lt;span class="s">-march=native&lt;/span> &lt;span class="s">-ffast-math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ggml&lt;/span> &lt;span class="s">OBJECT&lt;/span> &lt;span class="s">ggml/ggml.c&lt;/span> &lt;span class="s">ggml/ggml-alloc.c&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_compile_definitions&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ggml&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">GGML_USE_AVX2&lt;/span> &lt;span class="s">GGML_USE_F16C&lt;/span> &lt;span class="s">GGML_USE_FMA&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">main&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">main&lt;/span> &lt;span class="s">ggml&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>مثال لأمر البناء في PowerShell:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">mkdir&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd &lt;/span>&lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cmake&lt;/span> &lt;span class="p">..&lt;/span> &lt;span class="n">-G&lt;/span> &lt;span class="s2">&amp;#34;Visual Studio 17 2022&amp;#34;&lt;/span> &lt;span class="n">-A&lt;/span> &lt;span class="n">x64&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cmake&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-build&lt;/span> &lt;span class="p">.&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-config&lt;/span> &lt;span class="n">Release&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="10-الخلاصة">10. الخلاصة
&lt;/h2>&lt;p>يعد تنفيذ محرك استدلال لنموذج ذكاء اصطناعي صغير مثل TinyLLaMA من الصفر باستخدام C++ و ggml فرصة رائعة لكشف الصندوق الأسود للتعلم العميق وتعلم جمال التحكم في الأجهزة منخفضة المستوى. باستخدام التحميل بنسخ صفري المعتمد على تخطيط الذاكرة، وتحسينات SIMD، وبناء ذاكرة التخزين المؤقت KV، دعونا نفتح آفاقاً جديدة لمستقبل الذكاء الاصطناعي الطرفي (Edge AI) بينما نستمتع بجوهر برمجة الأنظمة.&lt;/p></description></item><item><title>【مقدمة في تنفيذ RAG】كيفية جعل الذكاء الاصطناعي المحلي يقرأ مستنداتك</title><link>http://kenji.blog/ar/p/rag-local-ai-implementation-guide/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/rag-local-ai-implementation-guide/</guid><description>&lt;img src="http://kenji.blog/p/rag-local-ai-implementation-guide/img/eyecatch.jpg" alt="Featured image of post 【مقدمة في تنفيذ RAG】كيفية جعل الذكاء الاصطناعي المحلي يقرأ مستنداتك" />&lt;h1 id="مقدمة">مقدمة
&lt;/h1>&lt;p>في السنوات الأخيرة، كان التطور في نماذج اللغة الكبيرة (LLM) ملحوظًا، حيث تغلغل العديد من أنظمة الذكاء الاصطناعي مثل ChatGPT و Claude في حياتنا وأعمالنا. ومع ذلك، هناك نقطة ضعف واضحة في نماذج LLM العامة. وهي أنها لا تعرف سوى &amp;ldquo;المعلومات العامة المتاحة وقت التدريب&amp;rdquo;. بالطبع، لا يمكنها الإجابة على الأسئلة المتعلقة بـ &amp;ldquo;المستندات الخاصة&amp;rdquo; مثل لوائح الشركة، والمذكرات الشخصية، ومواد المشاريع غير المنشورة. إذا حاولت إجبارها على الإجابة، فهناك خطر كبير من أنها ستولد أكاذيب تبدو معقولة ولكنها بعيدة عن الحقيقة (الهلوسة - Hallucination).&lt;/p>
&lt;p>لذلك، فإن البنية المعمارية التقنية التي تنتشر حاليًا بشكل هائل في جميع أنحاء العالم هي &lt;strong>RAG (Retrieval-Augmented Generation: التوليد المعزز بالاسترجاع)&lt;/strong>. باستخدام RAG، يصبح من الممكن تزويد LLM بالمعرفة الخاصة ديناميكيًا من قاعدة بيانات خارجية، وجعلها تولد إجابات دقيقة وموثوقة بناءً على ذلك.&lt;/p>
&lt;p>علاوة على ذلك، عند التعامل مع مجال الشركات أو المعلومات الشخصية السرية، غالبًا ما يكون إرسال البيانات إلى واجهات برمجة التطبيقات (APIs) المستندة إلى السحابة مثل OpenAI غير مسموح به بموجب سياسة الأمان. ما هو مطلوب هنا هو بناء &amp;ldquo;RAG محلي&amp;rdquo; مدمج مع &lt;strong>الذكاء الاصطناعي المحلي&lt;/strong> (LLM يعمل بالكامل على جهاز الكمبيوتر الخاص بك أو الخادم المحلي - On-Premise).&lt;/p>
&lt;p>في هذه المقالة، سنشرح بالتفصيل كل شيء بدءًا من النظريات الأساسية لـ RAG، وطرق التنفيذ المحددة لـ RAG المحلي باستخدام Python، والخلفية الرياضية (آلية البحث عن المتجهات)، إلى التقنيات المتقدمة لتشغيل النظام في بيئة الإنتاج.&lt;/p>
&lt;hr>
&lt;h1 id="1-البنية-المعمارية-العامة-لـ-rag">1. البنية المعمارية العامة لـ RAG
&lt;/h1>&lt;p>RAG ليس نموذج ذكاء اصطناعي واحد، بل هو بنية نظام تتعاون فيها مكونات متعددة. يتكون بشكل رئيسي من مرحلتين: &amp;ldquo;مرحلة الاستيعاب (إدخال البيانات)&amp;rdquo; و &amp;ldquo;مرحلة الاسترجاع والتوليد (البحث والتوليد)&amp;rdquo;.&lt;/p>
&lt;p>يوضح مخطط Mermaid التالي الصورة العامة لنظام RAG.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "مرحلة الاستيعاب (التحضير المسبق)"
Doc["مستندات خاصة (PDF, TXT, إلخ.)"] --> Loader["محمل المستندات"]
Loader --> Splitter["تقسيم النص (Chunking)"]
Splitter --> EmbedModel1["نموذج التضمين (Embedding)"]
EmbedModel1 --> VectorDB["قاعدة بيانات المتجهات"]
end
subgraph "مرحلة الاستدلال (عند استعلام المستخدم)"
User["سؤال من المستخدم (استعلام)"] --> EmbedModel2["نموذج التضمين (Embedding)"]
EmbedModel2 --> QueryVector["متجه الاستعلام"]
QueryVector --> Search["بحث التشابه (بحث المتجهات)"]
VectorDB --> Search
Search --> Context["استخراج القطع ذات الصلة (السياق)"]
User --> PromptBuilder["بناء الموجه (Prompt)"]
Context --> PromptBuilder
PromptBuilder --> LocalLLM["LLM محلي"]
LocalLLM --> Answer["توليد الإجابة النهائية"]
end&lt;/div>
&lt;h2 id="مرحلة-الاستيعاب-التحضير-المسبق">مرحلة الاستيعاب (التحضير المسبق)
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>تحميل المستندات&lt;/strong>: تحميل البيانات غير المهيكلة مثل ملفات PDF، Word، والملفات النصية.&lt;/li>
&lt;li>&lt;strong>التقسيم (Chunking)&lt;/strong>: تقسيم النصوص الطويلة إلى كتل ذات معنى (Chunks) لتتناسب مع قيود الإدخال في LLM (نافذة السياق) ولتحسين دقة البحث.&lt;/li>
&lt;li>&lt;strong>التضمين (Embedding / تحويل إلى متجهات)&lt;/strong>: إدخال الكتل المقسمة إلى نموذج التضمين (Embedding Model) وتحويلها إلى مصفوفات من الأرقام (متجهات) ذات مئات إلى آلاف الأبعاد.&lt;/li>
&lt;li>&lt;strong>الحفظ في قاعدة البيانات&lt;/strong>: حفظ المتجهات المحولة مرتبطة بالبيانات النصية الأصلية في قاعدة بيانات المتجهات (Vector DB).&lt;/li>
&lt;/ol>
&lt;h2 id="مرحلة-الاستدلال-أثناء-التشغيل">مرحلة الاستدلال (أثناء التشغيل)
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>تحويل الاستعلام إلى متجهات&lt;/strong>: تحويل سؤال المستخدم إلى متجه باستخدام نفس نموذج التضمين المستخدم في التحضير المسبق.&lt;/li>
&lt;li>&lt;strong>بحث التشابه&lt;/strong>: حساب التشابه بين متجه الاستعلام ومتجهات المستندات في قاعدة البيانات، واسترداد أعلى الكتل النصية الأقرب دلاليًا (ذات الصلة العالية).&lt;/li>
&lt;li>&lt;strong>بناء الموجه (Prompt)&lt;/strong>: دمج النصوص المستردة ذات الصلة كـ &amp;ldquo;سياق (معرفة خلفية)&amp;rdquo; مع سؤال المستخدم لإنشاء موجه الإدخال لـ LLM.&lt;/li>
&lt;li>&lt;strong>توليد الإجابة&lt;/strong>: يتلقى LLM الموجه الموسع ويولد إجابة بناءً على معلومات السياق المرفقة.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="2-الفهم-العميق-للبحث-في-المتجهات-والتضمين-embeddings">2. الفهم العميق للبحث في المتجهات والتضمين (Embeddings)
&lt;/h1>&lt;p>جوهر RAG هو &amp;ldquo;البحث في المتجهات (البحث الدلالي)&amp;rdquo;. بينما يعتمد بحث الكلمات الرئيسية التقليدي (مثل BM25) على المطابقة التامة للكلمات وتكرارها، يعتمد البحث في المتجهات على &amp;ldquo;التشابه الدلالي&amp;rdquo;. على سبيل المثال، حتى الكلمات المختلفة مثل &amp;ldquo;كلب&amp;rdquo; و &amp;ldquo;جرو&amp;rdquo;، أو &amp;ldquo;حاسوب&amp;rdquo; و &amp;ldquo;كمبيوتر&amp;rdquo;، ستظهر في نتائج البحث إذا كانت معانيها متقاربة.&lt;/p>
&lt;h2 id="ما-هو-نموذج-التضمين-embedding-model">ما هو نموذج التضمين (Embedding Model)؟
&lt;/h2>&lt;p>نموذج التضمين هو شبكة عصبية تأخذ النصوص باللغة الطبيعية كإدخال وتخرج متجهًا كثيفًا ثابت الطول (Dense Vector). النماذج الشائعة (مثل &lt;code>text-embedding-3-small&lt;/code> أو النماذج مفتوحة المصدر مثل &lt;code>multilingual-e5-large&lt;/code>) تقوم بتعيين النص إلى متجه حقيقي بأبعاد 384 أو 1024.&lt;/p>
&lt;p>في هذا الفضاء متعدد الأبعاد (الفضاء الكامن - Latent Space)، يتم تدريب النموذج بحيث تكون المسافة في فضاء الإحداثيات أقرب كلما كانت الجمل متشابهة في المعنى.&lt;/p>
&lt;h2 id="الخلفية-الرياضية-لحساب-التشابه-تشابه-جيب-التمام-cosine-similarity">الخلفية الرياضية لحساب التشابه: تشابه جيب التمام (Cosine Similarity)
&lt;/h2>&lt;p>عندما تبحث قاعدة بيانات المتجهات عن المستندات ذات الصلة، فإن مقياس المسافة الأكثر استخدامًا هو &lt;strong>تشابه جيب التمام (Cosine Similarity)&lt;/strong>. على عكس المسافة الإقليدية (المسافة المطلقة المكانية)، يركز تشابه جيب التمام على &amp;ldquo;الزاوية بين متجهين&amp;rdquo;. نظرًا لأنه أقل تأثرًا بطول الجملة (معيار المتجه)، فهو مناسب جدًا لحساب تشابه النصوص.&lt;/p>
&lt;p>يتم التعبير عن تشابه جيب التمام للمتجهين $\mathbf{A}$ و $\mathbf{B}$ رياضياً كالتالي:&lt;/p>
$$ \text{Cosine Similarity}(\mathbf{A}, \mathbf{B}) = \cos(\theta) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}} $$
&lt;ul>
&lt;li>$\mathbf{A} \cdot \mathbf{B}$ يمثل الجداء النقطي (Dot Product).&lt;/li>
&lt;li>$\|\mathbf{A}\|$ يمثل معيار L2 (الطول) للمتجه $\mathbf{A}$.&lt;/li>
&lt;li>$n$ هو عدد أبعاد المتجه.&lt;/li>
&lt;/ul>
&lt;p>يأخذ تشابه جيب التمام قيمًا من -1 إلى 1.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>قريب من 1&lt;/strong>: اتجاه كلا المتجهين هو نفسه تقريبًا (المعنى متشابه جدًا)&lt;/li>
&lt;li>&lt;strong>قريب من 0&lt;/strong>: المتجهان متعامدان (غير مرتبطين)&lt;/li>
&lt;li>&lt;strong>قريب من -1&lt;/strong>: المتجهان في اتجاهين متعاكسين (المعنى معاكس)&lt;/li>
&lt;/ul>
&lt;p>تستخدم قواعد بيانات المتجهات الحديثة (مثل Chroma، FAISS، Qdrant) خوارزمية بحث أقرب جار تقريبي (ANN) تسمى HNSW (Hierarchical Navigable Small World)، والتي تم تحسينها للبحث عن المستندات ذات تشابه جيب التمام العالي من بين ملايين البيانات المتجهة في أجزاء من الثانية.&lt;/p>
&lt;hr>
&lt;h1 id="3-حزمة-التقنيات-لبناء-rag-محلي">3. حزمة التقنيات لبناء RAG محلي
&lt;/h1>&lt;p>لبناء RAG محلي بالكامل لا يعتمد على السحابة، سنستفيد من نظام المصادر المفتوحة. نوصي بحزمة التقنيات التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>نموذج اللغة (LLM)&lt;/strong>
&lt;ul>
&lt;li>الأداة: &lt;code>Ollama&lt;/code> أو &lt;code>Llama.cpp&lt;/code>&lt;/li>
&lt;li>النماذج: نماذج مفتوحة خفيفة وعالية الأداء مثل &lt;code>Llama-3-8B-Instruct&lt;/code>، &lt;code>Gemma-2-9B-It&lt;/code>، &lt;code>Qwen2-7B-Instruct&lt;/code>. للمهام باللغة اليابانية، تعتبر النماذج المضبوطة لليابانية مثل &lt;code>Llama-3-ELYZA-JP-8B&lt;/code> مناسبة (يمكن استخدام نماذج تدعم اللغة العربية للمهام العربية).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>نموذج التضمين (Embedding)&lt;/strong>
&lt;ul>
&lt;li>النماذج: &lt;code>intfloat/multilingual-e5-large&lt;/code> أو &lt;code>BAAI/bge-m3&lt;/code>. لتشغيله محليًا، من الشائع تنزيله من Hugging Face وتشغيله باستخدام Sentence-Transformers.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>قاعدة بيانات المتجهات (Vector DB)&lt;/strong>
&lt;ul>
&lt;li>&lt;code>ChromaDB&lt;/code>: مبني على Python وسهل الإعداد للغاية. مثالي للتطوير المحلي.&lt;/li>
&lt;li>&lt;code>FAISS&lt;/code>: مكتبة بحث متجهات سريعة طورتها Meta.&lt;/li>
&lt;li>&lt;code>Qdrant&lt;/code> / &lt;code>Milvus&lt;/code>: مخصص للبيئات الأكبر وبيئات الإنتاج.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>إطار عمل التنسيق (Orchestration Framework)&lt;/strong>
&lt;ul>
&lt;li>&lt;code>LangChain&lt;/code>: المعيار الفعلي لربط المكونات (Chain).&lt;/li>
&lt;li>&lt;code>LlamaIndex&lt;/code>: إطار عمل للاتصال بالبيانات متخصص بشكل خاص في RAG.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>في هذه المرة، سنقوم بالتنفيذ باستخدام المزيج الأسهل في التقديم: &lt;strong>LangChain + ChromaDB + Ollama + HuggingFaceEmbeddings&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="4-دورة-تعليمية-للتنفيذ-بناء-rag-محلي-كامل-باستخدام-python">4. دورة تعليمية للتنفيذ: بناء RAG محلي كامل باستخدام Python
&lt;/h1>&lt;p>من هنا، سنقوم ببناء RAG محلي من خلال كتابة كود Python فعليًا. مسبقًا، يرجى تثبيت Ollama على جهاز الكمبيوتر الخاص بك وتشغيله في الخلفية. أيضًا، قم بسحب (Pull) النموذج على Ollama (مثال: &lt;code>ollama run llama3&lt;/code>).&lt;/p>
&lt;h2 id="الخطوة-1-تثبيت-المكتبات-المطلوبة">الخطوة 1: تثبيت المكتبات المطلوبة
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install langchain langchain-community langchain-huggingface
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install chromadb sentence-transformers pypdf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="الخطوة-2-الكود-البرمجي-الكامل-للتنفيذ">الخطوة 2: الكود البرمجي الكامل للتنفيذ
&lt;/h2>&lt;p>فيما يلي برنامج نصي كامل بلغة Python لقراءة ملف PDF، وتحويله إلى متجهات، وجعل نموذج LLM المحلي يجيب على الأسئلة.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;span class="lnt">92
&lt;/span>&lt;span class="lnt">93
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.document_loaders&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PyPDFLoader&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_text_splitters&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RecursiveCharacterTextSplitter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_huggingface&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">HuggingFaceEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.vectorstores&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Chroma&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.llms&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.prompts&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RetrievalQA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. تحميل المستندات&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;جاري تحميل المستندات...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># حدد مسار ملف PDF الذي تريد قراءته&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">file_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;sample_company_policy.pdf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">loader&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PyPDFLoader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file_path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">documents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">loader&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. تقسيم النص (Text Splitting)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># التقسيم إلى أحجام مناسبة دون تدمير معنى الجمل&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text_splitter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RecursiveCharacterTextSplitter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunk_size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># أقصى عدد من الأحرف لكل كتلة&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunk_overlap&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># عدد الأحرف المتداخلة بين الكتل (لمنع انقطاع السياق)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">separators&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;。&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;、&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text_splitter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;تم التقسيم إلى &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunks&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> كتلة.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. تهيئة نموذج التضمين (Local HuggingFace Model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># استخدام نموذج متعدد اللغات&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;جاري تحميل نموذج التضمين...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">HuggingFaceEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;intfloat/multilingual-e5-large&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;device&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;cpu&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span> &lt;span class="c1"># &amp;#39;cuda&amp;#39; أو &amp;#39;mps&amp;#39; إذا كان لديك وحدة معالجة رسومات (GPU)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. بناء قاعدة بيانات المتجهات (Chroma)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;جاري بناء قاعدة بيانات المتجهات...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./chroma_db&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Chroma&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_documents&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">documents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">chunks&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">persist_directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># إنشاء المسترد (Retriever). إعداد لجلب أفضل 3 مستندات ذات صلة&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_retriever&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">search_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;k&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 5. تهيئة LLM المحلي (Ollama)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;جاري الاتصال بـ LLM المحلي...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># تأكد من الحصول على النموذج مسبقًا باستخدام شيء مثل &amp;#39;ollama pull llama3&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;llama3&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 6. تعريف قالب الموجه (Prompt Template)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt_template&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;أنت مساعد ممتاز على دراية بلوائح الشركة والمعلومات الداخلية.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">يرجى الإجابة على سؤال المستخدم بالتفصيل باستخدام السياق (معلومات الخلفية) التالي فقط.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">إذا لم تتمكن من العثور على الإجابة في السياق، فلا تخمن من نفسك وأجب بصدق &amp;#34;لا يمكن المعرفة من المعلومات المقدمة&amp;#34;.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">【السياق】
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{context}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">【السؤال】
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{question}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">【الإجابة】:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">PROMPT&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">prompt_template&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">input_variables&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;context&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;question&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 7. بناء سلسلة RAG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qa_chain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RetrievalQA&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_chain_type&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chain_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;stuff&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retriever&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">retriever&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">return_source_documents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># إعداد لإرجاع مصدر المعلومات&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chain_type_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;prompt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">PROMPT&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 8. تنفيذ السؤال&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;يرجى إخباري عن شروط دفع نفقات النقل المتعلقة بالعمل عن بعد.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">السؤال: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">qa_chain&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【الإجابة】&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;result&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【مصادر المعلومات المرجعية】&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">doc&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;source_documents&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- صفحة &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;غير معروف&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">page_content&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">main&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="شرح-نقاط-الكود">شرح نقاط الكود
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>RecursiveCharacterTextSplitter&lt;/strong>:
وهو المقسم الموصى به بشدة عند تقسيم اللغة الطبيعية. يحاول التقسيم بترتيب الفقرات (&lt;code>\n\n&lt;/code>)، الأسطر (&lt;code>\n&lt;/code>)، وعلامات الترقيم (&lt;code>。&lt;/code>)، بحيث يتناسب مع &lt;code>chunk_size&lt;/code> المحدد مع الحفاظ على وحدة المعنى قدر الإمكان. عن طريق تعيين &lt;code>chunk_overlap&lt;/code>، فإنه يمنع فقدان المعلومات بسبب انقطاع الحدود السياقية.&lt;/li>
&lt;li>&lt;strong>HuggingFaceEmbeddings&lt;/strong>:
&lt;code>intfloat/multilingual-e5-large&lt;/code> هو نموذج تضمين مفتوح المصدر قوي جدًا يدعم لغات متعددة. يتيح لك تحويل النصوص إلى متجهات على الذاكرة المحلية دون اتصال بالإنترنت، دون استخدام واجهات برمجة التطبيقات السحابية (مثل &lt;code>text-embedding-ada-002&lt;/code> الخاص بـ OpenAI).&lt;/li>
&lt;li>&lt;strong>ChromaDB&lt;/strong>:
نظرًا لأنه يعمل في الذاكرة (In-memory) أو في التخزين المحلي (مبني على SQLite)، فلا حاجة لإعداد خادم قاعدة بيانات معقد. بتحديد &lt;code>persist_directory&lt;/code>، يمكنك تخطي عملية التحويل إلى متجهات عند إعادة التشغيل وقراءة قاعدة البيانات من القرص.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="5-تقنيات-rag-المتقدمة-advanced-rag-techniques">5. تقنيات RAG المتقدمة (Advanced RAG Techniques)
&lt;/h1>&lt;p>النظام الأساسي (Naive RAG) الذي بنيناه في الدورة التعليمية أعلاه يعمل، ولكن إذا كانت هناك حاجة إلى دقة إجابة عالية في بيئة الإنتاج، فمن الضروري تقديم تقنيات متقدمة مثل ما يلي.&lt;/p>
&lt;h2 id="51-البحث-الهجين-hybrid-search">5.1 البحث الهجين (Hybrid Search)
&lt;/h2>&lt;p>البحث في المتجهات ممتاز في التقاط &amp;ldquo;المعنى&amp;rdquo;، ولكنه قد يعاني مع عمليات البحث الدقيقة بالكلمات الرئيسية مثل &amp;ldquo;أسماء الأعلام الخاصة&amp;rdquo;، &amp;ldquo;أرقام طرازات المنتجات&amp;rdquo;، أو &amp;ldquo;معرفات الموظفين&amp;rdquo;.
لذلك، من خلال إجراء &lt;strong>البحث الدلالي&lt;/strong> عبر بحث المتجهات والبحث بالكلمات الرئيسية باستخدام خوارزميات مثل BM25 بشكل متوازٍ، ثم تسجيل ودمج نتائج كليهما (باستخدام طرق مثل دمج الترتيب المتبادل؛ Reciprocal Rank Fusion; RRF)، يمكن تقليل حالات الإخفاق في البحث بشكل كبير.&lt;/p>
&lt;h2 id="52-إعادة-الترتيب-re-ranking">5.2 إعادة الترتيب (Re-ranking)
&lt;/h2>&lt;p>البحث في المتجهات سريع، ولكنه لا يقيّم بالضرورة الملاءمة السياقية الدقيقة للسياق. خط أنابيب المعالجة (Pipeline) الشائع لتحسين دقة البحث هو كالتالي:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>البحث الأولي (First-stage Retrieval)&lt;/strong>: استرجاع حوالي 20 إلى 30 كتلة نصية ذات صلة بشكل واسع وسطحي من قاعدة بيانات المتجهات.&lt;/li>
&lt;li>&lt;strong>إعادة التقييم (Re-ranking)&lt;/strong>: استخدام نموذج تعلم آلي آخر أثقل يُعرف باسم Cross-Encoder (مثل &lt;code>bge-reranker&lt;/code>)، وإدخال زوج من استعلام المستخدم والكتل المستردة لإعادة حساب درجة الملاءمة الدلالية.&lt;/li>
&lt;li>&lt;strong>الفرز&lt;/strong>: تمرير أفضل 3 إلى 5 كتل ذات أعلى الدرجات كـسياق نهائي إلى موجه LLM.&lt;/li>
&lt;/ol>
&lt;p>من خلال هذه الطريقة، يمكن منع تمرير معلومات الضوضاء غير ذات الصلة إلى LLM، مما يزيد بشكل كبير من دقة الإجابة (Precision).&lt;/p>
&lt;div class="mermaid">graph LR
Query["استعلام"] --> VSearch["بحث المتجهات (أفضل 20)"]
VSearch --> Reranker["نموذج إعادة الترتيب (Cross-Encoder)"]
Query --> Reranker
Reranker --> TopK["أفضل 3 بدقة عالية"]
TopK --> LLM["توليد LLM"]&lt;/div>
&lt;h2 id="53-التقسيم-الدلالي-semantic-chunking-والبحث-في-المستند-الأصلي">5.3 التقسيم الدلالي (Semantic Chunking) والبحث في المستند الأصلي
&lt;/h2>&lt;p>بدلاً من تقسيم النص ميكانيكيًا بعدد ثابت من الأحرف، توجد طريقة تسمى &amp;ldquo;التقسيم الدلالي&amp;rdquo; (Semantic Chunking) تكتشف تغيرات المعنى في الجملة باستخدام الذكاء الاصطناعي لتقسيمها.
أيضًا، في طريقة تُعرف باسم &amp;ldquo;البحث في المستند الأصل&amp;rdquo; (Parent Document Retriever)، يتم تحويل النص إلى متجهات بوحدات صغيرة جدًا (مثل الجمل) لأغراض البحث لتحقيق بحث عالي الدقة، وعند تمريره إلى LLM، يتم تمرير &amp;ldquo;الفقرة الكبيرة الأصلية (المستند الأصل)&amp;rdquo; التي تحتوي على تلك الجملة، مما يوفر سياقًا كافيًا لـ LLM.&lt;/p>
&lt;hr>
&lt;h1 id="6-تحديات-وحلول-عند-تشغيل-rag-محلي">6. تحديات وحلول عند تشغيل RAG محلي
&lt;/h1>&lt;p>عند بناء وتشغيل RAG في بيئة محلية، توجد عقبات محددة.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>نفاد ذاكرة الفيديو (VRAM)&lt;/strong>:
لتشغيل LLM محلي بسرعة عملية (عشرات الرموز في الثانية)، يجب تحميل النموذج في ذاكرة الفيديو (VRAM) الخاصة بوحدة المعالجة الرسومية (GPU). لتشغيل نموذج من فئة 8B بصيغة fp16 (نقطة عائمة 16 بت)، يتطلب الأمر حوالي 16 غيغابايت من VRAM، ولكن باستخدام تقنيات &lt;strong>التكميم (Quantization)&lt;/strong> (تقنيات الضغط إلى 4 بت أو 8 بت مثل صيغ GGUF و AWQ)، من الممكن تشغيلها بسرعة كافية حتى على 8 غيغابايت من VRAM (مثل أجهزة الكمبيوتر المخصصة للألعاب). يدعم كل من Llama.cpp و Ollama تنسيقات التكميم هذه افتراضيًا.&lt;/li>
&lt;li>&lt;strong>حدود نافذة السياق&lt;/strong>:
إذا كان حجم السياق المسترد كبيرًا جدًا، فقد يتجاوز الحد الأقصى لإدخال LLM (حد الرموز)، أو قد ينسى النموذج الجزء الأوسط من المعلومات (ظاهرة الضياع في المنتصف - Lost in the middle). من الضروري تعديل عدد الكتل المستخرجة والاختيار الدقيق من خلال تقنية إعادة الترتيب المذكورة أعلاه.&lt;/li>
&lt;li>&lt;strong>إدارة حداثة البيانات&lt;/strong>:
عند تحديث المستندات المصدرية، يجب أيضًا تحديث المتجهات أو حذفها (عمليات CRUD) للمستندات المقابلة في قاعدة بيانات المتجهات. نظرًا لأن ChromaDB يدعم التحديثات بناءً على معرف المستند (Document ID)، فمن العملي إدارة قيم التجزئة (Hash) للملفات وإعداد معالجة مجمعة (Batch Processing) لمزامنة التغييرات فقط.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="الخاتمة">الخاتمة
&lt;/h1>&lt;p>RAG (التوليد المعزز بالاسترجاع) هو نموذج قوي يطور الذكاء الاصطناعي من مساعد عام عادي إلى &amp;ldquo;خبيرك الشخصي&amp;rdquo; أو &amp;ldquo;خبير متخصص في الأعمال الداخلية&amp;rdquo;.&lt;/p>
&lt;p>حتى في المتطلبات شديدة السرية حيث لا يمكن استخدام الخدمات السحابية، وجدنا أنه من السهل نسبيًا بناء بيئة &amp;ldquo;RAG محلي&amp;rdquo; كاملة من خلال الجمع بين أنظمة المصادر المفتوحة مثل Ollama، LangChain، و ChromaDB.&lt;/p>
&lt;p>بناءً على الفهم الرياضي للفضاء المتجه، والأساليب المتقدمة مثل تقسيم النصوص وإعادة الترتيب الموضحة في هذه المقالة، يرجى محاولة تطوير نظام ذكاء اصطناعي خاص بك باستخدام بياناتك الخاصة. إن سرعة تطور الذكاء الاصطناعي المحلي مذهلة، والنظام الذي تبنيه اليوم يمكن ترقية أدائه في لحظة بمجرد استبداله بنموذج خفيف الوزن وأكثر ذكاءً قد يظهر غدًا.&lt;/p>
&lt;hr>
&lt;p>&lt;em>في هذه المدونة، سنستمر في نشر مقالات متعمقة حول تكنولوجيا الذكاء الاصطناعي و RAG. إذا كان لديك أي أسئلة أو ملاحظات، يرجى تركها في قسم التعليقات.&lt;/em>&lt;/p></description></item><item><title>مقارنة شاملة لواجهات برمجة التطبيقات (API) لـ ChatGPT و Gemini و Claude! أيهم يجب أن تختار؟</title><link>http://kenji.blog/ar/p/chatgpt-gemini-claude-api-comparison/</link><pubDate>Fri, 11 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/chatgpt-gemini-claude-api-comparison/</guid><description>&lt;img src="http://kenji.blog/p/chatgpt-gemini-claude-api-comparison/img/eyecatch.jpg" alt="Featured image of post مقارنة شاملة لواجهات برمجة التطبيقات (API) لـ ChatGPT و Gemini و Claude! أيهم يجب أن تختار؟" />&lt;h1 id="مقارنة-شاملة-لواجهات-برمجة-التطبيقات-api-لـ-chatgpt-و-gemini-و-claude-أيهم-يجب-أن-تختار">مقارنة شاملة لواجهات برمجة التطبيقات (API) لـ ChatGPT و Gemini و Claude! أيهم يجب أن تختار؟
&lt;/h1>&lt;p>تطور تكنولوجيا الذكاء الاصطناعي مذهل، وخاصة في مجال النماذج اللغوية الكبيرة (LLM: Large Language Model)، حيث تدور معركة شرسة ثلاثية الأبعاد على الهيمنة بين ChatGPT (سلسلة GPT) من OpenAI، و Gemini من Google، و Claude من Anthropic. اعتبارًا من عام 2026، تطلق كل شركة نماذج وميزات API جديدة كل بضعة أشهر، بل كل بضعة أسابيع. بالنسبة للمطورين ومهندسي تكنولوجيا المعلومات في الشركات، أصبح السؤال &amp;ldquo;أي واجهة برمجة تطبيقات (API) يجب دمجها في منتجنا؟&amp;rdquo; قرارًا بالغ الأهمية يحدد نجاح المشروع.&lt;/p>
&lt;p>في هذه المقالة، لن نقتصر على سرد المواصفات لهذه الواجهات البرمجية من مزودي الذكاء الاصطناعي الثلاثة الكبار، بل سنقوم بمقارنتها وشرحها بالتفصيل من وجهة نظر المطورين. سيشمل ذلك تصميم البنية التحتية، والهياكل التفصيلية للأسعار، والتحليل الرياضي لوقت الاستجابة (زمن الانتقال)، وأمثلة تطبيقية عملية باستخدام Python و Node.js، وصولاً إلى أحدث تقنيات تحسين التكلفة مثل التخزين المؤقت للمطالبات (Prompt Caching).&lt;/p>
&lt;p>نهدف إلى أن يكون هذا دليلاً كاملاً لقرائنا لاختيار API الخاص بـ LLM الأنسب لحالات الاستخدام الخاصة بهم، وبناء تطبيقات ذكاء اصطناعي قابلة للتوسع وعالية الكفاءة من حيث التكلفة.&lt;/p>
&lt;hr>
&lt;h2 id="1-الفلسفة-ومبادئ-التصميم-لكل-llm-api">1. الفلسفة ومبادئ التصميم لكل LLM API
&lt;/h2>&lt;p>عند اختيار التقنية، من المهم جدًا فهم الفلسفة التي تبني عليها كل شركة نماذجها وواجهات برمجة التطبيقات الخاصة بها.&lt;/p>
&lt;h3 id="11-openai-chatgpt">1.1 OpenAI (ChatGPT)
&lt;/h3>&lt;p>تضع OpenAI &amp;ldquo;تحقيق الذكاء الاصطناعي العام (AGI)&amp;rdquo; كمهمة لها، وتقود دائمًا المعايير الصناعية (De facto standard). توفر الشركة نماذج متنوعة مصممة خصيصًا لحالات الاستخدام المختلفة، مثل GPT-4o و GPT-4o-mini، ونماذج o1 المتخصصة في الاستدلال. تمتلك النظام البيئي الأكثر نضجًا، مع توفر أكبر عدد من المكتبات والوثائق سواء الرسمية أو غير الرسمية.&lt;/p>
&lt;h3 id="12-google-gemini">1.2 Google (Gemini)
&lt;/h3>&lt;p>ترفع Google شعار &amp;ldquo;AI First&amp;rdquo; (الذكاء الاصطناعي أولاً)، وتتسلح بقابلية التوسع (Scalability) التي تستفيد إلى أقصى حد من بنيتها التحتية (شبكة TPU). تتميز نماذج Gemini 1.5 Pro/Flash بامتلاكها نافذة سياق ضخمة تصل إلى 2 مليون رمز (Token)، مما يسمح لها بمعالجة مستندات طويلة جدًا أو مقاطع فيديو وصوت تمتد لساعات في وقت واحد. كما يعد التكامل القوي مع Google Cloud (Vertex AI) ميزة جذابة للغاية للشركات.&lt;/p>
&lt;h3 id="13-anthropic-claude">1.3 Anthropic (Claude)
&lt;/h3>&lt;p>شركة Anthropic، التي أسسها أعضاء سابقون في OpenAI، تتبنى نهجًا فريدًا للسلامة يُعرف بـ &amp;ldquo;الذكاء الاصطناعي الدستوري&amp;rdquo; (Constitutional AI). تحظى نماذج Claude 3.5 Sonnet و Opus بدعم حماسي من العديد من المطورين بفضل قدراتها العالية في الاستدلال، وتوليد الكود، وقبل كل شيء &amp;ldquo;الحوار الطبيعي الشبيه بالبشر&amp;rdquo; و&amp;quot;قلة الهلوسة&amp;quot; (Hallucination).&lt;/p>
&lt;hr>
&lt;h2 id="2-مقارنة-تفصيلية-لمواصفات-عائلات-النماذج">2. مقارنة تفصيلية لمواصفات عائلات النماذج
&lt;/h2>&lt;p>فيما يلي مقارنة لمواصفات النماذج الرئيسية اعتبارًا من عام 2026.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>المزود&lt;/th>
&lt;th>النموذج الرئيسي&lt;/th>
&lt;th>أقصى طول للسياق&lt;/th>
&lt;th>نقاط القوة الرئيسية&lt;/th>
&lt;th>حالات الاستخدام الموصى بها&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>OpenAI&lt;/strong>&lt;/td>
&lt;td>GPT-4o&lt;/td>
&lt;td>128K&lt;/td>
&lt;td>السرعة، التعرف البصري، دعم الصوت&lt;/td>
&lt;td>التطبيقات التفاعلية، المهام العامة&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>OpenAI&lt;/strong>&lt;/td>
&lt;td>o1-preview&lt;/td>
&lt;td>128K&lt;/td>
&lt;td>الاستدلال المنطقي المتقدم، الرياضيات، البرمجة&lt;/td>
&lt;td>توليد الخوارزميات المعقدة، أغراض البحث&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Google&lt;/strong>&lt;/td>
&lt;td>Gemini 1.5 Pro&lt;/td>
&lt;td>2,000K&lt;/td>
&lt;td>معالجة النصوص الطويلة جدًا، متعدد الوسائط (فيديو/صوت)&lt;/td>
&lt;td>تحليل قواعد البيانات البرمجية الضخمة، تلخيص الفيديو&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Google&lt;/strong>&lt;/td>
&lt;td>Gemini 1.5 Flash&lt;/td>
&lt;td>2,000K&lt;/td>
&lt;td>زمن استجابة منخفض، إنتاجية عالية، تكلفة منخفضة جدًا&lt;/td>
&lt;td>المعالجة في الوقت الفعلي، معالجة الدفعات للبيانات الضخمة&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Anthropic&lt;/strong>&lt;/td>
&lt;td>Claude 3.5 Sonnet&lt;/td>
&lt;td>200K&lt;/td>
&lt;td>قدرات البرمجة، توليد نصوص طبيعية&lt;/td>
&lt;td>دعم تطوير البرمجيات، خدمة العملاء المتقدمة&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Anthropic&lt;/strong>&lt;/td>
&lt;td>Claude 3.5 Haiku&lt;/td>
&lt;td>200K&lt;/td>
&lt;td>استجابة فائقة السرعة، أداء عالي مقابل التكلفة&lt;/td>
&lt;td>الذكاء الاصطناعي للطرفيات (Edge AI)، روبوتات الدردشة في الوقت الفعلي&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="3-تعمق-في-البنية-ما-وراء-كواليس-طلبات-api">3. تعمق في البنية: ما وراء كواليس طلبات API
&lt;/h2>&lt;p>عند استدعاء LLM API، ما هي العمليات التي تتم في الخلفية؟ من أجل تحسين الأداء، من الضروري فهم هذه البنية.&lt;/p>
&lt;p>يوضح مخطط Mermaid التالي الصورة العامة للعملية منذ إرسال طلب API من العميل وحتى إرجاع الرموز (Tokens) عبر البث (Streaming).&lt;/p>
&lt;div class="mermaid">graph TD
A["تطبيق العميل"] -->|HTTP/REST أو gRPC| B["بوابة API"]
B --> C["موازن الحمل"]
C --> D["مجموعة الاستدلال"]
D --> E["مُقسِّم الرموز (BPE / SentencePiece)"]
E --> F["ذاكرة التخزين المؤقت KV وآلية الانتباه"]
F --> G["كتل المحول (التمرير الأمامي)"]
G --> H["طبقة المخرجات (Logits)"]
H --> I["أداة أخذ العينات (Temperature, Top-p, Top-k)"]
I --> J["مُجمِّع الرموز"]
J -->|استجابة البث (قطعة)| A&lt;/div>
&lt;h3 id="31-خوارزمية-تقسيم-الرموز-tokenization">3.1 خوارزمية تقسيم الرموز (Tokenization)
&lt;/h3>&lt;p>يتم تقسيم النص المُدخل إلى API داخليًا إلى وحدات تسمى &amp;ldquo;الرموز&amp;rdquo; (Tokens).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>OpenAI (tiktoken)&lt;/strong>: تعتمد على Byte-Pair Encoding (BPE). يتم ضغطها بكفاءة عالية جدًا، خاصة في اللغة الإنجليزية، ولكن عدد الرموز يميل إلى التضخم في اللغات غير الأبجدية.&lt;/li>
&lt;li>&lt;strong>Google (Gemini)&lt;/strong>: تعتمد على SentencePiece (Unigram Language Model). قوية في التعامل مع اللغات المتعددة، وتميل إلى القدرة على التعبير عن النصوص بعدد أقل من الرموز نسبيًا حتى في اللغات الأخرى.&lt;/li>
&lt;li>&lt;strong>Anthropic (Claude)&lt;/strong>: تستخدم نسخة مخصصة من BPE. تم تعزيز دعم اللغات المتعددة، واعتبارًا من Claude 3، تم تحسين كفاءة الرموز بشكل كبير في لغات أخرى.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="4-التحليل-الرياضي-لزمن-الاستجابة-والأداء">4. التحليل الرياضي لزمن الاستجابة والأداء
&lt;/h2>&lt;p>في التطبيقات التي تعمل في الوقت الفعلي، يرتبط زمن الاستجابة (Latency) ارتباطًا مباشرًا بتجربة المستخدم (UX). يمكن نمذجة زمن الاستجابة الكلي لـ LLM API ریاضیًا كالتالي:&lt;/p>
$$ T_{total} = T_{network} + T_{TTFT} + (N \times T_{TPOT}) $$
&lt;p>حيث يحمل كل متغير المعاني التالية:&lt;/p>
&lt;ul>
&lt;li>$T_{network}$: وقت رحلة الذهاب والإياب للشبكة (RTT).&lt;/li>
&lt;li>$T_{TTFT}$ (Time To First Token): الوقت المستغرق حتى يتم إنشاء الحرف (الرمز) الأول. يعتمد بشكل كبير على تكلفة حساب الانتباه (Attention) التي تتناسب طرديًا مع مربع طول المطالبة (عدد الرموز المدخلة).&lt;/li>
&lt;li>$N$: العدد الإجمالي للرموز المخرجة.&lt;/li>
&lt;li>$T_{TPOT}$ (Time Per Output Token): وقت الإنشاء لكل رمز. نظرًا لأنه نموذج انحدار ذاتي (Autoregressive)، يتم حسابه بشكل تسلسلي بالاعتماد على المخرجات السابقة.&lt;/li>
&lt;/ul>
&lt;h3 id="41-التعقيد-الحسابي-لآلية-الانتباه-الذاتي-self-attention">4.1 التعقيد الحسابي لآلية الانتباه الذاتي (Self-Attention)
&lt;/h3>&lt;p>يزداد التعقيد الحسابي للانتباه الذاتي في بنية Transformer بشكل تربيعي بالنسبة لطول التسلسل المدخل $L$.&lt;/p>
$$ \text{Complexity} = O(L^2 \cdot d) $$
&lt;p>حيث $d$ هو عدد أبعاد متجه التضمين (Embedding). وبسبب هذا القيد، يتدهور $T_{TTFT}$ عادة بشكل حاد عندما تطول المطالبة.
ومع ذلك، تتبنى نماذج Gemini 1.5 من Google بنيات تحسين ثورية مثل &amp;ldquo;Ring Attention&amp;rdquo; و &amp;ldquo;Block-wise Compute&amp;rdquo;، ونجحت في إنشاء الرمز الأول في وقت معقول (من بضع ثوانٍ إلى عشرات الثواني) حتى عند إدخال نص طويل يصل إلى 2 مليون رمز.&lt;/p>
&lt;hr>
&lt;h2 id="5-هيكل-التسعير-واستراتيجيات-تحسين-التكلفة">5. هيكل التسعير واستراتيجيات تحسين التكلفة
&lt;/h2>&lt;p>يتم حساب تكلفة API بشكل أساسي بناءً على عدد الرموز المدخلة والمخرجة.&lt;/p>
$$ Cost = (Tokens_{in} \times Rate_{in}) + (Tokens_{out} \times Rate_{out}) $$
&lt;p>ومع ذلك، تقدم أحدث واجهات برمجة التطبيقات آليات جديدة لتقليل التكاليف بشكل كبير.&lt;/p>
&lt;h3 id="51-التخزين-المؤقت-للمطالبات-prompt-caching">5.1 التخزين المؤقت للمطالبات (Prompt Caching)
&lt;/h3>&lt;p>إن إرسال مطالبات نظام (System Prompts) طويلة أو كميات كبيرة من المستندات المستردة بواسطة RAG في كل مرة يستهلك تكاليف هائلة. لمعالجة ذلك، تقدم كل شركة ميزات التخزين المؤقت.&lt;/p>
&lt;p>في Anthropic (Claude) و Google (Gemini)، من خلال التخزين المؤقت لكتل نصية معينة، يمكن تقليل تكاليف الإدخال بشكل كبير (حتى 90%).&lt;/p>
&lt;p>نموذج التكلفة عند استخدام التخزين المؤقت هو كالتالي:&lt;/p>
$$ Cost_{cached} = (Tokens_{cache\_write} \times Rate_{cache\_write}) + (Tokens_{cache\_read} \times Rate_{cache\_read}) + (Tokens_{out} \times Rate_{out}) $$
&lt;p>هنا يتم تعيين $Rate_{cache\_read}$ عادة بين 10% إلى 25% من $Rate_{in}$ العادي. وهذا يجعل من الممكن تشغيل روبوت دردشة بتكلفة منخفضة مع الاحتفاظ دائمًا بعشرات الآلاف من أسطر الأكواد كمعرفة أساسية.&lt;/p>
&lt;h3 id="52-واجهة-برمجة-التطبيقات-الدفعية-batch-api">5.2 واجهة برمجة التطبيقات الدفعية (Batch API)
&lt;/h3>&lt;p>للمهام التي لا تتطلب الاستجابة في الوقت الفعلي (مثل تحليل السجلات، تصنيف البيانات الضخمة، إلخ)، توفر OpenAI و Anthropic واجهات برمجة تطبيقات دفعية (Batch API). وهي آلية قوية تتيح إرسال الطلبات دفعة واحدة واستلام النتائج في غضون 24 ساعة، مقابل الحصول على خصم يصل إلى نصف سعر API العادي (خصم 50%).&lt;/p>
&lt;hr>
&lt;h2 id="6-تجربة-المطورين-dx-ومقارنة-حزم-sdk">6. تجربة المطورين (DX) ومقارنة حزم SDK
&lt;/h2>&lt;p>من منظور كفاءة التطوير، سنقارن حزم تطوير البرمجيات (SDK) التي تقدمها كل شركة.&lt;/p>
&lt;h3 id="61-openai-api">6.1 OpenAI API
&lt;/h3>&lt;p>هي الأكثر استخدامًا على نطاق واسع، ودعم المكتبات التابعة لجهات خارجية (مثل LangChain، LlamaIndex) هو الأسرع. بالإضافة إلى ذلك، تضمن ميزة المخرجات المنظمة (Structured Outputs) إرجاع استجابات تلتزم بمخطط JSON بدقة 100%، مما يسهل عملية تكامل النظام بشكل كبير.&lt;/p>
&lt;h3 id="62-anthropic-api-claude">6.2 Anthropic API (Claude)
&lt;/h3>&lt;p>تتمتع بواجهة SDK متطورة وأنيقة، وتحظى تعريفات أنواع TypeScript الخاصة بها بسمعة طيبة لسهولة استخدامها. وبشكل خاص، بنية Message API تعتبر بديهية، ويمكن كتابة الطلبات متعددة الوسائط (Multimodal) التي تتضمن صورًا متعددة بكل بساطة.&lt;/p>
&lt;h3 id="63-google-gemini-api">6.3 Google Gemini API
&lt;/h3>&lt;p>هناك نوعان من الوصول: عبر Google Cloud Vertex AI، وعبر AI Studio (Google Gen AI SDK)، وهو ما قد يربك المبتدئين قليلاً. ومع ذلك، تتكامل حزمة Vertex AI SDK الموجهة للشركات بالكامل مع نظام مصادقة الهوية والوصول (IAM) الخاص بـ GCP، مما يتيح بناء بيئة تطوير آمنة.&lt;/p>
&lt;hr>
&lt;h2 id="7-عملي-تنفيذ-اختبار-دمج-واجهات-api-متعددة-باستخدام-python">7. عملي! تنفيذ اختبار دمج واجهات API متعددة باستخدام Python
&lt;/h2>&lt;p>هنا سنقوم بكتابة نص برمجي باستخدام Python لإرسال طلبات غير متزامنة إلى 3 واجهات برمجة تطبيقات (OpenAI و Anthropic و Gemini) في نفس الوقت، ومقارنة أوقات الاستجابة.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">asyncio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AsyncOpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">anthropic&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AsyncAnthropic&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">google.generativeai&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">genai&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># تهيئة العملاء&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">openai_client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AsyncOpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;OPENAI_API_KEY&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">anthropic_client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AsyncAnthropic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ANTHROPIC_API_KEY&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">genai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">configure&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">environ&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;GEMINI_API_KEY&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;اشرح أساسيات الحوسبة الكمومية وتأثيرها على تقنيات التشفير الحالية بطريقة سهلة الفهم للمبتدئين.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">fetch_openai&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">openai_client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">completions&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4o&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">prompt&lt;/span>&lt;span class="p">}],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_tokens&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1024&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">elapsed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;OpenAI (GPT-4o)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">elapsed&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">choices&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">fetch_anthropic&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">anthropic_client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">messages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;claude-3-5-sonnet-20240620&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">prompt&lt;/span>&lt;span class="p">}],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_tokens&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1024&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">elapsed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;Anthropic (Claude 3.5 Sonnet)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">elapsed&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">fetch_gemini&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">genai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GenerativeModel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;gemini-1.5-pro&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># استخدام الطرق غير المتزامنة في حزمة Gemini Python SDK&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">generate_content_async&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">elapsed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;Google (Gemini 1.5 Pro)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">elapsed&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;جاري إرسال الطلبات إلى واجهات LLM API...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># تنفيذ الواجهات الثلاث بالتوازي&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gather&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">fetch_openai&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">fetch_anthropic&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">fetch_gemini&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">provider&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">latency&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">results&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;--- &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">provider&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Latency: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">latency&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> seconds&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Response (Excerpt): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">...&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">main&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>من خلال تشغيل هذا النص البرمجي، يمكنك بسهولة قياس أي النماذج يستجيب بأسرع وقت (ويقلل $T_{total}$) في بيئة شبكة حقيقية.&lt;/p>
&lt;hr>
&lt;h2 id="8-تنفيذ-استدعاء-الأدوات-tool-calling--function-calling-باستخدام-nodejs">8. تنفيذ استدعاء الأدوات (Tool Calling / Function Calling) باستخدام Node.js
&lt;/h2>&lt;p>لجعل LLM يعمل كـ &amp;ldquo;وكيل ذكاء اصطناعي&amp;rdquo; (AI Agent) يتفاعل مع الأنظمة الخارجية، وليس مجرد روبوت دردشة، فإن استدعاء الأدوات أو الوظائف (Tool Calling) يعد أمرًا ضروريًا. فيما يلي مثال باستخدام Node.js (TypeScript) لجعل OpenAI API يستدعي واجهة برمجة تطبيقات الطقس.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">OpenAI&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s2">&amp;#34;openai&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">openai&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">OpenAI&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">apiKey&lt;/span>: &lt;span class="kt">process.env.OPENAI_API_KEY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">async&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="nx">runAgent() {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">tools&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">type&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;function&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">function&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">name&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;get_weather&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">description&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;يسترد حالة الطقس الحالية لمدينة محددة.&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">parameters&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">type&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;object&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">properties&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">location&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">type&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">description&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;اسم المدينة (مثال: طوكيو، نيويورك)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">required&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;location&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="nx">openai&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">chat&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">completions&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">create&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">model&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;gpt-4o&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">messages&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[{&lt;/span> &lt;span class="nx">role&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;كيف هو الطقس في طوكيو اليوم؟ هل أحتاج إلى مظلة؟&amp;#34;&lt;/span> &lt;span class="p">}],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tools&lt;/span>: &lt;span class="kt">tools&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tool_choice&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;auto&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">response&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">choices&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">].&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tool_calls&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">toolCall&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">message&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tool_calls&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sb">`طلب LLM استدعاء أداة: اسم الوظيفة = &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nx">toolCall&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">name&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="sb">`&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">args&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">JSON&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">parse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">toolCall&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">arguments&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sb">`المتغيرات (Arguments): &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nx">args&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">location&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="sb">`&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// هنا تقوم بتنفيذ عملية استدعاء API الطقس الفعلي (مثل OpenWeatherMap)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// const weather = await fetchWeatherFromAPI(args.location);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تمرير النتائج المستردة مرة أخرى إلى LLM لإنشاء الإجابة النهائية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">runAgent&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="k">catch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">error&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>تمتلك نماذج Claude 3.5 Sonnet و Gemini 1.5 Pro أيضًا ميزات مشابهة لاستدعاء الأدوات، وعلى الرغم من وجود اختلافات طفيفة في طرق تعريف المخططات، إلا أن التدفق الأساسي يظل مشتركًا.&lt;/p>
&lt;hr>
&lt;h2 id="9-rag-مقابل-نافذة-السياق-الطويلة-long-context-أيهما-يجب-أن-تتبنى">9. RAG مقابل نافذة السياق الطويلة (Long Context): أيهما يجب أن تتبنى؟
&lt;/h2>&lt;p>حاليًا، من أكبر النقاشات في هندسة الذكاء الاصطناعي للمؤسسات هو: &amp;ldquo;لدمج المعرفة الخارجية، هل يجب استخدام RAG (التوليد المعزز بالاسترجاع) أم ترك كل شيء لنافذة السياق الضخمة (Long Context)؟&amp;rdquo;&lt;/p>
&lt;h3 id="فوائد-وتحديات-rag">فوائد وتحديات RAG
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>الفوائد&lt;/strong>: تكلفة منخفضة (لأنه يتم إدخال القطع اللازمة فقط في المطالبة)، ويسهل تحديد مصادر الإجابات.&lt;/li>
&lt;li>&lt;strong>التحديات&lt;/strong>: يعتمد على دقة البحث الدلالي (Semantic Search)، لذلك فهو غير مناسب لمهام الاستدلال المتقدمة حيث تتناثر السياقات في مستندات متعددة (مثل: &amp;ldquo;بناءً على جميع محاضر الاجتماعات للعام الماضي، قم بتحليل السبب الجذري لتأخير مشروع A زمنيًا&amp;rdquo;).&lt;/li>
&lt;/ul>
&lt;h3 id="نافذة-السياق-الطويلة-مثل-2-مليون-رمز-في-gemini-15-pro">نافذة السياق الطويلة (مثل 2 مليون رمز في Gemini 1.5 Pro)
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>الفوائد&lt;/strong>: لا يوجد فقدان للمعلومات بسبب البحث. حتى في اختبار &amp;ldquo;إيجاد إبرة في كومة قش&amp;rdquo; (Needle In A Haystack: NIAH)، يمكن لنماذج مثل Gemini 1.5 Pro و Claude 3.5 Sonnet استخراج المعلومات بدقة تتجاوز 99%.&lt;/li>
&lt;li>&lt;strong>التحديات&lt;/strong>: استهلاك هائل للرموز يؤدي إلى تكاليف مرتفعة، وزيادة في زمن الاستجابة ($T_{TTFT}$).&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>الخلاصة&lt;/strong>: أفضل الممارسات لعام 2026 هي &lt;strong>&amp;ldquo;النهج الهجين&amp;rdquo; (Hybrid Approach)&lt;/strong>. استخدام RAG مع قواعد البيانات المتجهة لأسئلة وأجوبة الحياة اليومية، واستخدام نافذة السياق الطويلة المدعومة بالتخزين المؤقت للمطالبات للمهام المتخصصة التي تتطلب تحليلاً معقدًا أو مراجعة للأكواد بالكامل، أصبح هذا هو التصميم السائد.&lt;/p>
&lt;hr>
&lt;h2 id="10-مقارنة-قدرات-المعالجة-متعددة-الوسائط-multimodal">10. مقارنة قدرات المعالجة متعددة الوسائط (Multimodal)
&lt;/h2>&lt;p>تطبيقات الذكاء الاصطناعي من الجيل التالي لا تتطلب فهم النصوص فحسب، بل قدرة مباشرة على فهم الصور والصوت والفيديو.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant User as "المستخدم"
participant Client as "تطبيق الواجهة الأمامية"
participant API as "LLM API (متعدد الوسائط)"
User->>Client: تحميل الفيديو والمطالبة النصية
Client->>API: إرسال بايتات/رابط الفيديو + النص
Note over API: تقسيم الفيديو وفصل الصوت
Note over API: نموذج التضمين متعدد الوسائط
API-->>Client: إرجاع ملخص نصي وطوابع زمنية
Client-->>User: عرض الرؤى (Insights)&lt;/div>
&lt;ul>
&lt;li>&lt;strong>OpenAI (GPT-4o)&lt;/strong>: دقة التعرف على الصور عالية جدًا، وتتفوق في قراءة المخططات اليدوية والرسوم البيانية المعقدة. كما تدعم واجهة Realtime API للمحادثات الصوتية الأصلية بزمن استجابة منخفض جدًا (أجزاء من الثانية) وهي ميزة قوية جدًا.&lt;/li>
&lt;li>&lt;strong>Google (Gemini 1.5 Pro)&lt;/strong>: &lt;strong>تتغلب على جميع المنافسين في تحليل الفيديو.&lt;/strong> يمكن إدخال ملف فيديو مدته ساعة (الإطارات + الصوت) كما هو، ويمكنها الإجابة على أسئلة دقيقة مثل &amp;ldquo;ما هو عنوان المستند الذي يحمله الشخص الذي يظهر على الحافة اليمنى من الشاشة في الدقيقة 12 و45 ثانية؟&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>Anthropic (Claude 3.5 Sonnet)&lt;/strong>: قدرة التعرف البصري (Vision) ممتازة تضاهي GPT-4o. تبرز قوتها المنقطعة النظير في دعم تطوير الواجهة الأمامية، مثل تمرير لقطة شاشة لواجهة المستخدم (UI) وطلب &amp;ldquo;توليد كود مكونات React لهذه الشاشة&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="11-الأمن-والامتثال-compliance-على-مستوى-المؤسسات">11. الأمن والامتثال (Compliance) على مستوى المؤسسات
&lt;/h2>&lt;p>عند استخدام الشركات لـ LLM API في بيئة الإنتاج، فإن أكبر مخاوفها تتمحور حول &amp;ldquo;هل ستُستخدم بياناتنا في تدريب الذكاء الاصطناعي؟&amp;rdquo; و&amp;quot;هل يلبي متطلبات الامتثال؟&amp;quot;.&lt;/p>
&lt;p>الشركات الثلاث أعلنت صراحة أن البيانات المُرسلة عبر الـ API (المطالبات والاستجابات) &lt;strong>لا تُستخدم لتدريب النماذج (Zero Data Retention / No Training on Customer Data)&lt;/strong> (ملاحظة: واجهة الدردشة المجانية للمستهلكين تختلف عن ذلك).&lt;/p>
&lt;p>للمتطلبات الأمنية الأعلى:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>OpenAI&lt;/strong>: من خلال Azure OpenAI Service، يمكن الاستفادة من أمان مستوى المؤسسات من Microsoft، واتفاقيات مستوى الخدمة (SLA)، والاتصال بشبكة مغلقة عبر Azure Private Link.&lt;/li>
&lt;li>&lt;strong>Google&lt;/strong>: عبر Google Cloud Vertex AI، يمكن عزل الشبكة بصرامة باستخدام VPC Service Controls، وحماية البيانات عبر مفاتيح التشفير المدارة من قبل العميل (CMEK).&lt;/li>
&lt;li>&lt;strong>Anthropic&lt;/strong>: عبر AWS Bedrock أو Google Cloud Vertex AI، يمكن الاعتماد على البنية التحتية الأمنية القوية لموفري الخدمات السحابية.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="12-الخلاصة-الدليل-النهائي-للاختيار-حسب-حالة-الاستخدام">12. الخلاصة: الدليل النهائي للاختيار حسب حالة الاستخدام
&lt;/h2>&lt;p>لقد قمنا بإجراء مقارنة شاملة، ولكن الإجابة النهائية على &amp;ldquo;أيهم تختار؟&amp;rdquo; تعتمد على حالة الاستخدام الخاصة بك.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>تطوير البرمجيات المعقدة، توليد الأكواد، الاستدلال المتقدم&lt;/strong>:
&lt;strong>👑 الفائز: Claude 3.5 Sonnet (Anthropic)&lt;/strong>
يقدم حاليًا أفضل أداء في فهم سياق الكود، وإعادة الهيكلة، وكتابة نصوص طبيعية قريبة من البشر. كما أنه يتميز بسهولة استخدام الـ API وكفاءة التكلفة بفضل التخزين المؤقت للمطالبات.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>تحليل المستندات الطويلة جدًا، المعالجة الدفعية للفيديو/الصوت&lt;/strong>:
&lt;strong>👑 الفائز: Gemini 1.5 Pro (Google)&lt;/strong>
نافذة السياق التي تبلغ 2 مليون رمز هي سلاح لا مثيل له. لا يوجد ما يضاهي Gemini في المهام التي تتطلب فهم الصورة الكاملة للبيانات، مثل تحليل مئات الصفحات من أدلة PDF أو تلخيص تسجيلات اجتماعات طويلة.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>التنوع، سرعة التنفيذ، والمخرجات المنظمة المستقرة (JSON)&lt;/strong>:
&lt;strong>👑 الفائز: GPT-4o / GPT-4o-mini (OpenAI)&lt;/strong>
ينفذ أي مهمة بكفاءة، ويدعم أكبر عدد من أدوات الطرف الثالث. يُعد نظام OpenAI البيئي ضروريًا إذا كنت بحاجة إلى تحليل JSON موثوق باستخدام Structured Outputs، أو استدلال منطقي عالي المستوى عبر نماذج o1.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="التوصية-بتوجيه-النماذج-المتعددة-multi-model-routing">التوصية بتوجيه النماذج المتعددة (Multi-Model Routing)
&lt;/h3>&lt;p>الاتجاه المستقبلي هو عدم الاعتماد على API واحد (Vendor lock-in)، بل التبديل الديناميكي بين النماذج حسب صعوبة أو أهمية المهمة، وهو ما يُعرف بهندسة &lt;strong>&amp;ldquo;توجيه LLM&amp;rdquo; (LLM Routing)&lt;/strong>.
على سبيل المثال، الاستجابة للأسئلة البسيطة من المستخدمين باستخدام &lt;code>GPT-4o-mini&lt;/code> أو &lt;code>Gemini 1.5 Flash&lt;/code> السريع والرخيص، والتراجع (Fallback) للمهام إلى &lt;code>Claude 3.5 Sonnet&lt;/code> فقط عند الحاجة إلى معالجة معقدة. هذا يحقق توازنًا مثاليًا بين التكلفة والأداء.&lt;/p>
&lt;p>تطور الذكاء الاصطناعي لن يتوقف. يجب الفهم العميق لنقاط القوة والضعف في كل API وخصائص بنية النظام لبناء تطبيقات ذكاء اصطناعي مرنة وقابلة للتوسع.&lt;/p></description></item><item><title>استخدام llama.cpp ومقدمة في التخصيص باستخدام C++</title><link>http://kenji.blog/ar/p/llama-cpp-cxx-customization/</link><pubDate>Fri, 11 Sep 2026 11:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/llama-cpp-cxx-customization/</guid><description>&lt;img src="http://kenji.blog/p/llama-cpp-cxx-customization/img/eyecatch.jpg" alt="Featured image of post استخدام llama.cpp ومقدمة في التخصيص باستخدام C++" />&lt;p>في السنوات الأخيرة، كان تطور النماذج اللغوية الكبيرة (LLMs) مذهلاً، ويتوسع نطاق تطبيقاتها يومًا بعد يوم. ومع ذلك، فإن تشغيل النماذج التي تحتوي على مليارات أو عشرات المليارات من المعلمات في بيئة محلية يتطلب عادةً وحدات معالجة رسومية (GPUs) متطورة مع ذاكرة VRAM ضخمة. لقد حطم &lt;strong>llama.cpp&lt;/strong> &amp;ldquo;حاجز الأجهزة&amp;rdquo; هذا، مما أتاح استنتاجًا عمليًا لـ LLM على أجهزة الكمبيوتر الشخصية وأجهزة Mac العادية، وحتى أجهزة مثل Raspberry Pi.&lt;/p>
&lt;p>في هذه المقالة، لن نقتصر على شرح كيفية استخدام أداة سطر الأوامر فقط، بل سنقدم شرحًا مفصلاً جدًا للمهندسين حول التكنولوجيا الأساسية لها، معمارية &lt;code>ggml&lt;/code>، والخلفية الرياضية لـ Transformer والتكميم (Quantization)، وكيفية استخدام واجهة برمجة تطبيقات C++ لدمج وتخصيص LLM في تطبيقاتك الخاصة.&lt;/p>
&lt;hr>
&lt;h2 id="1-نظرة-عامة-على-llamacpp-و-ggml">1. نظرة عامة على llama.cpp و ggml
&lt;/h2>&lt;p>&lt;code>llama.cpp&lt;/code> هو محرك استنتاج LLM خفيف الوزن مكتوب بلغة C/C++، تم تطويره بواسطة Georgi Gerganov. في البداية، تم إنشاؤه بغرض تشغيل نماذج LLaMA من Meta بسرعات عالية على Apple Silicon (M1/M2 Mac)، ولكنه يدعم الآن مجموعة متنوعة من المعماريات والنماذج.&lt;/p>
&lt;p>أكبر ميزة له هي أنه &lt;strong>تطبيق C/C++ نقي ولا يحتوي على تبعيات خارجية&lt;/strong>. نظرًا لأنه لا يتطلب أنظمة بيئية ضخمة مثل Python أو PyTorch ويمكن تجميعه كملف تنفيذي واحد، فإن نشره سهل للغاية.&lt;/p>
&lt;p>قلب &lt;code>llama.cpp&lt;/code> هو مكتبة عمليات الموترات (Tensor) &lt;strong>ggml&lt;/strong>. تم تصميم ggml من الصفر لتحسين عمليات المصفوفات في التعلم الآلي إلى أقصى حد على وحدات المعالجة المركزية (CPU) (وبعض وحدات المعالجة الرسومية GPU).&lt;/p>
&lt;h3 id="11-لماذا-llamacpp-سريع">1.1 لماذا llama.cpp سريع؟
&lt;/h3>&lt;ol>
&lt;li>&lt;strong>الاستفادة من تعيين الذاكرة (mmap)&lt;/strong>: عند تحميل أوزان النموذج في الذاكرة، يؤدي استخدام &lt;code>mmap&lt;/code> الخاص بنظام التشغيل إلى تجنب التحميل الكامل في ذاكرة الوصول العشوائي (RAM)، مما يحقق بدء تشغيل سريع وتوفيرًا للذاكرة.&lt;/li>
&lt;li>&lt;strong>التحسين الشامل لتعليمات SIMD&lt;/strong>: يستفيد من مجموعات التعليمات الخاصة بوحدة المعالجة المركزية مثل AVX2 و AVX-512 و ARM NEON و Apple AMX لتسريع ضرب المصفوفات بشكل كبير.&lt;/li>
&lt;li>&lt;strong>التكميم (Quantization)&lt;/strong>: يضغط الأوزان ذات النقطة العائمة 16 بت (FP16) إلى أعداد صحيحة 4 بت، 5 بت، و 8 بت، مما يزيل اختناق عرض النطاق الترددي للذاكرة (سيتم تفصيل ذلك لاحقًا).&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="2-الخلفية-الرياضية-transformer-والتكميم-quantization">2. الخلفية الرياضية: Transformer والتكميم (Quantization)
&lt;/h2>&lt;p>لفهم llama.cpp بعمق، يجب أن تعرف الصيغ الرياضية التي يحسبها وكيف يقارب العمليات الحسابية.&lt;/p>
&lt;h3 id="21-عملية-الاستنتاج-في-transformer">2.1 عملية الاستنتاج في Transformer
&lt;/h3>&lt;p>تعتمد نماذج مثل LLaMA على معمارية Transformer Decoder ذاتية الانحدار (Auto-regressive). جوهر توليد النص هو آلية &lt;strong>Self-Attention&lt;/strong>.&lt;/p>
&lt;p>بالنسبة لمصفوفة الحالة المخفية المدخلة $X \in \mathbb{R}^{N \times d}$، يتم حساب الاستعلام (Query) $Q$ والمفتاح (Key) $K$ والقيمة (Value) $V$ من خلال الضرب مع مصفوفات الأوزان.&lt;/p>
$$
Q = X W_Q, \quad K = X W_K, \quad V = X W_V
$$
&lt;p>هنا، يُعرَّف ناتج Attention على النحو التالي:&lt;/p>
$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
&lt;p>في حلقة استنتاج llama.cpp، يكمن عنق الزجاجة في ضرب مصفوفات الأوزان الضخمة هذه $W_Q, W_K, W_V$ ومصفوفات أوزان شبكة التغذية الأمامية (FFN) مع المتجه $X$ (في مرحلة التوليد $N=1$ لأنه يعالج رمزًا مميزًا (token) واحدًا في كل مرة)، أي &lt;strong>GEMV (General Matrix-Vector Multiplication)&lt;/strong>.&lt;/p>
&lt;h3 id="22-الأساس-الرياضي-للتكميم-quantization">2.2 الأساس الرياضي للتكميم (Quantization)
&lt;/h3>&lt;p>في الاستنتاج حيث يكون النطاق الترددي للوصول إلى الذاكرة هو عنق الزجاجة، فإن التكميم، الذي يمثل معلمات الوزن بعدد صغير من البتات، أمر لا غنى عنه. سنشرح المبدأ الأساسي للتكميم المعتمد على الكتل (مثل &lt;code>Q4_K&lt;/code> أو &lt;code>Q4_0&lt;/code>) المستخدم على نطاق واسع في llama.cpp.&lt;/p>
&lt;p>على سبيل المثال، لنفترض كتلة $w = [w_1, w_2, \dots, w_B]$ بطول $B$ (عادةً 32 أو 64) وهي جزء من مصفوفة أوزان FP16 المسماة $W$. تُقارب هذه الكتلة إلى أعداد صحيحة 4 بت $q_i \in [-8, 7]$ وعامل مقياس (scaling factor) واحد $\Delta$ (إما FP16 أو FP32).&lt;/p>
$$
w_i \approx \Delta \times q_i
$$
&lt;p>يتم تحديد $\Delta$ بناءً على القيمة المطلقة القصوى داخل الكتلة.&lt;/p>
$$
\Delta = \frac{\max_i |w_i|}{7}
$$
&lt;p>عند حساب حاصل الضرب النقطي $y = w \cdot x$ باستخدام الأوزان المكممة، إذا قمنا أيضًا بتكميم متجه الإدخال $x$ ليصبح $x_i \approx \Delta_x \times q_{x, i}$، فإن:&lt;/p>
$$
y = \sum_{i=1}^{B} w_i x_i \approx \Delta \Delta_x \sum_{i=1}^{B} q_i q_{x, i}
$$
&lt;p>الجزء الخاص بـ $\sum q_i q_{x, i}$ هو عبارة عن &lt;strong>عملية أعداد صحيحة نقية&lt;/strong>، ويمكن حسابه بالتوازي بسرعة عالية جدًا باستخدام تعليمات SIMD. هذا هو السر الرياضي وراء السرعات المذهلة التي يحققها llama.cpp على وحدة المعالجة المركزية (CPU).&lt;/p>
&lt;hr>
&lt;h2 id="3-المعمارية-وتدفق-الاستنتاج">3. المعمارية وتدفق الاستنتاج
&lt;/h2>&lt;p>لفهم الأعمال الداخلية لـ llama.cpp، يُظهر مخطط Mermaid التالي بنية النظام بأكمله وتدفق البيانات.&lt;/p>
&lt;div class="mermaid">graph TD
A["إدخال المستخدم (نص)"] --> B["مجزئ llama.cpp (Tokenizer)"]
B --> C["معرفات الرموز (مصفوفة int32)"]
C --> D["المخزن المؤقت للسياق (KV Cache)"]
D --> E["رسم بياني حسابي ggml"]
E --> F["طبقات Transformer"]
subgraph "محرك ggml"
F --> G["الانتباه الذاتي (RoPE)"]
G --> H["شبكة التغذية الأمامية (FFN)"]
H --> F
end
F --> I["الاحتمالات (Logits - حجم المفردات)"]
I --> J["مُصنف العينات (Temperature, Top-K, Top-P)"]
J --> K["معرف الرمز المحدد"]
K --> L["مُجمّع النصوص llama.cpp (Detokenizer)"]
L --> M["النص الناتج"]
K -. "حلقة ذاتية الانحدار" .-> D&lt;/div>
&lt;p>توليد النص هو حلقة ذاتية الانحدار حيث أنه في كل مرة يتم فيها إخراج رمز مميز (Token) واحد، تتم إضافته إلى ذاكرة التخزين المؤقت KV كإدخال تالٍ ويمر عبر الرسم البياني الحسابي مرة أخرى.&lt;/p>
&lt;hr>
&lt;h2 id="4-إعداد-البيئة-وطريقة-البناء">4. إعداد البيئة وطريقة البناء
&lt;/h2>&lt;p>قبل دمج llama.cpp في مشاريع C++، دعنا نقوم أولاً ببناء الكود المصدري.&lt;/p>
&lt;h3 id="41-استنساخ-المستودع">4.1 استنساخ المستودع
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git clone https://github.com/ggerganov/llama.cpp.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> llama.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="42-البناء-باستخدام-cmake">4.2 البناء باستخدام CMake
&lt;/h3>&lt;p>إذا كنت تريد دمجه في تطبيقات أخرى كمشروع C++، فإن استخدام CMake هو الأكثر معيارية. من خلال تمكين المسرع (backend) الخاص بكل منصة، يمكنك تسريع العمليات الحسابية.&lt;/p>
&lt;p>&lt;strong>وحدة المعالجة المركزية (CPU) فقط (بناء أساسي):&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir build &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build . --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>في حالة استخدام وحدة معالجة رسومية NVIDIA GPU (CUDA):&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir build &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake .. -DGGML_CUDA&lt;span class="o">=&lt;/span>ON
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build . --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>في حالة استخدام Apple Silicon (Metal):&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir build &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake .. -DGGML_METAL&lt;span class="o">=&lt;/span>ON
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build . --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>إذا نجح البناء، فسيتم إنشاء ملفات تنفيذية مثل &lt;code>llama-cli&lt;/code> في الدليل &lt;code>build/bin/&lt;/code>، ومكتبة &lt;code>llama&lt;/code> (وكذلك مكتبة &lt;code>ggml&lt;/code>) لربطها عبر واجهة برمجة تطبيقات C++ الموضحة أدناه.&lt;/p>
&lt;hr>
&lt;h2 id="5-مقدمة-في-التخصيص-باستخدام-c-استخدام-واجهة-برمجة-تطبيقات-llamacpp">5. مقدمة في التخصيص باستخدام C++: استخدام واجهة برمجة تطبيقات llama.cpp
&lt;/h2>&lt;p>من هنا، سنشرح الموضوع الرئيسي وهو كيفية التحكم في llama.cpp من كود C++.
لدمج LLM في تطبيقاتك الخاصة (مثل محركات الألعاب، تطبيقات سطح المكتب، الأنظمة المدمجة، إلخ) بدلاً من استخدام أداة سطر الأوامر فقط، ستحتاج إلى التفاعل مع واجهة برمجة تطبيقات C++ مباشرةً.&lt;/p>
&lt;p>يوفر llama.cpp واجهة برمجة بلغة C بشكل أساسي من خلال ملف الرأس &lt;code>llama.h&lt;/code>. حتى عند الاستدعاء من C++، يتم استخدام هذه الواجهة.&lt;/p>
&lt;h3 id="51-الحد-الأدنى-من-التضمينات-includes-والإعدادات">5.1 الحد الأدنى من التضمينات (Includes) والإعدادات
&lt;/h3>&lt;p>عند استخدام llama.cpp في مشروعك، قم بتضمين ما يلي:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;llama.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ماكرو لمعالجة الأخطاء
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#define LLAMA_ASSERT(x) \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> do { \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> if (!(x)) { \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> std::cerr &amp;lt;&amp;lt; &amp;#34;Assertion failed: &amp;#34; &amp;lt;&amp;lt; #x &amp;lt;&amp;lt; std::endl; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> std::terminate(); \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> } \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> } while (0)
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-تحميل-النموذج-وتهيئة-السياق">5.2 تحميل النموذج وتهيئة السياق
&lt;/h3>&lt;p>أولاً، نقوم بتحميل ملف النموذج بصيغة &lt;code>.gguf&lt;/code> ونخصص السياق (مساحة الذاكرة و KV Cache) للاستنتاج.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">**&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">argc&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Usage: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; &amp;lt;model.gguf&amp;gt;&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">model_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. تهيئة الواجهة الخلفية (إعداد بيئة CPU/GPU وغيرها)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_backend_init&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. الحصول على الإعدادات الافتراضية لمعلمات النموذج
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_model_params&lt;/span> &lt;span class="n">model_params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_model_default_params&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_gpu_layers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">35&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// عدد الطبقات التي يتم تفريغها إلى وحدة المعالجة الرسومية (GPU)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 3. تحميل النموذج
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_model&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_load_model_from_file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model_path&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">c_str&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">model_params&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to load model&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 4. إعداد معلمات السياق
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_context_params&lt;/span> &lt;span class="n">ctx_params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_context_default_params&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ctx_params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2048&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// الحد الأقصى لحجم السياق (عدد الرموز)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">ctx_params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_threads&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// عدد خيوط وحدة المعالجة المركزية (CPU threads) المستخدمة في الاستنتاج
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. إنشاء السياق
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_context&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_new_context_with_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctx_params&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to create context&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_free_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Model and context loaded successfully!&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ... العمليات اللاحقة
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-تقطيع-النص-الموجه-إلى-رموز-tokenization">5.3 تقطيع النص الموجه إلى رموز (Tokenization)
&lt;/h3>&lt;p>لا تفهم نماذج LLM النصوص مباشرة، بل تعالجها كسلسلة من المعرفات الصحيحة (الرموز). يجب تحويل سلسلة الإدخال إلى رموز.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Q: ما هي عاصمة اليابان؟&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">A:&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">llama_token&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// حجم ذاكرة تخزين مؤقت به مساحة كافية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ما إذا كان سيتم إضافة رموز خاصة (مثل BOS: Begin of Sequence) في البداية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">add_special&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تحويل السلسلة النصية إلى مصفوفة معرفات الرموز (Token IDs)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_tokenize&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">c_str&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">add_special&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">false&lt;/span> &lt;span class="c1">// parse_special
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n_tokens&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إذا كان المخزن المؤقت غير كافٍ، يجب إعادة تخصيصه وإعادة المحاولة (تم الحذف للتبسيط)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to tokenize prompt&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_tokens&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="54-حلقة-الاستنتاج-وأخذ-العينات">5.4 حلقة الاستنتاج وأخذ العينات
&lt;/h3>&lt;p>تقوم بتمرير الرموز إلى النموذج، والحصول على التوزيع الاحتمالي للرمز التالي (Logits)، ثم إنشاء حلقة لأخذ عينات من تلك الاحتمالات لتحديد الرمز التالي.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// الحد الأقصى لعدد الرموز المراد توليدها
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">max_gen_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تهيئة الهيكل (struct) لتقييم الدُفعات (Batch evaluation)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_batch&lt;/span> &lt;span class="n">batch&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_batch_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">512&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إضافة رموز المُوجّه إلى الدُفعة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_batch_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">},&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إعداد لإخراج الاحتمالات (Logits - نتائج التوقع) فقط في الرمز الأخير من المُوجّه
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">logits&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_tokens&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// التقييم الأول (إطعام المُوجّه للنموذج)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;llama_decode() failed&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_cur&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_tokens&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// طول السياق الحالي
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_decode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">Output: &amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تهيئة سياق أخذ العينات (إعدادات Temperature, Top-K, Top-P وما إلى ذلك)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_sampler&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">smpl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_sampler_chain_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">llama_sampler_chain_default_params&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_top_k&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_top_p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.9f&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_temp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.7f&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_dist&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1234&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// قيمة البذرة (Seed)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n_decode&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">max_gen_tokens&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. أخذ العينات: توقع الرمز التالي بناءً على السياق الحالي
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_token&lt;/span> &lt;span class="n">new_token_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_sampler_sample&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. إنهاء الحلقة إذا كان الرمز هو EOS (End of Sequence)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_token_is_eog&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_token_id&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 3. فك تشفير الرمز إلى سلسلة نصية (نص) وعرضها
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="n">buf&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">128&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_chars&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_token_to_piece&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_token_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">buf&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buf&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n_chars&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buf&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_chars&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">flush&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 4. إعداد الرمز المولد حديثًا كدُفعة تالية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_batch_clear&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_batch_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_token_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_cur&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">},&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. تقييم النموذج (تحديث ذاكرة التخزين المؤقت KV وتوقع التالي)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to evaluate&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n_cur&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n_decode&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// التنظيف (Cleanup)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_sampler_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_batch_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_free_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_backend_free&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>يقوم هذا الكود بتنفيذ حلقة استنتاج مخصصة باستخدام واجهة برمجة التطبيقات الأساسية لـ llama.cpp.
تتم إدارة مجموعة الرموز باستخدام هيكل &lt;code>llama_batch&lt;/code>، ويتم تنفيذ التمرير الأمامي (الانتشار الأمامي) للشبكة العصبية بـ &lt;code>llama_decode&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="6-دراسة-حالة-التخصيص-المتقدم-معالجة-logits-والتحكم-في-العقوبات-penalty-عبر-c">6. دراسة حالة التخصيص المتقدم: معالجة Logits والتحكم في العقوبات (Penalty) عبر C++
&lt;/h2>&lt;p>بالإضافة إلى التوليد البسيط للنص، عندما تريد فرض إخراج بتنسيق معين (مثل JSON فقط)، أو التحكم لمنع إخراج كلمات محظورة معينة، يمكنك التحكم مباشرة في &lt;strong>الاحتمالات الأولية (Logits)&lt;/strong> قبل أخذ العينات من جانب C++.&lt;/p>
&lt;p>يمكنك الحصول على مصفوفة النتائج الخام (القيم قبل تحويلها إلى احتمالات) مباشرة قبل أن يخرج النموذج كل رمز.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// الحصول على مصفوفة Logits الخام بعد الاستنتاج مباشرة، وقبل أخذ العينات
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">float&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">logits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_get_logits_ith&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_tokens&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="n">n_vocab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_n_vocab&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// قائمة بمعرفات الرموز المحظورة (على سبيل المثال 1234، 5678)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">llama_token&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">forbidden_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">1234&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5678&lt;/span> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// تعيين احتمال ظهور الرموز المحظورة إلى 0 (جعل Logit سالب ما لا نهاية)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_token&lt;/span> &lt;span class="nl">bad_tok&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">forbidden_tokens&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logits&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">bad_tok&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">INFINITY&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بهذه الطريقة، من خلال التعامل المباشر مع واجهة برمجة تطبيقات C++، يصبح &lt;strong>&amp;ldquo;التدخل على مستوى الميكروثانية والملي ثانية لكل دورة استنتاج&amp;rdquo;&lt;/strong> ممكنًا، وهو أمر صعب التحقيق أو يتطلب عبئًا كبيرًا (Overhead) عند القيام به من خلال LangChain أو Python.&lt;/p>
&lt;hr>
&lt;h2 id="7-أسرار-ضبط-الأداء">7. أسرار ضبط الأداء
&lt;/h2>&lt;p>فيما يلي بعض نقاط التحقق لزيادة السرعة إلى أقصى حد للتشغيل الفعلي بعد الانتهاء من التنفيذ في C++.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>تحسين معالجة الدفعات:&lt;/strong> عند معالجة طلبات من عدة مستخدمين في نفس الوقت، يمكنك تضمين عدة تسلسلات في &lt;code>llama_batch&lt;/code> واستدعاء &lt;code>llama_decode&lt;/code> مرة واحدة (Continuous Batching). يتيح ذلك مشاركة الوصول إلى الذاكرة وتحسين الإنتاجية (Throughput) بشكل كبير.&lt;/li>
&lt;li>&lt;strong>تفعيل Flash Attention:&lt;/strong>
من خلال تعيين &lt;code>ctx_params.flash_attn = true;&lt;/code> في معلمات السياق، يمكنك تقليل استخدام الذاكرة مع تسريع حسابات Attention. هذا الإعداد ضروري عند التعامل مع سياقات طويلة (عشرات الآلاف من الرموز).&lt;/li>
&lt;li>&lt;strong>دعم NUMA:&lt;/strong>
في بيئات الخوادم متعددة المقابس (Multi-socket)، من خلال تكوين إعدادات NUMA بشكل صحيح قبل &lt;code>llama_backend_init()&lt;/code>، يمكنك تقليل وقت استجابة الوصول إلى الذاكرة (Latency).&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-خاتمة">8. خاتمة
&lt;/h2>&lt;p>في هذه المقالة، قدمنا شرحًا مفصلاً بدءًا من الخلفية الرياضية لـ &lt;code>llama.cpp&lt;/code>، مرورًا بشرح المعمارية، ووصولاً إلى كيفية بناء محرك استنتاج مخصص باستخدام واجهة برمجة تطبيقات C++.&lt;/p>
&lt;p>في حين أن النظام البيئي لـ Python ملائم للغاية للنماذج الأولية (Prototyping)، إلا أن التحكم المباشر عبر &lt;code>llama.cpp&lt;/code> القائم على C/C++ يُظهر قوة ساحقة في بيئات الإنتاج التي تتطلب النشر على الأجهزة الطرفية (Edge devices)، والدمج في الألعاب، والمعالجة في الوقت الفعلي.&lt;/p>
&lt;p>نشجعك على كتابة كود C++ بيدك وتجربة متعة التحكم بحرية في LLM في بيئتك المحلية.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>مجموعة الروابط المرجعية&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener"
>المستودع الرسمي llama.cpp&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/ggml" target="_blank" rel="noopener"
>ggml - مكتبة Tensor&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
>Attention Is All You Need (Vaswani et al., 2017)&lt;/a>&lt;/li>
&lt;/ul>
&lt;/blockquote></description></item><item><title>【أحدث إصدار لعام 2026】الدليل الشامل لتشغيل النماذج اللغوية الكبيرة (LLM) المحلية على بيئة ويندوز</title><link>http://kenji.blog/ar/p/local-llm-windows-2026/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/local-llm-windows-2026/</guid><description>&lt;img src="http://kenji.blog/p/local-llm-windows-2026/img/eyecatch.jpg" alt="Featured image of post 【أحدث إصدار لعام 2026】الدليل الشامل لتشغيل النماذج اللغوية الكبيرة (LLM) المحلية على بيئة ويندوز" />&lt;h1 id="1-مقدمة-لماذا-نماذج-llm-المحلية-على-ويندوز-الآن">1. مقدمة: لماذا نماذج LLM المحلية على ويندوز الآن؟
&lt;/h1>&lt;p>في عام 2026، يشهد تطور الذكاء الاصطناعي التوليدي والنماذج اللغوية الكبيرة (LLM) نقلة نوعية كبرى من خدمات واجهة برمجة التطبيقات (API) الضخمة على السحابة إلى &amp;ldquo;نماذج LLM المحلية&amp;rdquo; التي تعمل على أجهزة الكمبيوتر الشخصية والبيئات المحلية (On-Premises). على الرغم من أن نماذج الذكاء الاصطناعي السحابية مثل GPT-5 من OpenAI و Claude 3.5 من Anthropic قوية جدًا، إلا أنه لا يمكن للشركات والأفراد إرسال جميع بياناتهم إلى السحابة. من منظور الخصوصية، والأمان، وزمن الوصول (Latency)، والتكلفة المستدامة طويلة الأجل، فقد زاد الطلب على نماذج LLM المحلية بشكل غير مسبوق وبشكل هائل.&lt;/p>
&lt;p>تطور النظام البيئي لنماذج LLM المحلية في بيئة ويندوز (Windows) بشكل خاص كان مذهلًا. حتى سنوات قليلة مضت، كان من المتعارف عليه أن &amp;ldquo;تطوير وتشغيل الذكاء الاصطناعي يعني Linux&amp;rdquo;، ولكن في عام 2026، تحول نظام ويندوز إلى منصة ذكاء اصطناعي قوية وسهلة الاستخدام للغاية.&lt;/p>
&lt;p>في هذه المقالة، وبناءً على أحدث الاتجاهات التقنية لعام 2026، نقدم دليلاً شاملاً لبناء، وتشغيل، وتحسين نماذج LLM المحلية في بيئة ويندوز. سنقوم بشرح مفصل بحجم هائل يغطي كل شيء بدءًا من الإعداد البسيط للمبتدئين باستخدام Ollama، والتحسين الأقصى للمتقدمين باستخدام llama.cpp، وحتى الفهم العميق للبنية (Architecture) والنهج الرياضي لحساب ذاكرة الوصول العشوائي للفيديو (VRAM)، بالإضافة إلى الضبط الدقيق (Fine-tuning) محليًا.&lt;/p>
&lt;h2 id="11-الاتجاهات-التقنية-المحيطة-بنماذج-llm-المحلية-في-عام-2026">1.1 الاتجاهات التقنية المحيطة بنماذج LLM المحلية في عام 2026
&lt;/h2>&lt;p>تتمثل الاتجاهات الرئيسية التي تشكل النظام البيئي الحالي لنماذج LLM المحلية فيما يلي:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>الانتشار الكامل لتنسيق GGUF&lt;/strong>: أصبح تنسيق GGUF (GPT-Generated Unified Format)، الذي يدمج البيانات الوصفية (Metadata) والموترات (Tensors) في ملف واحد، معيارًا أساسيًا (De facto standard) بالكامل. وبفضل هذا، أصبح من الممكن تشغيل النماذج في أي بيئة بمجرد تنزيل ملف واحد من Hugging Face.&lt;/li>
&lt;li>&lt;strong>إضفاء الطابع الديمقراطي على بنية MoE (مزيج الخبراء)&lt;/strong>: تم إطلاق العديد من نماذج MoE صغيرة الحجم ولكنها عالية الأداء. ومن خلال تنشيط بعض الخبراء فقط أثناء الاستدلال (Inference)، فإنها تحقق أداءً يضاهي النماذج الضخمة مع تقليل العبء الحسابي على أجهزة الكمبيوتر الشخصية الاستهلاكية.&lt;/li>
&lt;li>&lt;strong>التجريد العالي والتحسين لمحركات الاستدلال&lt;/strong>: تم تحسين أدوات مثل Ollama، LM Studio، و AnythingLLM، ولم يعد المستخدمون بحاجة إلى القلق بشأن التبعيات المعقدة مثل تثبيت برامج تشغيل CUDA. بالإضافة إلى ذلك، بفضل الدعم الأصلي (Native) لـ FlashAttention 3 على ويندوز، زادت سرعة الاستدلال بشكل كبير.&lt;/li>
&lt;li>&lt;strong>الاستفادة من وحدات المعالجة العصبية (NPU) وظهور أجهزة كمبيوتر Windows Copilot+&lt;/strong>: حتى بالنسبة لأجهزة الكمبيوتر المحمولة التي لا تحتوي على وحدة معالجة رسومات (GPU)، فقد دخلت تقنية تشغيل النماذج اللغوية الصغيرة (SLM) باستهلاك منخفض للطاقة باستخدام وحدة المعالجة العصبية (NPU) المدمجة مرحلة الاستخدام العملي.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="2-متطلبات-الأجهزة-hardware-وإعداد-نظام-التشغيل">2. متطلبات الأجهزة (Hardware) وإعداد نظام التشغيل
&lt;/h1>&lt;p>لكي تعمل نماذج LLM المحلية بسرعة عملية (أكثر من 15 إلى 30 رمزًا مميزًا &amp;ldquo;Token&amp;rdquo; في الثانية)، يعد اختيار الأجهزة (Hardware) هو الأمر الأكثر أهمية.&lt;/p>
&lt;h2 id="21-تكوين-الأجهزة-الموصى-به">2.1 تكوين الأجهزة الموصى به
&lt;/h2>&lt;p>مع تطور أجهزة الكمبيوتر الخاصة بالذكاء الاصطناعي (AI PC)، تتغير أيضًا المواصفات المطلوبة.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>نظام التشغيل (OS)&lt;/strong>: Windows 11 Pro (إصدار 24H2 أو أحدث). يعد هذا ضروريًا للاستفادة الكاملة من ميزات WSL2، والإدارة المتقدمة للذاكرة، بالإضافة إلى استخدام أحدث واجهات برمجة التطبيقات (API) الخاصة بـ DirectML.&lt;/li>
&lt;li>&lt;strong>وحدة المعالجة المركزية (CPU)&lt;/strong>: سلسلة Intel Core Ultra 200 أو أحدث، أو سلسلة AMD Ryzen 9000 أو أحدث. عند استخدام استدلال CPU معًا، فإن الاتصال بذاكرة ذات نطاق ترددي عالي يعد أمرًا لا غنى عنه.&lt;/li>
&lt;li>&lt;strong>ذاكرة الوصول العشوائي (RAM)&lt;/strong>: الحد الأدنى 32 جيجابايت، ويُوصى بـ 64 جيجابايت أو أكثر. يصبح النطاق الترددي للذاكرة الرئيسية (بالجيجابايت/ثانية) هو عنق الزجاجة (Bottleneck) الحاسم أثناء استدلال CPU أو عند تفريغ التحميل (Offloading). يُفضل استخدام ذاكرة عالية السرعة DDR5-6000 أو أعلى.&lt;/li>
&lt;li>&lt;strong>وحدة معالجة الرسومات (GPU)&lt;/strong>: سلسلة NVIDIA RTX 4000/5000. الأهم في نماذج LLM المحلية ليس أداء الحوسبة بل &amp;ldquo;سعة ذاكرة الوصول العشوائي للفيديو (VRAM)&amp;rdquo;.
&lt;ul>
&lt;li>&lt;strong>فئة البداية (Entry)&lt;/strong>: RTX 4060 Ti (نسخة 16 جيجابايت) - الأفضل من حيث التكلفة والأداء. مثالية لنماذج بحجم 8B إلى 14B.&lt;/li>
&lt;li>&lt;strong>الفئة المتوسطة (Mid-range)&lt;/strong>: RTX 4070 Ti SUPER (16 جيجابايت) / RTX 4080 SUPER (16 جيجابايت).&lt;/li>
&lt;li>&lt;strong>الفئة المتقدمة (High-end)&lt;/strong>: RTX 4090 (24 جيجابايت) / RTX 5090 (32 جيجابايت) - مطلوبة لتشغيل النماذج المكممة (Quantized models) بحجم 30B إلى 70B.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>التخزين (Storage)&lt;/strong>: محرك أقراص PCIe Gen4 أو Gen5 NVMe SSD. يقلل من وقت تحميل النماذج التي تبلغ مساحتها عشرات الجيجابايت بشكل كبير.&lt;/li>
&lt;/ul>
&lt;h2 id="22-إعداد-wsl2-نظام-ويندوز-الفرعي-لنظام-لينكس-2">2.2 إعداد WSL2 (نظام ويندوز الفرعي لنظام لينكس 2)
&lt;/h2>&lt;p>تعمل العديد من أدوات واجهة المستخدم الرسومية (GUI) بشكل أصلي (Native) على ويندوز، ولكن WSL2 مفيد جدًا للتطوير باستخدام بايثون (Python)، وتجميع أحدث الأدوات، وإجراء الضبط الدقيق (LoRA Fine-tuning) الذي سيتم شرحه لاحقًا. في أحدث بيئة لـ Windows 11، يمكنك استخدام GPU (CUDA) بشفافية من WSL2 بمجرد تثبيت برنامج تشغيل NVIDIA على النظام المضيف.&lt;/p>
&lt;p>افتح PowerShell بصلاحيات المسؤول (Administrator) وقم بتشغيل ما يلي:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># تثبيت WSL2 وأحدث إصدار من Ubuntu&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-install&lt;/span> &lt;span class="n">-d&lt;/span> &lt;span class="n">Ubuntu&lt;/span>&lt;span class="p">-&lt;/span>&lt;span class="mf">24.04&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># تحديث النواة (Kernel)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">wsl&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-update&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بعد التثبيت، قم بتشغيل &lt;code>nvidia-smi&lt;/code> داخل وحدة تحكم WSL2، وإذا تم التعرف على GPU بشكل صحيح، فقد نجحت العملية.&lt;/p>
&lt;hr>
&lt;h1 id="3-بنية-نموذج-llm-المحلي-وآلية-الاستدلال-inference">3. بنية نموذج LLM المحلي وآلية الاستدلال (Inference)
&lt;/h1>&lt;p>من المفيد جدًا في استكشاف الأخطاء وإصلاحها وتحسين الأداء فهم كيفية قيام النموذج بإنشاء النص في بيئة محلية، وهيكله الداخلي.&lt;/p>
&lt;p>يوضح مخطط Mermaid التالي خط أنابيب (Pipeline) الاستدلال النموذجي لـ LLM المحلي.&lt;/p>
&lt;div class="mermaid">graph TD
User["إدخال المستخدم (الموجه/Prompt)"] --> Tokenizer["أداة الترميز (Tokenizer)"]
Tokenizer --> Embedding["طبقة التضمين (Embedding)"]
subgraph "كتلة المحول (Transformer Block) (x طبقات)"
Embedding --> Attn["الانتباه الذاتي (Self-Attention)"]
Attn --> KVCache["ذاكرة التخزين المؤقت KV (الاحتفاظ بالمفتاح/القيمة)"]
Attn --> FFN["شبكة التغذية الأمامية (FFN)"]
end
FFN --> Logits["حساب اللوجيت (Logits)"]
Logits --> Sampler["أداة أخذ العينات (Temperature, Top-K, Top-P)"]
Sampler --> OutputToken["الرمز المميز المخرج (Output Token)"]
OutputToken --> |"التوليد التلقائي الانحداري"| Tokenizer
OutputToken --> Decoder["أداة فك الترميز (Detokenizer)"]
Decoder --> FinalOutput["النص النهائي المخرج"]&lt;/div>
&lt;h2 id="31-مرحلتان-التعبئة-المسبقة-prefill-وفك-التشفير-decode">3.1 مرحلتان: التعبئة المسبقة (Prefill) وفك التشفير (Decode)
&lt;/h2>&lt;p>ينقسم إنشاء النص بواسطة LLM إلى مرحلتين تختلفان في الخصائص الحسابية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>مرحلة التعبئة المسبقة (معالجة الموجه - Prefill)&lt;/strong>: هي المرحلة التي يتم فيها معالجة وفهم موجه الإدخال (Prompt) بأكمله مرة واحدة. نظرًا لإمكانية الحوسبة المتوازية، ترتبط قدرة حساب GPU (FLOPS) بشكل مباشر بالسرعة. إذا كان الموجه طويلاً، فقد تستغرق هذه المرحلة بضع ثوانٍ.&lt;/li>
&lt;li>&lt;strong>مرحلة فك التشفير (توليد الرموز المميزة - Decode)&lt;/strong>: هي المرحلة التي يتم فيها التنبؤ برمز مميز واحد في كل مرة وتمريره إلى الإدخال التالي (التوليد التلقائي الانحداري - Autoregressive). نظرًا لأن الحوسبة المتوازية مقيدة في هذه المرحلة، فإن عرض النطاق الترددي لـ VRAM في GPU يصبح عنق الزجاجة الحاسم.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="4-حساب-استهلاك-vram-والفهم-الرياضي-لحجم-النموذج">4. حساب استهلاك VRAM والفهم الرياضي لحجم النموذج
&lt;/h1>&lt;p>لتحكم بشكل صحيح على &amp;ldquo;ما هو النموذج الذي سيعمل على جهاز الكمبيوتر الخاص بي؟&amp;quot;، تحتاج إلى فهم معادلة حساب VRAM. في حالة حدوث تراجع (Fallback) إلى ذاكرة النظام (RAM) بسبب نقص VRAM، ستنخفض سرعة الاستدلال بمقدار 10 إلى 100 مرة.&lt;/p>
&lt;h2 id="41-vram-الأساسي-بناء-على-حجم-المعلمة-parameter">4.1 VRAM الأساسي بناءً على حجم المعلمة (Parameter)
&lt;/h2>&lt;p>هو مقدار الذاكرة المطلوب لتحميل أوزان (Weights) النموذج في VRAM.
يتم حسابه باستخدام حجم النموذج $P$ (عدد المعلمات، الوحدة: 1 مليار = 1B) وعدد البايتات لكل معلمة $B$.&lt;/p>
$$
V_{base} = P \times B \quad \text{(GB)}
$$
&lt;p>على سبيل المثال، عند تحميل نموذج بـ 8B (8 مليارات) معلمة بتنسيق FP16 (فاصلة عائمة نصف الدقة، 16 بت = 2 بايت):&lt;/p>
$$
V_{base} = 8 \times 2 = 16 \text{ GB}
$$
&lt;p>بمعنى آخر، حتى مع وحدة معالجة رسومات تحتوي على 16 جيجابايت من VRAM، ستصل إلى الحد الأقصى تقريبًا بمجرد تحميل النموذج.&lt;/p>
&lt;h2 id="42-سحر-التكميم-quantization">4.2 سحر التكميم (Quantization)
&lt;/h2>&lt;p>وهنا يأتي دور &amp;ldquo;التكميم&amp;rdquo;. من خلال تقليل دقة المعلمات، يتم تصغير حجم النموذج بشكل كبير. في حالة التكميم الأكثر شيوعًا 4 بت (مثل: Q4_K_M)، يبلغ المتوسط حوالي 0.55 بايت لكل معلمة.&lt;/p>
$$
V_{base\_4bit} = 8 \times 0.55 = 4.4 \text{ GB}
$$
&lt;p>وبالتالي، إذا كان لديك 16 جيجابايت من VRAM، فيمكنك بسهولة تشغيل نموذج 8B بوجود مساحة إضافية كافية.&lt;/p>
&lt;h2 id="43-حساب-ذاكرة-التخزين-المؤقت-kv-إصدار-يدعم-gqa">4.3 حساب ذاكرة التخزين المؤقت KV (إصدار يدعم GQA)
&lt;/h2>&lt;p>أثناء الاستدلال، تستهلك &amp;ldquo;ذاكرة التخزين المؤقت KV&amp;rdquo; التي تحتفظ بالسياق الماضي VRAM. في أحدث النماذج مثل Llama 3، يتم استخدام GQA (الانتباه الاستعلامي المجمع - Grouped Query Attention) لتوفير الذاكرة.&lt;/p>
&lt;p>يمكن التعبير عن استهلاك ذاكرة التخزين المؤقت KV $V_{kv}$ (بالجيجابايت) بالصيغة الرياضية التالية:&lt;/p>
$$
V_{kv} = 2 \times b \times s \times l \times \left( \frac{h_{kv}}{h_q} \right) \times h_q \times d \times B_{kv} \div 10^9
$$
&lt;p>عند التبسيط، يمكن حسابها ببساطة باستخدام عدد رؤوس المفاتيح والقيم $h_{kv}$:&lt;/p>
$$
V_{kv} = 2 \times b \times s \times l \times h_{kv} \times d \times B_{kv} \div 10^9
$$
&lt;p>حيث أن:&lt;/p>
&lt;ul>
&lt;li>$b$: حجم الدفعة (عادة 1 للاستخدام الشخصي المحلي)&lt;/li>
&lt;li>$s$: طول التسلسل (طول السياق، مثال: 8192)&lt;/li>
&lt;li>$l$: عدد الطبقات (مثال: 32)&lt;/li>
&lt;li>$h_{kv}$: عدد رؤوس KV (مثال: 8)&lt;/li>
&lt;li>$d$: عدد الأبعاد لكل رأس (مثال: 128)&lt;/li>
&lt;li>$B_{kv}$: عدد البايتات لذاكرة التخزين المؤقت KV (2 إذا كان FP16)&lt;/li>
&lt;/ul>
&lt;p>مثال للحساب (Llama 3 8B، سياق 8192، ذاكرة تخزين مؤقت FP16):
$V_{kv} = 2 \times 1 \times 8192 \times 32 \times 8 \times 128 \times 2 \div 10^9 \approx 1.07 \text{ GB}$&lt;/p>
&lt;p>يرجى ملاحظة أنه كلما زاد طول السياق $s$، زادت الحاجة إلى VRAM بشكل خطي.&lt;/p>
&lt;hr>
&lt;h1 id="5-الممارسة-1-إعداد-أسرع-وأقصر-باستخدام-ollama">5. الممارسة 1: إعداد أسرع وأقصر باستخدام Ollama
&lt;/h1>&lt;p>بمجرد فهم النظرية، دعنا نقم بتشغيل LLM فعليًا على بيئة ويندوز.
اعتبارًا من عام 2026، فإن الأداة الأكثر سهولة في الاستخدام هي &amp;ldquo;Ollama&amp;rdquo;. فهي توفر واجهة سطر أوامر (CLI) بديهية تشبه Docker.&lt;/p>
&lt;h2 id="51-التثبيت-والتشغيل">5.1 التثبيت والتشغيل
&lt;/h2>&lt;ol>
&lt;li>قم بتنزيل مثبت ويندوز من &lt;a class="link" href="https://ollama.com/" target="_blank" rel="noopener"
>موقع Ollama الرسمي&lt;/a> وقم بتشغيله.&lt;/li>
&lt;li>افتح PowerShell وأدخل الأمر التالي. هنا، سنستخدم &lt;code>llama3:8b&lt;/code> الذي يدعم اللغة اليابانية.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ollama&lt;/span> &lt;span class="n">run&lt;/span> &lt;span class="n">llama3&lt;/span>&lt;span class="err">:&lt;/span>&lt;span class="n">8b&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في أول تشغيل، سيتم تنزيل النموذج. بمجرد الانتهاء، يمكنك التفاعل معه مباشرة في الجهاز الطرفي (Terminal).&lt;/p>
&lt;h2 id="52-إنشاء-ذكاء-اصطناعي-مخصص-باستخدام-modelfile">5.2 إنشاء ذكاء اصطناعي مخصص باستخدام Modelfile
&lt;/h2>&lt;p>يمكنك بسهولة إنشاء ذكاء اصطناعي بشخصية (Persona) محددة. قم بإنشاء &lt;code>Modelfile&lt;/code> في أي مكان تريده.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">FROM llama3:8b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">SYSTEM &amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">أنت مهندس برمجيات أول ممتاز جدًا.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">يرجى الإجابة على أسئلة المستخدم بشكل منطقي وموجز، مع تقديم أمثلة التعليمات البرمجية دائمًا.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER temperature 0.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER num_ctx 8192
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>قم ببناء النموذج المخصص الخاص بك وتشغيله بالأوامر التالية:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ollama&lt;/span> &lt;span class="n">create&lt;/span> &lt;span class="n">SeniorDev&lt;/span> &lt;span class="o">-f&lt;/span> &lt;span class="p">./&lt;/span>&lt;span class="n">Modelfile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ollama&lt;/span> &lt;span class="n">run&lt;/span> &lt;span class="n">SeniorDev&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="53-الاستخدام-من-التطبيقات-الخارجية-محرر-الذكاء-الاصطناعي">5.3 الاستخدام من التطبيقات الخارجية (محرر الذكاء الاصطناعي)
&lt;/h2>&lt;p>تكشف Ollama عن نقطة نهاية API متوافقة مع OpenAI على &lt;code>http://localhost:11434&lt;/code>.
من خلال تحديد عنوان URL هذا في إعدادات الخلفية (Backend) لإضافات VS Code مثل Cursor و Continue.dev، وتحديد اسم النموذج كـ &lt;code>SeniorDev&lt;/code> أو ما شابه، ستحصل على مساعد تشفير (Coding) محلي قوي ومجاني.&lt;/p>
&lt;hr>
&lt;h1 id="6-الممارسة-2-ضبط-الأداء-الأقصى-باستخدام-llamacpp">6. الممارسة 2: ضبط الأداء الأقصى باستخدام llama.cpp
&lt;/h1>&lt;p>إذا كنت ترغب في إجراء إدارة دقيقة للذاكرة أو تجربة أحدث التنسيقات (مثل EXL2 وتكميم IQ) بسرعة، فسوف تتفاعل مباشرة مع المحرك الأساسي &lt;code>llama.cpp&lt;/code>.&lt;/p>
&lt;h2 id="61-خطوات-بناء-llamacpp">6.1 خطوات بناء llama.cpp
&lt;/h2>&lt;p>في بيئة ويندوز، من الأفضل بناءه من المصدر باستخدام CUDA Toolkit و CMake.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">git&lt;/span> &lt;span class="n">clone&lt;/span> &lt;span class="n">https&lt;/span>&lt;span class="err">:&lt;/span>&lt;span class="p">//&lt;/span>&lt;span class="n">github&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="p">/&lt;/span>&lt;span class="n">ggerganov&lt;/span>&lt;span class="p">/&lt;/span>&lt;span class="n">llama&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nb">cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd &lt;/span>&lt;span class="n">llama&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nb">cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">&lt;/span>&lt;span class="n">mkdir&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd &lt;/span>&lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># التهيئة والتجميع ليكون متوافقًا مع CUDA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cmake&lt;/span> &lt;span class="p">..&lt;/span> &lt;span class="n">-DLLAMA_CUBLAS&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="n">ON&lt;/span> &lt;span class="n">-DBUILD_SHARED_LIBS&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="n">OFF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cmake&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-build&lt;/span> &lt;span class="p">.&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-config&lt;/span> &lt;span class="n">Release&lt;/span> &lt;span class="n">-j&lt;/span> &lt;span class="mf">16&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="62-التشغيل-المتقدم-في-وضع-الخادم">6.2 التشغيل المتقدم في وضع الخادم
&lt;/h2>&lt;p>استخدم &lt;code>llama-server.exe&lt;/code> الذي تم بناؤه لاستضافة النموذج.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="p">.\&lt;/span>&lt;span class="n">bin&lt;/span>&lt;span class="p">\&lt;/span>&lt;span class="n">Release&lt;/span>&lt;span class="p">\&lt;/span>&lt;span class="nb">llama-server&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">exe&lt;/span> &lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">-&lt;/span>&lt;span class="n">-model&lt;/span> &lt;span class="s2">&amp;#34;C:\models\Llama-3-8B-Instruct.Q4_K_M.gguf&amp;#34;&lt;/span> &lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">-&lt;/span>&lt;span class="n">-ctx-size&lt;/span> &lt;span class="mf">8192&lt;/span> &lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">-&lt;/span>&lt;span class="n">-n-gpu-layers&lt;/span> &lt;span class="mf">99&lt;/span> &lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">-&lt;/span>&lt;span class="n">-threads&lt;/span> &lt;span class="mf">8&lt;/span> &lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">-&lt;/span>&lt;span class="n">-flash-attn&lt;/span> &lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">-&lt;/span>&lt;span class="n">-port&lt;/span> &lt;span class="mf">8080&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>&lt;code>--n-gpu-layers 99&lt;/code>: نقل كل الطبقات الممكنة إلى VRAM الخاص بـ GPU.&lt;/li>
&lt;li>&lt;code>--flash-attn&lt;/code>: تمكين FlashAttention 3 لتحسين سرعة الاستدلال وتقليل استهلاك VRAM لذاكرة التخزين المؤقت KV.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="7-واجهة-المستخدم-الرسومية-gui-بناء-lm-studio-و-rag-المحلي">7. واجهة المستخدم الرسومية (GUI): بناء LM Studio و RAG المحلي
&lt;/h1>&lt;p>إذا كنت لا تفضل استخدام سطر الأوامر، أو إذا كنت ترغب في إجراء التوليد المعزز بالاسترجاع (RAG) بشكل بديهي، فاستخدم واجهة مستخدم رسومية (GUI).&lt;/p>
&lt;h2 id="71-lm-studio">7.1 LM Studio
&lt;/h2>&lt;p>يعد LM Studio تطبيقًا رائعًا يجمع بين البحث عن النماذج، والتنزيل، والتحقق المسبق من متطلبات النظام، وواجهة مستخدم (UI) للدردشة في مكان واحد. بضغطة زر &amp;ldquo;Local Server&amp;rdquo; داخل التطبيق، سيتم تشغيل واجهة برمجة تطبيقات (API) متوافقة مع OpenAI.&lt;/p>
&lt;h2 id="72-بنية-rag-باستخدام-anythingllm">7.2 بنية RAG باستخدام AnythingLLM
&lt;/h2>&lt;p>هذا هو المخطط المعماري لبيئة RAG التي تسمح بقراءة المستندات الداخلية للشركة والمذكرات الشخصية.&lt;/p>
&lt;div class="mermaid">graph LR
Document["المستند (PDF, MD)"] --> Chunking["تقسيم إلى كتل (Chunking)"]
Chunking --> EmbedModel["نموذج التضمين (Embedding Model)"]
EmbedModel --> VectorDB["قاعدة بيانات المتجهات (Vector Database)"]
UserQuery["سؤال المستخدم"] --> EmbedQuery["تضمين السؤال"]
EmbedQuery --> VectorDB
VectorDB --> |"بحث عن التشابه"| RetrievedDocs["استخراج المستندات ذات الصلة"]
UserQuery --> PromptBuilder["توليد الموجه (Prompt)"]
RetrievedDocs --> PromptBuilder
PromptBuilder --> LocalLLM["نموذج LLM محلي"]
LocalLLM --> Answer["الإجابة النهائية"]&lt;/div>
&lt;p>باستخدام إصدار سطح المكتب من AnythingLLM (لويندوز)، يمكنك تحديد Ollama (لـ LLM والتضمين) من شاشة الإعدادات، وإعداده لاستخدام VectorDB محلي (LanceDB)، وستكتمل هذه البنية في غضون بضع دقائق. هذه هي ولادة الذكاء الاصطناعي الخاص الذي لا يرسل البيانات إلى الخارج على الإطلاق.&lt;/p>
&lt;hr>
&lt;h1 id="8-الضبط-الدقيق-lora-على-windows-wsl2">8. الضبط الدقيق (LoRA) على Windows WSL2
&lt;/h1>&lt;p>لا يقتصر الأمر على التشغيل المحلي فحسب، بل إذا كنت ترغب في جعل النموذج أكثر ذكاءً باستخدام بياناتك الخاصة، فيمكنك إجراء الضبط الدقيق (Fine-tuning) باستخدام LoRA (التكيف منخفض الرتبة - Low-Rank Adaptation). اعتبارًا من عام 2026، وبفضل مكتبة تسمى &amp;ldquo;Unsloth&amp;rdquo;، يمكنك إكمال تدريب نموذج 8B في بضع ساعات حتى مع 16 جيجابايت من VRAM في بيئة Windows WSL2.&lt;/p>
&lt;p>قم بتشغيل الأوامر التالية داخل Ubuntu في WSL2 لإعداد البيئة:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">conda create --name unsloth_env &lt;span class="nv">python&lt;/span>&lt;span class="o">=&lt;/span>3.11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">conda activate unsloth_env
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install &lt;span class="s2">&amp;#34;unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install --no-deps trl peft accelerate bitsandbytes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>تعمل Unsloth على تحسين أنوية CUDA (CUDA kernels) إلى أقصى حد، وبالمقارنة مع مكتبة Hugging Face القياسية، فإن سرعة التدريب تزيد بحوالي الضعف، وينخفض استهلاك VRAM إلى النصف تقريبًا. بمجرد فتح Jupyter Notebook وتحميل مجموعة البيانات (بتنسيق JSONL)، يمكن إجراء التدريب لعدة عصور (Epochs) باستخدام أجهزة مثل RTX 4060 Ti مع 12 جيجابايت إلى 16 جيجابايت من VRAM.&lt;/p>
&lt;hr>
&lt;h1 id="9-استكشاف-أخطاء-الأداء-وإصلاحها">9. استكشاف أخطاء الأداء وإصلاحها
&lt;/h1>&lt;p>فيما يلي المشكلات الشائعة والحلول الخاصة بها.&lt;/p>
&lt;h3 id="1-سرعة-الاستدلال-بطيئة-للغاية-1-إلى-2-رمز--ثانية">1. سرعة الاستدلال بطيئة للغاية (1 إلى 2 رمز / ثانية)
&lt;/h3>&lt;p>&lt;strong>السبب&lt;/strong>: النموذج لا يتناسب مع VRAM وتم تحميله على ذاكرة النظام (RAM).
&lt;strong>الحل&lt;/strong>: تحقق من &amp;ldquo;ذاكرة GPU المخصصة&amp;rdquo; في إدارة المهام. إذا وصلت إلى الحد الأقصى، فقم بتقليل حجم السياق (&lt;code>-c&lt;/code>)، أو استخدم نموذج تكميم بعدد بتات أقل (مثل Q4_K_M).&lt;/p>
&lt;h3 id="2-خطأ-cuda-out-of-memory">2. خطأ &amp;ldquo;CUDA out of memory&amp;rdquo;
&lt;/h3>&lt;p>&lt;strong>السبب&lt;/strong>: تم استنفاد VRAM بالكامل. يحدث هذا بشكل خاص عندما تطول المحادثة وتتضخم ذاكرة التخزين المؤقت KV.
&lt;strong>الحل&lt;/strong>: قم بتقييد قيمة &lt;code>num_ctx&lt;/code> بشكل مقصود في حالة Ollama، أو قيمة &lt;code>-c&lt;/code> في حالة llama.cpp.&lt;/p>
&lt;h3 id="3-توليد-اللغة-مثل-اليابانية-أو-العربية-غريب">3. توليد اللغة (مثل اليابانية أو العربية) غريب
&lt;/h3>&lt;p>&lt;strong>السبب&lt;/strong>: عدم تطابق قالب الموجه (Prompt template)، أو النموذج غير مدعوم.
&lt;strong>الحل&lt;/strong>: استخدم نموذجًا يحتوي اسمه على &lt;code>Instruct&lt;/code>، وتأكد من تحديد القالب الصحيح (مثل تنسيق ChatML أو Llama3) الذي حدده منشئ النموذج في الأداة.&lt;/p>
&lt;hr>
&lt;h1 id="10-الخلاصة-والآفاق-المستقبلية">10. الخلاصة والآفاق المستقبلية
&lt;/h1>&lt;p>في عام 2026، لم يعد بناء نماذج LLM المحلية في بيئة ويندوز حكرًا على عدد قليل من المهندسين فقط. بفضل تحول تنسيق GGUF إلى معيار أساسي، وظهور أنظمة بيئية محسّنة مثل Ollama و LM Studio، والتحسينات على مستوى الأجهزة (Hardware) مثل FlashAttention، يمكن لأي شخص الآن بسهولة الحصول على بيئة ذكاء اصطناعي بمستوى الشركات (Enterprise-grade).&lt;/p>
&lt;p>يرجى الاستفادة من النقاط التالية المشروحة في هذا المقال:&lt;/p>
&lt;ol>
&lt;li>استخدم &lt;strong>الحساب الرياضي لـ VRAM&lt;/strong> لاختيار حجم النموذج ومستوى التكميم المناسبين لمنطق مواصفات جهاز الكمبيوتر الخاص بك.&lt;/li>
&lt;li>استخدم &lt;strong>Ollama&lt;/strong> لإعداد بيئة بأسرع وقت، وربطها مع محرر الذكاء الاصطناعي لتحسين الإنتاجية بشكل كبير.&lt;/li>
&lt;li>استخدم التحكم المتقدم في المعلمات من خلال &lt;strong>llama.cpp&lt;/strong> لاستخراج أقصى أداء ممكن للأجهزة.&lt;/li>
&lt;li>قم ببناء نظام RAG محلي آمن للتعامل مع البيانات السرية باستخدام &lt;strong>AnythingLLM&lt;/strong>.&lt;/li>
&lt;li>استفد من &lt;strong>Unsloth (WSL2)&lt;/strong> لتطوير وتدريب ذكاء اصطناعي مخصص يمتلك معرفتك المتخصصة الخاصة.&lt;/li>
&lt;/ol>
&lt;p>لم يعد مصطلح &amp;ldquo;إضفاء الطابع الديمقراطي&amp;rdquo; على الذكاء الاصطناعي مجرد كلمة طنانة (Buzzword)، بل أصبح نظامًا واقعيًا يعمل على سطح مكتب ويندوز الخاص بك. تحرر من تكاليف استخدام واجهات برمجة التطبيقات السحابية وخطر تسرب المعلومات، وادخل الآن إلى عالم الذكاء الاصطناعي الخاص القوي والحر.&lt;/p></description></item></channel></rss>