<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AI on kenji.blog</title><link>http://kenji.blog/ar/categories/ai/</link><description>Recent content in AI on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 18:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/categories/ai/index.xml" rel="self" type="application/rss+xml"/><item><title>أمثلة تطبيقية وأكواد برمجية لأحدث واجهات برمجة تطبيقات Microsoft.Windows.AI</title><link>http://kenji.blog/ar/p/microsoft-windows-ai-api-guide/</link><pubDate>Fri, 11 Sep 2026 18:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/microsoft-windows-ai-api-guide/</guid><description>&lt;img src="http://kenji.blog/p/microsoft-windows-ai-api-guide/img/eyecatch.jpg" alt="Featured image of post أمثلة تطبيقية وأكواد برمجية لأحدث واجهات برمجة تطبيقات Microsoft.Windows.AI" />&lt;h1 id="أمثلة-تطبيقية-وأكواد-برمجية-لأحدث-واجهات-برمجة-تطبيقات-microsoftwindowsai-استكشاف-أعماق-windows-copilot-runtime">أمثلة تطبيقية وأكواد برمجية لأحدث واجهات برمجة تطبيقات Microsoft.Windows.AI: استكشاف أعماق Windows Copilot Runtime
&lt;/h1>&lt;h2 id="1-مقدمة-عصر-جديد-لـ-windows-يتم-فيه-دمج-الذكاء-الاصطناعي-أصليا">1. مقدمة: عصر جديد لـ Windows يتم فيه دمج الذكاء الاصطناعي أصلياً
&lt;/h2>&lt;p>في السنوات الأخيرة، كان تطور تقنية الذكاء الاصطناعي ملحوظًا، وهناك تحول سريع في النموذج من استخدام النماذج اللغوية الكبيرة (LLMs) في السحابة إلى استنتاج الذكاء الاصطناعي على الأجهزة الطرفية (الحواسيب المحلية). في قلب هذا التحول يوجد &amp;ldquo;Windows Copilot Runtime&amp;rdquo; الذي توفره Microsoft لنظام التشغيل Windows 11، وواجهة برمجة تطبيقات &amp;ldquo;Microsoft.Windows.AI&amp;rdquo; للتحكم فيه.&lt;/p>
&lt;p>تطوير التطبيقات باستخدام واجهات برمجة التطبيقات السحابية (مثل OpenAI وAzure OpenAI) سهل، ولكنه يأتي بتحديات مثل زمن الوصول، الخصوصية، والتكاليف المستمرة. من ناحية أخرى، من خلال تشغيل نماذج الذكاء الاصطناعي محليًا، من الممكن تحقيق تطبيقات ذات زمن وصول منخفض للغاية تعمل حتى دون اتصال بالإنترنت، دون السماح للبيانات السرية بمغادرة الجهاز.&lt;/p>
&lt;p>في هذه المقالة، سنشرح بالتفصيل كيفية تنفيذ ميزات الذكاء الاصطناعي المحلي، والتي ستصبح ضرورية في تطوير تطبيقات Windows في المستقبل، بدءًا من البنية وصولاً إلى ضبط الأداء، مع أمثلة عملية بأكواد C# وC++. لن نكتفي باستدعاء واجهة برمجة التطبيقات فحسب، بل سنتعمق في التفاصيل التقنية المتقدمة مثل الاستفادة من الأجهزة الأساسية (NPU وGPU) والتكامل مع DirectML.&lt;/p>
&lt;h2 id="2-النظرة-العامة-على-بنية-windows-copilot-runtime">2. النظرة العامة على بنية Windows Copilot Runtime
&lt;/h2>&lt;p>Windows Copilot Runtime عبارة عن حزمة ذكاء اصطناعي مصممة للسماح للمطورين بدمج نماذج الذكاء الاصطناعي بسهولة في Windows وتحقيق أقصى قدر من الأداء. يعمل هذا وقت التشغيل (Runtime) على تجريد تسريع الأجهزة على مستوى نظام التشغيل (OS) ويوفر واجهة موحدة للمطورين.&lt;/p>
&lt;div class="mermaid">graph TD
App["تطبيقات Windows (C# / C++)"] --> API["واجهات برمجة تطبيقات Microsoft.Windows.AI"]
App --> ORT["ONNX Runtime"]
API --> WCR["Windows Copilot Runtime (طبقة نظام التشغيل)"]
WCR --> SLM["النماذج المحلية (Phi-Silica، وغيرها)"]
ORT --> DML["مزود تنفيذ DirectML"]
SLM --> DML
DML --> DXCore["DXCore / DirectX 12"]
DXCore --> NPU["NPU (وحدة المعالجة العصبية)"]
DXCore --> GPU["GPU (وحدة معالجة الرسومات)"]
DXCore --> CPU["CPU"]&lt;/div>
&lt;p>كما يوضح مخطط البنية أعلاه، يمكن للتطبيقات الوصول مباشرة إلى النماذج اللغوية الصغيرة (SLM: مثل Phi-Silica) المدمجة في نظام التشغيل باستخدام واجهة برمجة التطبيقات &lt;code>Microsoft.Windows.AI&lt;/code> عالية المستوى. أيضًا، عند استخدام نماذج مخصصة، يمكن استخدام تسريع الأجهزة صراحةً من خلال ONNX Runtime وDirectML. نظرًا لأن طبقة نظام التشغيل تعمل على تحسين توزيع أعباء العمل على وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU) ووحدة المعالجة العصبية (NPU)، يمكن للمطورين بناء تطبيقات ذكاء اصطناعي عالية الأداء دون الحاجة إلى القلق العميق بشأن اختلافات الأجهزة.&lt;/p>
&lt;h2 id="3-تسريع-الأجهزة-والالتقييم-الرياضي-لـ-npu">3. تسريع الأجهزة والالتقييم الرياضي لـ NPU
&lt;/h2>&lt;p>تم تجهيز أحدث أجهزة Copilot+ PC بـ NPU (وحدة المعالجة العصبية)، وهي معالجات متخصصة في معالجة الذكاء الاصطناعي. يتم تقييم أداء NPU عمومًا بـ TOPS (تريليون عملية في الثانية).&lt;/p>
&lt;p>في استنتاج نماذج الذكاء الاصطناعي، وخاصة قدرة حساب ضرب المصفوفات (GEMM: General Matrix Multiply)، هي التي تحدد الإنتاجية. يُقدر الحد الأقصى للأداء النظري $P_{\text{peak}}$ للأجهزة بالصيغة التالية.&lt;/p>
$$
P_{\text{peak}} = f \times N_{\text{cores}} \times N_{\text{MACs/core}} \times 2
$$
&lt;p>حيث:&lt;/p>
&lt;ul>
&lt;li>$f$ هو تردد ساعة NPU (بهرتز)&lt;/li>
&lt;li>$N_{\text{cores}}$ هو عدد النوى في NPU&lt;/li>
&lt;li>$N_{\text{MACs/core}}$ هو عدد وحدات MAC (الضرب والتراكم) لكل نواة&lt;/li>
&lt;li>الـ $2$ الأخير يرجع إلى أن عملية MAC واحدة تُحسب كعمليتين (الضرب والجمع) (FLOPs/OPs).&lt;/li>
&lt;/ul>
&lt;p>على سبيل المثال، بالنسبة لـ NPU بتردد 1.5 جيجاهرتز و4 نوى، وكل نواة تحتوي على 4096 وحدة MAC،
&lt;/p>
$$
P_{\text{peak}} = 1.5 \times 10^9 \times 4 \times 4096 \times 2 \approx 49.15 \text{ TOPS}
$$
&lt;p>
كما يظهر رياضيًا، هذا الأداء يتجاوز متطلبات 40 TOPS لأجهزة Copilot+ PC في Windows 11.&lt;/p>
&lt;p>بالإضافة إلى ذلك، فإن استنتاج نماذج الذكاء الاصطناعي، وخاصة نماذج LLM (مرحلة فك التشفير)، يميل إلى أن يكون &lt;strong>مقيدًا بالذاكرة (Memory-Bound)&lt;/strong>. يُحسب عرض النطاق الترددي النظري $BW$ لذاكرة النظام على النحو التالي.&lt;/p>
$$
BW = f_{\text{mem}} \times W_{\text{bus}} \times \frac{2}{8}
$$
&lt;p>في حالة ذاكرة LPDDR5x-8533 ($f_{\text{mem}} = 8533 \text{ MT/s}$) وناقل 128 بت ($W_{\text{bus}} = 128$)، سيكون عرض النطاق الترددي حوالي $136 \text{ GB/s}$. في تحسين تطبيقات الذكاء الاصطناعي، من المهم كيفية الحفاظ على عرض النطاق الترددي هذا، وتصبح عملية تكميم النموذج (Quantization)، التي سيتم وصفها لاحقًا، ضرورية.&lt;/p>
&lt;h2 id="4-إعداد-بيئة-التطوير">4. إعداد بيئة التطوير
&lt;/h2>&lt;p>لاستخدام أحدث واجهات برمجة تطبيقات الذكاء الاصطناعي لـ Windows، تحتاج إلى إعداد البيئة وسلسلة الأدوات التالية.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>نظام التشغيل&lt;/strong>: Windows 11 الإصدار 24H2 أو أحدث (يُوصى بشدة بالأجهزة المزودة بـ NPU والتي تلبي متطلبات Copilot+ PC)&lt;/li>
&lt;li>&lt;strong>حزمة تطوير البرامج (SDK)&lt;/strong>: Windows App SDK (إصدار يدعم امتداد الذكاء الاصطناعي v1.5 أو أحدث)&lt;/li>
&lt;li>&lt;strong>بيئة التطوير&lt;/strong>: Visual Studio 2022 (v17.10 أو أحدث)، مع أعباء عمل التطوير الأصلي باستخدام C++ وتطوير سطح مكتب .NET&lt;/li>
&lt;li>&lt;strong>الحزم&lt;/strong>: قم بتثبيت &lt;code>Microsoft.Windows.AI&lt;/code> و &lt;code>Microsoft.ML.OnnxRuntime.DirectML&lt;/code> عبر NuGet&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;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-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- مثال على إعداد .csproj --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;ItemGroup&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;PackageReference&lt;/span> &lt;span class="na">Include=&lt;/span>&lt;span class="s">&amp;#34;Microsoft.Windows.AI&amp;#34;&lt;/span> &lt;span class="na">Version=&lt;/span>&lt;span class="s">&amp;#34;1.0.0-preview1&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;PackageReference&lt;/span> &lt;span class="na">Include=&lt;/span>&lt;span class="s">&amp;#34;Microsoft.WindowsAppSDK&amp;#34;&lt;/span> &lt;span class="na">Version=&lt;/span>&lt;span class="s">&amp;#34;1.5.240311000&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;PackageReference&lt;/span> &lt;span class="na">Include=&lt;/span>&lt;span class="s">&amp;#34;Microsoft.ML.OnnxRuntime.DirectML&amp;#34;&lt;/span> &lt;span class="na">Version=&lt;/span>&lt;span class="s">&amp;#34;1.17.1&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/ItemGroup&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="5-التعمق-1-استخدام-النماذج-اللغوية-المحلية-phi-silica-باستخدام-c">5. [التعمق 1] استخدام النماذج اللغوية المحلية (Phi-Silica) باستخدام C#
&lt;/h2>&lt;p>يتضمن Windows Copilot Runtime نموذج لغوي صغير عالي الكفاءة يُسمى &amp;ldquo;Phi-Silica&amp;rdquo; طورته Microsoft كمكون قياسي في نظام التشغيل. يتيح ذلك معالجة متقدمة للغة الطبيعية (تلخيص النصوص، إنشاء الأكواد، روبوتات الدردشة) في بيئة غير متصلة بالإنترنت، دون الحاجة إلى تنزيل نماذج بحجم جيجابايت من الشبكة.&lt;/p>
&lt;p>فيما يلي نموذج كود متقدم لإنشاء روبوت دردشة ذكاء اصطناعي باستخدام C# ومساحة الأسماء &lt;code>Microsoft.Windows.AI.Generative&lt;/code>. وهو يدعم استجابات البث المتدفق ويقوم بإنشاء نصوص في الوقت الفعلي دون حظر خيط واجهة المستخدم (UI thread).&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">System&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">System.Text&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">System.Threading&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">System.Threading.Tasks&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">Microsoft.Windows.AI.Generative&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">namespace&lt;/span> &lt;span class="nn">WindowsAI.Sample&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="kd">public&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">LocalLanguageModelService&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="kd">private&lt;/span> &lt;span class="n">LanguageModel&lt;/span> &lt;span class="n">_languageModel&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">private&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">_isInitialized&lt;/span> &lt;span class="p">=&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cs">/// &amp;lt;summary&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cs">/// يقوم بتهيئة النموذج اللغوي. يتحقق من توفر NPU ويحمل النموذج على أفضل جهاز.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cs">/// &amp;lt;/summary&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">async&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">InitializeAsync&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="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">_isInitialized&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&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">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;التحقق من متطلبات النظام وتوافر نموذج الذكاء الاصطناعي المحلي (Phi-Silica)...&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="kt">var&lt;/span> &lt;span class="n">availability&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">LanguageModel&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">CheckAvailabilityAsync&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">availability&lt;/span> &lt;span class="p">!=&lt;/span> &lt;span class="n">LanguageModelAvailability&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Available&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="k">throw&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">InvalidOperationException&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">$&amp;#34;نموذج الذكاء الاصطناعي المحلي غير متاح حاليًا. الحالة: {availability}&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">// إنشاء مثيل النموذج (في هذا الوقت يتم التعيين إلى مساحة الذاكرة وتهيئة NPU)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">_languageModel&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">LanguageModel&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">CreateAsync&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">_isInitialized&lt;/span> &lt;span class="p">=&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;تمت تهيئة النموذج اللغوي. تسريع الأجهزة عبر DirectML نشط.&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="cs">/// &amp;lt;summary&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cs">/// يستقبل مطالبة المستخدم ويولد استجابة عبر البث المتدفق.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cs">/// &amp;lt;/summary&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">async&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">GenerateResponseStreamAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">string&lt;/span> &lt;span class="n">prompt&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&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="k">if&lt;/span> &lt;span class="p">(!&lt;/span>&lt;span class="n">_isInitialized&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">InitializeAsync&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">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">$&amp;#34;\n[إدخال المستخدم]: {prompt}\n[مساعد الذكاء الاصطناعي]: &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">// إعداد المعلمات الفائقة (Hyperparameters) للإنشاء&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">options&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">LanguageModelOptions&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">Temperature&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="m">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">TopP&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="m">0.9f&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MaxTokens&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="m">2048&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">RepetitionPenalty&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="m">1.1f&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">// بناء سياق المحادثة&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">context&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">LanguageModelContext&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">AddSystemMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;أنت مساعد ذكاء اصطناعي متقدم تعمل مباشرة على وحدة NPU المحلية لنظام Windows. يرجى التفكير منطقياً خطوة بخطوة والإجابة بإيجاز.&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">context&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">AddUserMessage&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="k">try&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">// استدعاء واجهة برمجة تطبيقات الاستنتاج عبر البث&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">responseStream&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">_languageModel&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GenerateResponseStreamAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">options&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">// التكرار غير المتزامن للقطع (chunks) التي يتم إرجاعها كـ IAsyncEnumerable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="k">foreach&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">var&lt;/span> &lt;span class="n">chunk&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">responseStream&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WithCancellation&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cancellationToken&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">// إخراج الرموز (القطع) المُنشأة إلى وحدة التحكم في الوقت الفعلي&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// بالنسبة لتطبيقات واجهة المستخدم (UI)، استخدم DispatcherQueue هنا لعكسها في TextBox وما إلى ذلك&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunk&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Text&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">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&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="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">OperationCanceledException&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">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;\n[تم إلغاء الإنشاء بواسطة المستخدم أو النظام]&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="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Exception&lt;/span> &lt;span class="n">ex&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">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">$&amp;#34;\n[حدث خطأ فادح: {ex.Message}]&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="51-شرح-البنية-في-تنفيذ-c">5.1 شرح البنية في تنفيذ C#
&lt;/h3>&lt;p>يكمن جوهر هذا الكود في التحقق قبل التنفيذ باستخدام &lt;code>LanguageModel.CheckAvailabilityAsync()&lt;/code> والبث غير المتزامن باستخدام &lt;code>GenerateResponseStreamAsync&lt;/code>. عندما يتلقى Copilot Runtime الذي يعمل في خلفية نظام التشغيل استدعاء واجهة برمجة التطبيقات هذا، فإنه يبدأ تشغيل ONNX Runtime داخليًا ويختار أفضل موفر تنفيذ (Execution Provider) (DirectML + NPU في العديد من أجهزة الكمبيوتر الحديثة) وفقًا لتكوين النظام.&lt;/p>
&lt;p>يمكن للمطورين دمج أحدث خطوط أنابيب استنتاج الذكاء الاصطناعي في تطبيقاتهم ببضعة أسطر من كود C# دون الحاجة إلى القلق بشأن شكل موتر النموذج (Tensor Shape)، أو تنفيذ المُرمِّز (Tokenizer)، أو إدارة ذاكرة التخزين المؤقت KV (KV Cache).&lt;/p>
&lt;h2 id="6-التعمق-2-الاستنتاج-عالي-السرعة-للنماذج-المخصصة-باستخدام-c-و-directml">6. [التعمق 2] الاستنتاج عالي السرعة للنماذج المخصصة باستخدام C++ و DirectML
&lt;/h2>&lt;p>عند التعامل مع مجالات معينة (تجزئة الصور الخاصة، التعرف على الصوت، نماذج اكتشاف الكائنات المخصصة، إلخ) التي لا يمكن تغطيتها بواسطة النماذج اللغوية القياسية لنظام التشغيل فقط، يحتاج المطورون إلى معالجة ONNX Runtime وDirectML مباشرة، والتي تقع في الطبقات الدنيا من &lt;code>Microsoft.Windows.AI&lt;/code>.&lt;/p>
&lt;p>باستخدام C++، يمكنك تحسين تخصيص الذاكرة إلى أقصى حد واستخراج أقصى أداء من NPU/GPU. فيما يلي تنفيذ أساسي لخط أنابيب التهيئة والاستنتاج المتقدم لتشغيل النماذج المخصصة بصيغة ONNX (مثل YOLOv8) في C++ باستخدام DirectML.&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;span class="lnt">94
&lt;/span>&lt;span class="lnt">95
&lt;/span>&lt;span class="lnt">96
&lt;/span>&lt;span class="lnt">97
&lt;/span>&lt;span class="lnt">98
&lt;/span>&lt;span class="lnt">99
&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;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">#include&lt;/span> &lt;span class="cpf">&amp;lt;onnxruntime_cxx_api.h&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;dml_provider_factory.h&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="k">class&lt;/span> &lt;span class="nc">CustomVisionAIProcessor&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Env&lt;/span> &lt;span class="n">env&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Session&lt;/span> &lt;span class="n">session&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="k">nullptr&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">AllocatorWithDefaultOptions&lt;/span> &lt;span class="n">allocator&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">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CustomVisionAIProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">wstring&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">modelPath&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">env&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ORT_LOGGING_LEVEL_WARNING&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;VisionAIProcessor&amp;#34;&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">SessionOptions&lt;/span> &lt;span class="n">sessionOptions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تحسين عدد الخيوط (Threads)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sessionOptions&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">SetIntraOpNumThreads&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="c1">// تعيين مستوى تحسين الرسم البياني (Graph Optimization Level) إلى الحد الأقصى
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sessionOptions&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">SetGraphOptimizationLevel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">GraphOptimizationLevel&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ORT_ENABLE_ALL&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. إضافة مزود تنفيذ DirectML (DML EP)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// device_id = 0 هو المحول الافتراضي الموصى به للنظام (NPU أو GPU عالي الأداء)
&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="n">OrtApi&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">ortApi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">GetApi&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">OrtDmlApi&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dmlApi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">nullptr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">OrtStatus&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ortApi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetExecutionProviderApi&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;DML&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ORT_API_VERSION&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">reinterpret_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="o">**&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">dmlApi&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">status&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">dmlApi&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">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ThrowOnError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dmlApi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">SessionOptionsAppendExecutionProvider_DML&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sessionOptions&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="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;[معلومات] تم إرفاق مزود تنفيذ DirectML بنجاح.&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="p">}&lt;/span> &lt;span class="k">else&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;[تحذير] فشل الحصول على واجهة برمجة تطبيقات DirectML. سيتم التشغيل في وضع التراجع إلى وحدة المعالجة المركزية (CPU Fallback Mode).&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">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">status&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="k">nullptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">ortApi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ReleaseStatus&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">status&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">// 2. تحميل النموذج وإنشاء الجلسة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">session&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Session&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">env&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">modelPath&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">sessionOptions&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="s">&amp;#34;[معلومات] تم تحميل نموذج ONNX بنجاح، وتم تجميع الرسم البياني الحسابي.&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="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Exception&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">e&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;[خطأ] فشل تحميل النموذج: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">what&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">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">throw&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">RunInference&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&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="kt">float&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">imageTensor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&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="kt">int64_t&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">inputShape&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">// 3. إنشاء مخزن مؤقت (Buffer) لموتر الإدخال (Input Tensor)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MemoryInfo&lt;/span> &lt;span class="n">memoryInfo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MemoryInfo&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">CreateCpu&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">OrtArenaAllocator&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">OrtMemTypeDefault&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Value&lt;/span> &lt;span class="n">inputTensor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">CreateTensor&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">float&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">memoryInfo&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">float&lt;/span>&lt;span class="o">*&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">imageTensor&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">imageTensor&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">inputShape&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">inputShape&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="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="k">auto&lt;/span> &lt;span class="n">inputNamePtr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">session&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetInputNameAllocated&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">allocator&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">outputNamePtr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">session&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetOutputNameAllocated&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">allocator&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">char&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">inputNames&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">inputNamePtr&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">get&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">const&lt;/span> &lt;span class="kt">char&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">outputNames&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">outputNamePtr&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">get&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. تنفيذ الاستنتاج (يتم تفريغه (offloaded) إلى NPU/GPU عبر DirectML)
&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[معلومات] بدء تنفيذ محرك الاستنتاج...&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">auto&lt;/span> &lt;span class="n">startTime&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">high_resolution_clock&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">now&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">auto&lt;/span> &lt;span class="n">outputTensors&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">session&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Ort&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">RunOptions&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="k">nullptr&lt;/span>&lt;span class="p">},&lt;/span> &lt;span class="n">inputNames&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">inputTensor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">outputNames&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="k">auto&lt;/span> &lt;span class="n">endTime&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">high_resolution_clock&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">duration&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">duration_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">milliseconds&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">endTime&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">startTime&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. استرداد موتر النتيجة وتحليله
&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">outputData&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">outputTensors&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">front&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">GetTensorMutableData&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">float&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">outputSize&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">outputTensors&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">front&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">GetTensorTypeAndShapeInfo&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">GetElementCount&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;[النتيجة] اكتمل الاستنتاج: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">duration&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">count&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;#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">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;[النتيجة] عدد عناصر موتر الإخراج: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">outputSize&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">// * بعد ذلك، يتم تنفيذ القمع غير الأقصى (NMS) وعمليات رسم الصناديق المحيطة (Bounding Boxes) على موتر الإخراج
&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="kt">int&lt;/span> &lt;span class="nf">main&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">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// مسار نموذج ONNX المراد تنفيذه
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">CustomVisionAIProcessor&lt;/span> &lt;span class="n">processor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;models/yolov8n_quantized.onnx&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">// بيانات صورة وهمية للاستنتاج (حجم الدُفعة (Batch Size) 1 × 3 قنوات × 640 × 640)
&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="kt">int64_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">inputShape&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">640&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">640&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="kt">float&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">dummyImage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">3&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">640&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">640&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.5f&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">processor&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">RunInference&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dummyImage&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">inputShape&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="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">exception&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">e&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;انتهى البرنامج بشكل غير طبيعي: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">what&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">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="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 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;h3 id="61-أهمية-إدارة-الذاكرة-والاستنتاج-الخالي-من-النسخ-zero-copy-في-c">6.1 أهمية إدارة الذاكرة والاستنتاج الخالي من النسخ (Zero-Copy) في C++
&lt;/h3>&lt;p>أكبر ميزة لاستخدام DirectML في C++ هي التكامل الوثيق الممكن مع DirectX 12 (DX12). يتضمن الكود أعلاه نسخة قياسية من بيانات ذاكرة وحدة المعالجة المركزية للأغراض التعليمية، ولكن في محركات الألعاب الفعلية أو تطبيقات معالجة الفيديو، غالبًا ما يتم الاحتفاظ بالصور (الأنسجة (Textures)) بالفعل في مساحة ذاكرة وحدة معالجة الرسومات (GPU) أو وحدة المعالجة العصبية (NPU) باستخدام DX12.&lt;/p>
&lt;p>في هذه الحالة، من خلال الاستفادة من ميزات الربط المتقدمة لـ &lt;code>OrtDmlApi&lt;/code>، من الممكن تحقيق &amp;ldquo;&lt;strong>الاستنتاج الخالي من النسخ (Zero-Copy Inference)&lt;/strong>&amp;quot;، والذي يعين موارد DX12 مباشرة كموترات (Tensors) لـ ONNX Runtime. نتيجة لذلك، يختفي تمامًا العبء الإضافي لنقل البيانات عبر ناقل PCIe (استهلاك النطاق الترددي $BW$ المذكور أعلاه)، ويتحسن معدل الإطارات في معالجة الفيديو في الوقت الفعلي بشكل كبير.&lt;/p>
&lt;h2 id="7-تحسين-الأداء-وأفضل-الممارسات">7. تحسين الأداء وأفضل الممارسات
&lt;/h2>&lt;p>فيما يلي استراتيجيات التحسين الأساسية عند تطوير تطبيقات الذكاء الاصطناعي من الدرجة الأولى باستخدام واجهات برمجة تطبيقات Windows AI و DirectML.&lt;/p>
&lt;h3 id="71-تكميم-النموذج-quantization-ومجموعة-أدوات-olive">7.1 تكميم النموذج (Quantization) ومجموعة أدوات Olive
&lt;/h3>&lt;p>لإطلاق العنان للقوة الحقيقية لـ NPU، فإن الشرط المطلق هو &lt;strong>تكميم (Quantization)&lt;/strong> أوزان وتنشيطات نموذج الذكاء الاصطناعي من FP32 (الفاصلة العائمة أحادية الدقة) إلى INT8 أو INT4. تم تحسين بنية NPU لعمليات الأعداد الصحيحة، ويوفر INT8 إنتاجية أعلى من الناحية النظرية بـ 4 أضعاف وتوفيرًا كبيرًا في الطاقة مقارنة بـ FP32.&lt;/p>
&lt;p>باستخدام سلسلة أدوات &lt;code>Olive (ONNX Live)&lt;/code> التي توفرها Microsoft، يمكن تحسين نماذج مثل PyTorch تلقائيًا لبيئات Windows. يوفر Olive دعمًا قويًا لتحسينات الانتباه (Attention) الخاصة لنماذج المحولات (Transformer models) وتجميع الرسوم البيانية (Graph compilation) الخاصة بالأجهزة.&lt;/p>
&lt;h3 id="72-مقايضة-بين-معالجة-الدفعات-batch-processing-والبث-التفاعلي">7.2 مقايضة بين معالجة الدفعات (Batch Processing) والبث التفاعلي
&lt;/h3>&lt;p>في استدعاءات واجهة برمجة التطبيقات، يمكن أن تؤدي معالجة الدفعات لطلبات استنتاج متعددة إلى زيادة كفاءة استخدام NPU (Compute Utilization). ومع ذلك، بالنسبة لواجهات المستخدم التفاعلية مثل روبوتات الدردشة، فإن الوقت المستغرق لعرض الرمز الأول (TTFT: Time To First Token) يحدد تجربة المستخدم (UX) أكثر من الإنتاجية.
لذلك، بالنسبة لواجهات المستخدم التفاعلية، فإن أفضل ممارسة هي تعيين حجم الدفعة إلى 1 وتحديد أولوية الإنشاء المتدفق.&lt;/p>
&lt;h3 id="73-مهام-الخلفية-والتكامل-مع-نظام-التشغيل">7.3 مهام الخلفية والتكامل مع نظام التشغيل
&lt;/h3>&lt;p>يستهلك استنتاج الذكاء الاصطناعي كمية كبيرة من الطاقة المحلية وموارد النظام. بالاشتراك مع واجهة برمجة تطبيقات &lt;code>App Lifecycle API&lt;/code> في Windows، عندما يعمل التطبيق في الخلفية، يُطلب تعليق (Suspend) مهام الاستنتاج ذات الأولوية المنخفضة أو تقييد استهلاك الموارد.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant User as "المستخدم"
participant App as "تطبيق Windows (C#)"
participant API as "Microsoft.Windows.AI"
participant OS as "Windows Copilot Runtime"
participant ORT as "ONNX Runtime (DML)"
participant NPU as "جهاز NPU"
User->>App: "إدخال المطالبة"
App->>API: "GenerateResponseStreamAsync()"
API->>OS: "إرسال مهمة الاستنتاج"
OS->>ORT: "طلب تنفيذ الرسم البياني"
ORT->>NPU: "تنفيذ قائمة الأوامر عبر DirectML"
NPU-->>ORT: "اكتمل الحساب (تم إنشاء رمز واحد)"
ORT-->>OS: "نتيجة الموتر"
OS-->>API: "نص تم فك تشفيره"
API-->>App: "قطع (Chunks) كـ IAsyncEnumerable&lt;string>"
App-->>User: "رسم النص في الوقت الفعلي على واجهة المستخدم"
Note over ORT,NPU: "تتكرر هذه الحلقة بسرعة حتى تكتمل"&lt;/div>
&lt;p>يوضح مخطط التسلسل هذا جمال المعالجة غير المتزامنة حيث تتدفق البيانات بسلاسة من الأجهزة الأساسية (NPU) في أدنى مستوى إلى طبقة العرض الخاصة بالتطبيق دون حظر خيط واجهة المستخدم (UI thread) على الإطلاق.&lt;/p>
&lt;h2 id="8-الآفاق-المستقبلية-وتطور-windows-ai">8. الآفاق المستقبلية وتطور Windows AI
&lt;/h2>&lt;p>تتطور واجهة برمجة تطبيقات &lt;code>Microsoft.Windows.AI&lt;/code> و Copilot Runtime بسرعة في الوقت الحاضر. من المتوقع حدوث التحولات التالية في التحديثات المستقبلية للمطورين:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>تكامل أصلي لواجهة برمجة تطبيقات متعددة الوسائط (Multimodal API) في نظام التشغيل&lt;/strong>: المعالجة المتزامنة السلسة ليس فقط للنصوص ولكن أيضًا للصوت، الصور، وحتى خلاصات الفيديو الحية، مما يوفر استنتاج ذكاء اصطناعي متعدد الوسائط كمعيار قياسي على مستوى نظام التشغيل.&lt;/li>
&lt;li>&lt;strong>دعم على مستوى النظام لـ RAG (الجيل المعزز بالاسترجاع)&lt;/strong>: بناء مساعد ذكاء اصطناعي شخصي متقدم للغاية عن طريق ربط مجموعة المستندات الشخصية في جهاز الكمبيوتر المحلي أو فهرس Windows Search بنموذج الذكاء الاصطناعي في بيئة (Sandbox) آمنة داخل نظام التشغيل، مع حماية خصوصية المستخدم بشكل كامل.&lt;/li>
&lt;li>&lt;strong>توسيع النطاق الديناميكي لموارد NPU&lt;/strong>: عندما تعمل تطبيقات ذكاء اصطناعي متعددة في نفس الوقت (على سبيل المثال، إلغاء الضوضاء في الخلفية وإنشاء الأكواد في المقدمة)، يقوم مجدول النواة (Kernel Scheduler) في Windows بتبديل سياق تنفيذ NPU ديناميكيًا لضمان جودة الخدمة (QoS).&lt;/li>
&lt;/ul>
&lt;h2 id="9-الخلاصة-مستقبل-التطبيقات-التي-يغيرها-الذكاء-الاصطناعي-المحلي">9. الخلاصة: مستقبل التطبيقات التي يغيرها الذكاء الاصطناعي المحلي
&lt;/h2>&lt;p>جلب Copilot Runtime و واجهة برمجة التطبيقات &lt;code>Microsoft.Windows.AI&lt;/code> في Windows 11 سلاحًا قويًا للغاية يُسمى &amp;ldquo;الذكاء الاصطناعي المحلي&amp;rdquo; لجميع مطوري Windows. لم يعد من الضروري الاعتماد بالكامل على واجهات برمجة التطبيقات السحابية. من الممكن تزويد المستخدمين بتجربة ذكاء اصطناعي من الجيل التالي تقضي على زمن الوصول، وتحمي الخصوصية، وتعمل بشكل كامل حتى في وضع عدم الاتصال.&lt;/p>
&lt;p>استخدم المعرفة بدمج النماذج اللغوية القياسية للنظام باستخدام C#، والتقييم الرياضي للأداء، وتحسين الأجهزة المتقدم باستخدام C++ و DirectML المشروح في هذه المقالة لإنشاء تطبيقات Windows من الجيل التالي &amp;ldquo;الأصلية للذكاء الاصطناعي&amp;rdquo; بيديك. الاحتمالات اللانهائية التي يوفرها الذكاء الاصطناعي تكمن مباشرة وراء الكود الذي تكتبه.&lt;/p>
&lt;hr>
&lt;p>&lt;em>ملاحظة: تمت كتابة هذه المقالة بناءً على واجهات برمجة التطبيقات للمعاينة وأحدث المواصفات اعتبارًا من سبتمبر 2026. نظرًا لأن مواصفات واجهة برمجة التطبيقات ومتطلبات الأجهزة قد تتغير مع تحديثات Windows، فتأكد من الرجوع إلى الوثائق الرسمية لـ Microsoft Learn عند التنفيذ.&lt;/em>&lt;/p></description></item><item><title>لا حاجة لبايثون! بناء محرك استدلال للذكاء الاصطناعي باستخدام C++ فقط</title><link>http://kenji.blog/ar/p/building-ai-inference-engine-cpp-only/</link><pubDate>Fri, 11 Sep 2026 17:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/building-ai-inference-engine-cpp-only/</guid><description>&lt;img src="http://kenji.blog/p/building-ai-inference-engine-cpp-only/img/eyecatch.jpg" alt="Featured image of post لا حاجة لبايثون! بناء محرك استدلال للذكاء الاصطناعي باستخدام C++ فقط" />&lt;h2 id="1-مقدمة-لماذا-نتخلى-عن-بايثون-ونصنع-محرك-استدلال-للذكاء-الاصطناعي-باستخدام-c">1. مقدمة: لماذا نتخلى عن بايثون ونصنع محرك استدلال للذكاء الاصطناعي باستخدام C++؟
&lt;/h2>&lt;p>في تطوير الذكاء الاصطناعي الحديث، تعتبر بايثون (Python) هي المعيار الفعلي. بفضل أطر العمل القوية مثل PyTorch و TensorFlow، يمكنك بناء وتدريب واستدلال شبكات عصبية معقدة ببضعة أسطر من التعليمات البرمجية. ومع ذلك، وراء كواليس هذه الأطر، تتولى اللغات ذات المستوى المنخفض مثل C++ و CUDA معالجة العمليات الحسابية الثقيلة. إن بايثون تلعب مجرد دور &amp;ldquo;الصمغ&amp;rdquo;.&lt;/p>
&lt;p>إذن، لماذا نحتاج إلى استبعاد بايثون وبناء محرك استدلال للذكاء الاصطناعي باستخدام C++ بمفردها؟ هناك عدة أسباب قوية لذلك:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>الأداء الفائق وزمن الانتقال المنخفض&lt;/strong>: يمكن التخلص تمامًا من النفقات الإضافية الناتجة عن القفل العالمي للمترجم (GIL) والنوع الديناميكي في بايثون. خاصة في الأنظمة التي تتطلب العمل في الوقت الفعلي، حيث يكون التأخير بالمللي ثانية أمرًا قاتلًا.&lt;/li>
&lt;li>&lt;strong>سهولة النشر&lt;/strong>: من الصعب للغاية بناء بيئة بايثون (مجموعة ضخمة من المكتبات، جحيم التبعيات) في بيئة المستخدم النهائي. باستخدام C++، كل ما عليك فعله هو توزيع ملف تنفيذي ثنائي واحد مرتبط بشكل ثابت (مثل &lt;code>.exe&lt;/code> أو ثنائيات ELF).&lt;/li>
&lt;li>&lt;strong>دعم الأجهزة الطرفية&lt;/strong>: في البيئات ذات الموارد المحدودة مثل الهواتف الذكية، والأجهزة المدمجة، و Raspberry Pi، لا توجد سعة لتشغيل بيئة تشغيل بايثون التي تستهلك جيجابايتات من الذاكرة.&lt;/li>
&lt;li>&lt;strong>التحكم المباشر في الأجهزة&lt;/strong>: توفر C++ إمكانية التحكم في المستوى المنخفض، مثل توقيت تخصيص الذاكرة، والاستخدام الصريح لتعليمات SIMD، وتحسين عمليات نقل الذاكرة مع وحدة المعالجة الرسومية (GPU).&lt;/li>
&lt;/ol>
&lt;p>في هذه المقالة، ومن خلال استلهام كبير من بنية مكتبة &amp;ldquo;GGML&amp;rdquo; التي طورها Georgi Gerganov، سنغوص في الأعماق التقنية لشرح عملية بناء محرك استدلال من الصفر باستخدام C++ فقط لتشغيل النماذج اللغوية الكبيرة (LLMs) وغيرها.&lt;/p>
&lt;hr>
&lt;h2 id="2-النظرة-العامة-على-بنية-محرك-الاستدلال">2. النظرة العامة على بنية محرك الاستدلال
&lt;/h2>&lt;p>تعد عملية الاستدلال في الذكاء الاصطناعي في جوهرها &amp;ldquo;سلسلة من حسابات المصفوفات الضخمة&amp;rdquo;. لتنفيذ ذلك بكفاءة، يجب أن يتكون محرك الاستدلال من المكونات التالية.&lt;/p>
&lt;div class="mermaid">graph TD
A["بيانات الإدخال (رموز/صور)"] --> B["إدارة الموترات"]
B --> C["الرسم البياني الحسابي (DAG)"]
C --> D["ساحة الذاكرة والمخصص"]
C --> E["المجدول وتجمع الخيوط"]
E --> F["الواجهة الخلفية للمعالج (AVX2/ARM NEON)"]
E --> G["الواجهة الخلفية للرسوميات (CUDA/Metal)"]
F --> H["نتائج الإخراج"]
G --> H&lt;/div>
&lt;ol>
&lt;li>&lt;strong>إدارة الموترات (Tensor)&lt;/strong>: إدارة هيكل بيانات المصفوفات متعددة الأبعاد، والخطوة (Stride) لكل بُعد.&lt;/li>
&lt;li>&lt;strong>الرسم البياني الحسابي (Computation Graph)&lt;/strong>: تمثيل العمليات الحسابية لكل طبقة من طبقات الشبكة العصبية كرسم بياني موجه غير دوري (DAG).&lt;/li>
&lt;li>&lt;strong>ساحة الذاكرة (Memory Arena)&lt;/strong>: آلية إدارة ذاكرة مخصصة مسبقًا لتجنب النفقات الإضافية لتخصيص الذاكرة الديناميكي (&lt;code>malloc&lt;/code> أو &lt;code>new&lt;/code>).&lt;/li>
&lt;li>&lt;strong>الواجهة الخلفية (Backend)&lt;/strong>: تنفيذ العمليات (النواة/Kernels) المحسّنة لأجهزة معينة مثل CPU أو GPU.&lt;/li>
&lt;/ol>
&lt;p>سنقوم ببناء هذه المكونات معًا باستخدام ميزات C++ القوية (مثل القوالب، حساب المؤشرات، و RAII).&lt;/p>
&lt;hr>
&lt;h2 id="3-أسرار-إدارة-الذاكرة-ساحة-الذاكرة-memory-arena-ومحاذاة-simd">3. أسرار إدارة الذاكرة: ساحة الذاكرة (Memory Arena) ومحاذاة SIMD
&lt;/h2>&lt;p>تعتبر إدارة الذاكرة في محرك الاستدلال من أهم العناصر التي تؤثر بشكل مباشر على الأداء. أثناء الاستدلال، خاصة عند المرور عبر كل طبقة من نموذج Transformer، يتم إنشاء عدد هائل من الموترات الوسيطة. إذا قمنا بتخصيص وتحرير الذاكرة في كل مرة باستخدام &lt;code>malloc&lt;/code> القياسي، فسيؤدي ذلك إلى تجزئة الكومة (Heap) وتحويل السياق في نظام التشغيل، مما يتسبب في انخفاض فادح في السرعة.&lt;/p>
&lt;p>لذلك، نعتمد نهج &amp;ldquo;&lt;strong>ساحة الذاكرة (Memory Arena)&lt;/strong>&amp;rdquo;. تتمثل هذه الطريقة في حساب (أو تحديد) الحد الأقصى للذاكرة المطلوبة في بداية الاستدلال وتخصيصها دفعة واحدة، ثم استقطاع الذاكرة ببساطة عن طريق زيادة المؤشر.&lt;/p>
&lt;h3 id="31-أهمية-المحاذاة-alignment">3.1 أهمية المحاذاة (Alignment)
&lt;/h3>&lt;p>تدعم وحدات المعالجة المركزية (CPUs) الحديثة تعليمات SIMD (تعليمة واحدة، بيانات متعددة). مثل AVX2/AVX-512 في Intel/AMD، و NEON في ARM. تقوم هذه التعليمات بمعالجة 256 بت (32 بايت) أو 512 بت (64 بايت) من البيانات دفعة واحدة، ولكن يجب أن تكون ذاكرة البيانات المعالجة محاذاة (Aligned) عند حدود بايت معينة (عادةً 32 بايت أو 64 بايت).&lt;/p>
&lt;p>فيما يلي مثال على تنفيذ ساحة ذاكرة في C++ يأخذ المحاذاة في الاعتبار:&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;/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;lt;cstdint&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;cstddef&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">#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">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">MemoryArena&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">size_t&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">size_t&lt;/span> &lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">*&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MemoryArena&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">size&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">offset&lt;/span>&lt;span class="p">(&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">// استخدم posix_memalign للأنظمة المتوافقة مع POSIX، و _aligned_malloc لنظام Windows
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#ifdef _WIN32
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">*&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">_aligned_malloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#else
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">posix_memalign&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">reinterpret_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="o">**&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&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="k">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">bad_alloc&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="cp">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&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="o">~&lt;/span>&lt;span class="n">MemoryArena&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="cp">#ifdef _WIN32
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="n">_aligned_free&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="cp">#else
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="n">free&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="cp">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&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="kt">void&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">allocate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">bytes&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">alignment&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">64&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">size_t&lt;/span> &lt;span class="n">pad&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">alignment&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">offset&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">alignment&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">alignment&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">offset&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">pad&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">bytes&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">size&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">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">runtime_error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;OOM: MemoryArena out of memory&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">offset&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">pad&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">offset&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">bytes&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="n">ptr&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">void&lt;/span> &lt;span class="nf">reset&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">offset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// تحرير الذاكرة يكون بمجرد إرجاع المؤشر للخلف (O(1))
&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بهذه الطريقة، يتم دائمًا الحصول على الذاكرة من خلال هذه الساحة عند إنشاء الموترات. في كل مرة تنتهي فيها خطوة الاستدلال (مثلًا بعد كل توليد رمز)، يمكنك إعادة استخدام الذاكرة في لمح البصر عن طريق استدعاء &lt;code>reset()&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="4-سحر-هيكل-بيانات-الموترات-والخطوة-stride">4. سحر هيكل بيانات الموترات والخطوة (Stride)
&lt;/h2>&lt;p>الموتر هو تعميم لمفاهيم القيم العددية، والمتجهات، والمصفوفات. في التنفيذ، من المهم أن البيانات الفعلية توضع في الذاكرة كـ &lt;strong>مصفوفة متجاورة أحادية البعد&lt;/strong>، بينما نستخدم مفهوم &amp;ldquo;الخطوة (Stride)&amp;rdquo; لتفسيرها على أنها متعددة الأبعاد.&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;/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="k">enum&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">DataType&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">FP32&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="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">INT8&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">INT4&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="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">struct&lt;/span> &lt;span class="nc">Tensor&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_dims&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">int64_t&lt;/span> &lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// عدد العناصر في كل بُعد (Number of Elements)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">nb&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// الخطوة بالبايت لكل بُعد (Number of Bytes)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">DataType&lt;/span> &lt;span class="n">type&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">void&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">data&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">// للرسم البياني الحسابي
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">enum&lt;/span> &lt;span class="nc">OpType&lt;/span> &lt;span class="n">op&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&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>تمثل الخطوة &lt;code>nb[i]&lt;/code> المسافة بالبايت في الذاكرة بين العناصر المتجاورة في البُعد &lt;code>i&lt;/code>.
على سبيل المثال، إذا كانت مصفوفة تحتوي على $M \times N$ عنصر (من نوع FP32، أي 4 بايت لكل عنصر) مخزنة بتنسيق أولوية الصفوف (Row-Major)، فستكون الخطوات كالتالي:&lt;/p>
&lt;ul>
&lt;li>&lt;code>nb[0]&lt;/code> = 4 (بايت) : الانتقال في اتجاه العمود&lt;/li>
&lt;li>&lt;code>nb[1]&lt;/code> = $N \times 4$ (بايت) : الانتقال في اتجاه الصف&lt;/li>
&lt;/ul>
&lt;p>باستخدام هذا المفهوم، يمكننا إجراء عمليات مثل &amp;ldquo;المنقول (Transpose)&amp;rdquo; أو &amp;ldquo;العرض (View)&amp;rdquo; ببساطة عن طريق التبديل بين قيم الخطوات دون الحاجة إلى نسخ الذاكرة. هذه طريقة أنيقة وسريعة جدًا.&lt;/p>
&lt;hr>
&lt;h2 id="5-بناء-الرسم-البياني-الحسابي-dag-والتقييم-المؤجل">5. بناء الرسم البياني الحسابي (DAG) والتقييم المؤجل
&lt;/h2>&lt;p>على غرار PyTorch وغيرها، سيعتمد محرك الاستدلال الخاص بنا على التقييم المؤجل (Lazy Evaluation). بمعنى آخر، عند استدعاء دالة عملية رياضية، لا يتم إجراء الحساب الفعلي حينها، بل يتم فقط بناء الرسم البياني (تبعيات العقد).&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;/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">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">tensor_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">MemoryArena&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">b&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">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">create_tensor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">n_dims&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpType&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ADD&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&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="n">out&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">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">tensor_mul_mat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">MemoryArena&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">b&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">// b غالبًا ما تكون منقولة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&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">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">create_tensor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ne&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpType&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MUL_MAT&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&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="n">out&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>سيكون تدفق عملية الاستدلال على النحو التالي:&lt;/p>
&lt;div class="mermaid">graph LR
A["تعريف الموترات"] --> B["بناء الرسم البياني عبر العمليات"]
B --> C["الفرز الطوبولوجي (Topological Sort)"]
C --> D["تخصيص الذاكرة للمخرجات"]
D --> E["تنفيذ العقد بالترتيب"]&lt;/div>
&lt;p>عند تقييم الرسم البياني (المسار الأمامي)، نستخدم الفرز الطوبولوجي لتنفيذ العمليات بدءًا من العقد التي لا تحتوي على تبعيات. نظرًا لأننا نقوم بالاستدلال فقط، فلا داعي للاحتفاظ بالتدرجات الخاصة بالانتشار الخلفي، مما يجعل إدارة الذاكرة بسيطة للغاية.&lt;/p>
&lt;hr>
&lt;h2 id="6-جوهر-الرياضيات-والتحسين-ضرب-المصفوفات-gemm">6. جوهر الرياضيات والتحسين: ضرب المصفوفات (GEMM)
&lt;/h2>&lt;p>يتم استهلاك أكثر من 90% من العمليات الحسابية في استدلال الذكاء الاصطناعي في عمليات ضرب المصفوفات (GEMM: General Matrix Multiply). فآلية الانتباه والشبكات العصبية المتقدمة (FFN) التي تُعد جوهر نماذج Transformer، هي في الأساس عمليات ضرب لمصفوفات ضخمة.&lt;/p>
&lt;p>حاصل ضرب $C = A B$ (بحجم $M \times N$) لمصفوفتين $A$ (بحجم $M \times K$) و $B$ (بحجم $K \times N$) يُعبر عنه رياضياً كالتالي:&lt;/p>
$$
C_{i,j} = \sum_{k=0}^{K-1} A_{i,k} \cdot B_{k,j}
$$
&lt;p>إذا قمنا بتنفيذ ذلك باستخدام حلقة ثلاثية بسيطة، فسيحدث عدد كبير من إخفاقات ذاكرة التخزين المؤقت، ولن نحصل على أداء جيد إطلاقًا.&lt;/p>
&lt;h3 id="61-حظر-ذاكرة-التخزين-المؤقت-وتحسينات-simd-على-وحدة-المعالجة-المركزية">6.1 حظر ذاكرة التخزين المؤقت وتحسينات SIMD على وحدة المعالجة المركزية
&lt;/h3>&lt;p>تتلخص الإستراتيجية الأساسية لتسريع عملية GEMM على وحدة المعالجة المركزية في التالي:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>تجانب الحلقات (Cache Blocking)&lt;/strong>: تقسيم المصفوفات إلى كتل صغيرة تتناسب مع حجم ذاكرة التخزين المؤقت L1/L2 لتسهيل الحسابات.&lt;/li>
&lt;li>&lt;strong>تعبئة البيانات&lt;/strong>: إعادة ترتيب البيانات داخليًا بحيث تصبح أنماط الوصول إلى الذاكرة متسلسلة.&lt;/li>
&lt;li>&lt;strong>الاستفادة من SIMD&lt;/strong>: استخدام تعليمات FMA (الضرب والجمع المدمج) مثل &lt;code>_mm512_fmadd_ps&lt;/code> في AVX-512 لتنفيذ العديد من عمليات الضرب والجمع في دورة ساعة واحدة.&lt;/li>
&lt;/ol>
&lt;p>إليك مثال مبسط لعملية الضرب النقطي للمتجهات باستخدام C++ و SIMD Intrinsics:&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;/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;lt;immintrin.h&amp;gt;&lt;/span>&lt;span class="cp"> &lt;/span>&lt;span class="c1">// لتعليمات AVX
&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">// الضرب النقطي السريع لـ FP32 باستخدام AVX2
&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="nf">dot_product_avx2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">n&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">__m256&lt;/span> &lt;span class="n">sum256&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_setzero_ps&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">i&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="c1">// معالجة 8 عناصر في المرة الواحدة (256 بت = 32 بايت = 8 * 4 بايت)
&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">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">8&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">__m256&lt;/span> &lt;span class="n">va&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_loadu_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">__m256&lt;/span> &lt;span class="n">vb&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_loadu_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تعليمة FMA: sum256 = va * vb + sum256
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sum256&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_fmadd_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">va&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vb&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sum256&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">// الجمع الأفقي للقيم الموجودة في سجلات SIMD
&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="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">_mm256_storeu_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sum256&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">float&lt;/span> &lt;span class="n">dot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&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">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">7&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">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&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">dot&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&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="k">return&lt;/span> &lt;span class="n">dot&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>بهذه التعديلات البسيطة فقط، يمكننا الحصول على زيادة في السرعة تتراوح من عدة أضعاف إلى أكثر من عشرة أضعاف مقارنة بالتنفيذ البسيط.&lt;/p>
&lt;hr>
&lt;h2 id="7-تجاوز-حدود-الأجهزة-دمج-واجهات-cuda-و-metal">7. تجاوز حدود الأجهزة: دمج واجهات CUDA و Metal
&lt;/h2>&lt;p>رغم أن تنفيذ C++ الخالص يعمل بشكل معقول على وحدة المعالجة المركزية، إلا أنه لتشغيل نماذج ضخمة مثل LLM بسرعة عملية، فإن قوة المعالجة المتوازية في وحدة المعالجة الرسومية (GPU) تعتبر ضرورية. لذلك، سنقدم طبقة تجريد للواجهات الخلفية في محركنا.&lt;/p>
&lt;h3 id="71-تجريد-الواجهة-الخلفية">7.1 تجريد الواجهة الخلفية
&lt;/h3>&lt;p>باستخدام تعدد الأشكال في C++، يمكننا التبديل بين مُنفذي العمليات الحسابية (Executors).&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;/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="k">class&lt;/span> &lt;span class="nc">Backend&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="o">~&lt;/span>&lt;span class="n">Backend&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">alloc_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">free_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">copy_to_device&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">copy_to_host&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&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>&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">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">compute_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dst&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">compute_mul_mat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dst&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>&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;h3 id="72-تنفيذ-الواجهة-الخلفية-nvidia-cuda">7.2 تنفيذ الواجهة الخلفية NVIDIA CUDA
&lt;/h3>&lt;p>للاستفادة من وحدات معالجة الرسوميات من NVIDIA، سنقوم بتنفيذ واجهة خلفية باستخدام امتدادات CUDA C++. من الممكن كتابة نواة خاصة بنا، ولكن فيما يتعلق بضرب المصفوفات، فإن استخدام &amp;ldquo;cuBLAS&amp;rdquo;، وهي أفضل مكتبة تقدمها NVIDIA، هو الحل الأمثل.&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;/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;lt;cublas_v2.h&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;cuda_runtime.h&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="k">class&lt;/span> &lt;span class="nc">CUDABackend&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">public&lt;/span> &lt;span class="n">Backend&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cublasHandle_t&lt;/span> &lt;span class="n">handle&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">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CUDABackend&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">cublasCreate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">handle&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="o">~&lt;/span>&lt;span class="n">CUDABackend&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">cublasDestroy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&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">void&lt;/span> &lt;span class="nf">compute_mul_mat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dst&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">override&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// في CUDA، التنسيق الافتراضي هو العمود الأول (Column-Major)، لذا يجب الانتباه للمعلمات
&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">float&lt;/span> &lt;span class="n">alpha&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">1.0f&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span> &lt;span class="n">beta&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.0f&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="kt">int&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&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="kt">int&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&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="kt">int&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// بافتراض أن src1 منقولة
&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">cublasSgemm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CUBLAS_OP_T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CUBLAS_OP_N&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">alpha&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="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">src0&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&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="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">src1&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">beta&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="kt">float&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">dst&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cudaDeviceSynchronize&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>نظرًا لأن نقل البيانات بين ذاكرة CUDA وذاكرة المضيف (&lt;code>cudaMemcpy&lt;/code>) عملية مكلفة للغاية، فمن المهم تصميم النظام بحيث يحتفظ بجميع الأوزان والموترات الوسيطة داخل VRAM قدر الإمكان طوال فترة الاستدلال.&lt;/p>
&lt;h3 id="73-الواجهة-الخلفية-لـ-apple-silicon-metal">7.3 الواجهة الخلفية لـ Apple Silicon (Metal)
&lt;/h3>&lt;p>في السنوات الأخيرة، أثبتت شرائح M1/M2/M3 في أجهزة Mac كفاءتها العالية كأجهزة استدلال للذكاء الاصطناعي. والسبب في ذلك يعود إلى &amp;ldquo;الذاكرة الموحدة&amp;rdquo;. نظرًا لأن CPU و GPU يشتركان في نفس مساحة الذاكرة، فإننا نستغني تمامًا عن عمليات نقل الذاكرة المكلفة بين المضيف والجهاز عبر ناقل PCIe كما هو الحال في CUDA.&lt;/p>
&lt;p>لاستدعاء Metal من C++، نستخدم Objective-C++ (ملفات &lt;code>.mm&lt;/code>) كجسر أو نستخدم مكتبة &lt;code>metal-cpp&lt;/code>.
يتم كتابة النواة باستخدام Metal Compute Shader.&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;/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">// تظليل Metal
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;metal_stdlib&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 class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">metal&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">kernel&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">mul_mat_kernel&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&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="p">[[&lt;/span>&lt;span class="n">buffer&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="n">device&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="na">[[buffer(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">device&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">C&lt;/span> &lt;span class="na">[[buffer(2)]]&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">constant&lt;/span> &lt;span class="n">uint3&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">dims&lt;/span> &lt;span class="na">[[buffer(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">uint2&lt;/span> &lt;span class="n">gid&lt;/span> &lt;span class="na">[[thread_position_in_grid]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&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">uint&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dims&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">uint&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dims&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">uint&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dims&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">z&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uint&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gid&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">uint&lt;/span> &lt;span class="n">col&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gid&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&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">row&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">col&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">n&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="kt">float&lt;/span> &lt;span class="n">sum&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.0&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="p">(&lt;/span>&lt;span class="n">uint&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">k&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&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">sum&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">col&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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">C&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">col&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sum&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في بيئة Apple Silicon، تتوفر أيضًا مكتبة محسنة لعمليات ضرب المصفوفات تُسمى MPS. باستخدام هذه المكتبة، يمكننا تحقيق سرعات استدلال مذهلة.&lt;/p>
&lt;hr>
&lt;h2 id="8-المعالجات-الخاصة-بنماذج-transformer-الانتباه-وذاكرة-التخزين-المؤقت-kv">8. المعالجات الخاصة بنماذج Transformer: الانتباه وذاكرة التخزين المؤقت KV
&lt;/h2>&lt;p>تعتمد أحدث نماذج LLM مثل LLaMA 2/3 و GPT على بنية Transformer. لتنفيذها في C++، من الضروري بناء خوارزمية الانتباه &amp;ldquo;Scaled Dot-Product Attention&amp;rdquo; الممثلة في المعادلة التالية:&lt;/p>
$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
&lt;p>بالإضافة إلى ذلك، في توليد الرموز ذاتي الانحدار، من الضروري الاحتفاظ بنتائج حسابات الرموز السابقة. هذا ما يُسمى &amp;ldquo;&lt;strong>ذاكرة التخزين المؤقت KV&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">graph TD
T["الرمز الحالي"] --> Q["الاستعلام (Query)"]
T --> K["المفتاح (Key)"]
T --> V["القيمة (Value)"]
K --> KCache["إضافة إلى ذاكرة التخزين المؤقت KV"]
V --> VCache["إضافة إلى ذاكرة التخزين المؤقت KV"]
Q --> Dot1["Q * K_Cache^T"]
KCache --> Dot1
Dot1 --> Scale["مقياس (1/sqrt(d))"]
Scale --> Softmax["Softmax"]
Softmax --> Dot2["SoftmaxOut * V_Cache"]
VCache --> Dot2
Dot2 --> Out["متجه السياق"]&lt;/div>
&lt;p>يتم تخصيص الذاكرة لذاكرة التخزين المؤقت KV عن طريق حجز مساحة ذاكرة للحد الأقصى لطول السياق مسبقًا في ساحة الذاكرة بطريقة مشابهة للمخزن المؤقت الحلقي. هذا يمنع الحاجة إلى إعادة التخصيص في كل خطوة توليد.&lt;/p>
&lt;p>بالنسبة للتشفير الموضعي، سنقوم بتنفيذ &amp;ldquo;RoPE (Rotary Position Embedding)&amp;rdquo;. إنها طريقة لتضمين معلومات الموقع كمتجه دوران في مساحة معقدة. إن مفتاح الأداء هنا يكمن في تحسين استدعاء دوال &lt;code>sin&lt;/code> و &lt;code>cos&lt;/code> في C++.&lt;/p>
&lt;hr>
&lt;h2 id="9-التحسين-الفائق-من-خلال-تكميم-النموذج-quantization">9. التحسين الفائق من خلال تكميم النموذج (Quantization)
&lt;/h2>&lt;p>إذا تم تحميل نموذج ضخم (مثل نموذج LLaMA بـ 7 مليارات معلمة) بصيغة FP32، فسيستهلك حوالي 28 جيجابايت من الذاكرة (VRAM) للأوزان فقط. ومع إضافة ذاكرة التخزين المؤقت KV، يمكن أن يتجاوز بسهولة 30 جيجابايت، مما يجعله مستحيلاً للتشغيل على وحدات المعالجة الرسومية العادية.&lt;/p>
&lt;p>لذلك، يصبح من الضروري استخدام تقنية &amp;ldquo;&lt;strong>التكميم&lt;/strong>&amp;rdquo;. وهذا هو صميم وأهم ما يميز تنسيق GGML.&lt;/p>
&lt;p>التكميم هو تقنية لتقليل دقة الأوزان عمدًا:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>FP16 (16-bit)&lt;/strong>: يقلل الحجم إلى النصف. مع عدم وجود انخفاض ملحوظ في الدقة.&lt;/li>
&lt;li>&lt;strong>INT8 (8-bit)&lt;/strong>: يقلل الحجم إلى الربع. تدهور طفيف.&lt;/li>
&lt;li>&lt;strong>INT4 (4-bit)&lt;/strong>: يقلل الحجم إلى الثُمن. باستخدام عوامل القياس والحجب الخاصة، يمكن إجراء استدلال عملي.&lt;/li>
&lt;/ul>
&lt;p>على جانب محرك الاستدلال، تُقرأ الأوزان المضغوطة بصيغة INT4 (أو INT8) من الذاكرة، و&lt;strong>مباشرة بعد تحميلها في سجلات CPU أو GPU، يتم فك تكميمها (Dequantize) إلى FP16 أو FP32 لإجراء الحسابات&lt;/strong>.&lt;/p>
&lt;p>بشكل يثير الدهشة، فإن تقليل كمية البيانات المقروءة من الذاكرة حتى لو أدى ذلك لزيادة العمليات الحسابية يجعل العملية أسرع. وذلك لأن عنق الزجاجة لمهام الاستدلال في الأجهزة الحديثة ليس في &amp;ldquo;قوة الحوسبة&amp;rdquo; بل في &amp;ldquo;&lt;strong>عرض النطاق الترددي للذاكرة&lt;/strong>&amp;rdquo;. باستخدام محرك مبني بـ C++ ومكمم بتقنية INT4، يمكنك تشغيل نماذج LLM محليًا بسلاسة حتى على جهاز MacBook Air بذاكرة 8 جيجابايت.&lt;/p>
&lt;hr>
&lt;h2 id="10-ضبط-الأداء-معمارية-numa-وتجمع-الخيوط">10. ضبط الأداء: معمارية NUMA وتجمع الخيوط
&lt;/h2>&lt;p>عند إجراء الاستدلال باستخدام وحدة المعالجة المركزية، يكون تعدد الخيوط أمرًا ضروريًا. ومع ذلك، فإن مجرد بدء تشغيل العديد من &lt;code>std::thread&lt;/code> لا يعتبر الحل الأمثل.&lt;/p>
&lt;p>في الخوادم الحديثة أو معالجات سطح المكتب المتطورة، يتم اعتماد معمارية &lt;strong>NUMA (Non-Uniform Memory Access)&lt;/strong>. الوصول إلى الذاكرة القريبة ماديًا من نواة CPU محددة يكون سريعًا، في حين أن الوصول إلى ذاكرة مرتبطة بمعالج آخر يكون بطيئًا للغاية.&lt;/p>
&lt;p>في محركات الاستدلال المتقدمة المكتوبة بـ C++، يتم استخدام التقنيات التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>تثبيت الخيوط (Thread Pinning)&lt;/strong>: تثبيت كل خيط بنواة CPU معينة لمنع تدمير ذاكرة التخزين المؤقت الناتج عن تبديل السياق.&lt;/li>
&lt;li>&lt;strong>تخصيص مدرك لـ NUMA&lt;/strong>: تخصيص الذاكرة على نفس عقدة NUMA التي توجد بها الخيوط التي تعالج تلك البيانات.&lt;/li>
&lt;li>&lt;strong>تجمع خيوط لسرقة العمل (Work-Stealing)&lt;/strong>: تقسيم كل عقدة في الرسم البياني الحسابي إلى مهام دقيقة، وتنفيذ مُجدوِل فعّال يسمح للخيوط الخاملة بسرقة المهام وتنفيذها تلقائيًا.&lt;/li>
&lt;/ol>
&lt;p>من خلال الاستفادة من هذه التقنيات، يمكننا إبقاء استخدام وحدة المعالجة المركزية قريبًا من 100%، وتحقيق إنتاجية قريبة من القيمة النظرية.&lt;/p>
&lt;hr>
&lt;h2 id="11-الخلاصة-متعة-قيادة-الذكاء-الاصطناعي-بعضلات-c">11. الخلاصة: متعة قيادة الذكاء الاصطناعي &amp;ldquo;بعضلات&amp;rdquo; C++
&lt;/h2>&lt;p>بايثون لغة مفيدة حقًا. ومع ذلك، بمجرد الانتقال إلى مرحلة &amp;ldquo;تشغيل النموذج المكتمل بكفاءة على جميع الأجهزة في العالم الحقيقي&amp;rdquo;، يحين وقت C++.&lt;/p>
&lt;p>إن الشعور بالإنجاز عند رؤية محرك استدلال قمت ببنائه بنفسك من خلال معالجة متتاليات البايت في الذاكرة مباشرة، والضغط على السجلات إلى الحد الأقصى بتعليمات SIMD، والمصارعة مع عرض النطاق الترددي لـ VRAM، وهو يولد نصوصًا طبيعية على سطر الأوامر، هو &amp;ldquo;فرحة هندسية خالصة&amp;rdquo; لا يمكن أن تحصل عليها أبدًا بمجرد استدعاء &lt;code>model.generate()&lt;/code> في أحد أطر عمل بايثون.&lt;/p>
&lt;p>غالبًا ما يُنظر إلى تقنيات الذكاء الاصطناعي كـ &amp;ldquo;صندوق أسود&amp;rdquo;، ولكن بكتابة كل شيء بنفسك باستخدام C++ بدءًا من عمليات الموترات وحتى تخصيص الذاكرة، يمكنك فهم الآلية الحقيقية بعمق وكيف &amp;ldquo;تفكر&amp;rdquo; النماذج اللغوية الكبيرة.&lt;/p>
&lt;p>إذا كان لديك معرفة أساسية بـ C++ واهتمام قوي بتقنيات الذكاء الاصطناعي الحالية، فجرّب التحدي المتمثل في تطوير محرك الاستدلال الخاص بك. ستكون الأكواد المصدرية لمشاريع مثل GGML أو llama.cpp أفضل الكتب المدرسية الحية.&lt;/p>
&lt;p>&lt;strong>هيا بنا إذن، تخلص من بيئة تشغيل بايثون الثقيلة، ودعنا نُشغّل أحدث تقنيات الذكاء الاصطناعي مستخدمين عضلات C++!&lt;/strong>&lt;/p></description></item><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>كيف يجب أن ينجو المبرمجون في عصر الذكاء الاصطناعي؟</title><link>http://kenji.blog/ar/p/how-programmers-survive-in-ai-era/</link><pubDate>Fri, 11 Sep 2026 15:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/how-programmers-survive-in-ai-era/</guid><description>&lt;img src="http://kenji.blog/p/how-programmers-survive-in-ai-era/img/eyecatch.jpg" alt="Featured image of post كيف يجب أن ينجو المبرمجون في عصر الذكاء الاصطناعي؟" />&lt;h1 id="كيف-يجب-أن-ينجو-المبرمجون-في-عصر-الذكاء-الاصطناعي-نهاية-البرمجة-وبداية-فجر-جديد-لهندسة-البرمجيات">كيف يجب أن ينجو المبرمجون في عصر الذكاء الاصطناعي؟ نهاية البرمجة وبداية فجر جديد لهندسة البرمجيات
&lt;/h1>&lt;p>اعتبارًا من عام 2026، يشهد مجال تطوير البرمجيات فترة من التغيير الجذري غير المسبوق. حتى سنوات قليلة مضت، كان مفهوم &amp;ldquo;الذكاء الاصطناعي يكتب التعليمات البرمجية&amp;rdquo; يقتصر على كونه أداة مساعدة للمبرمجين، مثل إنشاء الأكواد النمطية (boilerplate) أو الإكمال التلقائي للدوال. ولكن، مع التطور المذهل للنماذج اللغوية الكبيرة (LLMs)، انقلبت الأمور رأسًا على عقب. فالذكاء الاصطناعي الحديث ليس مجرد &amp;ldquo;آلة كاتبة ذكية&amp;rdquo;؛ بل تحول إلى &amp;ldquo;مهندس مبتدئ مستقل&amp;rdquo; قادر على بناء أنظمة كاملة بشكل لحظي ومستقل، من الواجهة الأمامية إلى منطق الواجهة الخلفية، وتصميم مخطط قاعدة البيانات، وحتى بناء خطوط أنابيب CI/CD، بمجرد تزويده بمستند متطلبات.&lt;/p>
&lt;p>في مثل هذا العصر، كيف يمكننا نحن &amp;ldquo;المبرمجين&amp;rdquo; و&amp;quot;مهندسي البرمجيات&amp;quot; البقاء على قيد الحياة؟ مع الانكماش السريع للقيمة الاقتصادية لفعل &amp;ldquo;كتابة الأكواد&amp;rdquo; نفسه، فإن &amp;ldquo;المبرمج&amp;rdquo; الذي يعرف فقط بناء الجملة (الـ syntax) للغة برمجة معينة ويتقن واجهات برمجة التطبيقات (API) لإطار عمل محدد يتم إقصاؤه سريعًا من السوق.&lt;/p>
&lt;p>في هذا المقال، سنقوم بدراسة استراتيجية بقاء المبرمجين في عصر الذكاء الاصطناعي بتفصيل كبير من منظور تقني، رياضي، وفلسفي. هذا ليس مجرد نقاش حول المسار المهني، بل هو إعادة تعريف لهندسة البرمجيات كعلم في حد ذاته.&lt;/p>
&lt;hr>
&lt;h2 id="1-تاريخ-التجريد-abstraction-وإعادة-تعريف-البرمجة">1. تاريخ التجريد (Abstraction) وإعادة تعريف &amp;ldquo;البرمجة&amp;rdquo;
&lt;/h2>&lt;p>إذا نظرنا إلى تاريخ هندسة البرمجيات، سنجد أنه كان دائمًا تاريخًا من &amp;ldquo;التجريد&amp;rdquo;. لقد سعينا دائمًا لبناء طبقات من أجل وصف الأنظمة المعقدة بلغة أقرب إلى لغة البشر.&lt;/p>
&lt;p>كان علماء الكمبيوتر الأوائل يتفاعلون مع مفاتيح الأجهزة المادية مباشرة باستخدام البطاقات المثقبة، ويعطون التعليمات للكمبيوتر بلغة الآلة (سلسلة من الأصفار والآحاد). بعد ذلك، ظهرت لغة التجميع (Assembly)، والتي أتاحت للبشر التحكم في الأجهزة باستخدام اختصارات سهلة الفهم. ومع تقدم الزمن، ظهرت لغات عالية المستوى مثل C و Fortran، ونجحت في تغليف التفاصيل المعقدة للأجهزة مثل إدارة الذاكرة وسجلات وحدة المعالجة المركزية. ثم من خلال لغات حديثة مثل Java و Python و Ruby و TypeScript، أصبح بإمكان المبرمجين التركيز أكثر على &amp;ldquo;ما نريد أن يفعله الكمبيوتر (What)&amp;rdquo; بدلاً من &amp;ldquo;كيفية تشغيل الكمبيوتر (How)&amp;rdquo;.&lt;/p>
&lt;p>ظهور الذكاء الاصطناعي (LLM) هو التحول النموذجي الأحدث والأكبر في تاريخ التجريد هذا. إذا كان تطور لغات البرمجة بمثابة &amp;ldquo;إخفاء للأجهزة&amp;rdquo;، فإن تطور النماذج اللغوية الكبيرة هو &amp;ldquo;إخفاء لقواعد اللغة (syntax)&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">graph TD
A["لغة الآلة / البطاقات المثقبة (الأربعينيات)"] --> B["لغة التجميع (الخمسينيات)"]
B --> C["اللغات المترجمة عالية المستوى (السبعينيات)"]
C --> D["اللغات المدارة / اللغات النصية (التسعينيات)"]
D --> E["اللغة الطبيعية عبر LLMs (عشرينيات القرن الحادي والعشرين)"]
E --> F["وكلاء الذكاء الاصطناعي المستقلون (2026-)"]
style E fill:#f9f,stroke:#333,stroke-width:2px
style F fill:#fbb,stroke:#333,stroke-width:2px&lt;/div>
&lt;p>لقد ولى العصر الذي كان يقلق فيه المطورون بشأن تسرب الذاكرة أثناء التعامل مع المؤشرات، أو كتابة مئات الأسطر من الأكواد النمطية لتحليل ملفات JSON. أصبح استخدام اللغة الطبيعية (مثل اليابانية أو الإنجليزية)، وهي اللغة الأكثر تجريدًا بالنسبة للبشر، لتعريف الأنظمة هو معيار &amp;ldquo;البرمجة&amp;rdquo; في عام 2026.&lt;/p>
&lt;hr>
&lt;h2 id="2-النموذج-الرياضي-للإنتاجية-ركوب-موجة-النمو-الأسي">2. النموذج الرياضي للإنتاجية: ركوب موجة النمو الأُسي
&lt;/h2>&lt;p>دعونا نقيم التحسن في الإنتاجية الذي يجلبه الذكاء الاصطناعي كميًا باستخدام نموذج رياضي.
يمكن نمذجة الإنتاجية الفردية $P_{traditional}$ في تطوير البرمجيات التقليدية كمجموعة خطية من مستوى مهارة الفرد $S$، وخبرته في المجال $E$، وكفاءة الأدوات $T$.&lt;/p>
$$ P_{traditional} = c_1 \cdot S + c_2 \cdot E + c_3 \cdot T $$
&lt;p>ومع ذلك، في التطوير الحديث باستخدام الذكاء الاصطناعي، تعمل قدرة الذكاء الاصطناعي $A(t)$ كـ &amp;ldquo;مضاعف قوي (Multiplier)&amp;rdquo; يضخم القدرة البشرية. نظرًا لأن قدرات الذكاء الاصطناعي تنمو بشكل أُسي مع مرور الوقت $t$ (نسخة الذكاء الاصطناعي من قانون مور)، يمكن التعبير عن الإنتاجية في عصر الذكاء الاصطناعي $P_{AI}(t)$ بالمعادلة التالية:&lt;/p>
$$ P_{AI}(t) = \alpha \cdot S_{core} \cdot e^{\beta \cdot A(t)} $$
&lt;p>حيث تعني كل متغيرة ما يلي:&lt;/p>
&lt;ul>
&lt;li>$\alpha$: معامل الإنتاجية البشرية الأساسي&lt;/li>
&lt;li>$S_{core}$: &amp;ldquo;المهارات البشرية الأساسية&amp;rdquo; التي لا يمكن للذكاء الاصطناعي استبدالها (تصميم البنية، فهم متطلبات العمل، الأحكام الأخلاقية، إلخ)&lt;/li>
&lt;li>$A(t)$: القدرة المطلقة لنموذج الذكاء الاصطناعي في الوقت $t$ (عدد المعلمات، نافذة السياق، القدرة على الاستدلال)&lt;/li>
&lt;li>$\beta$: معامل يشير إلى مدى فعالية استخلاص الأدوات الخاصة بالذكاء الاصطناعي (جودة هندسة التلقين (Prompt Engineering) ومدى تطور سير العمل التعاوني مع الذكاء الاصطناعي)&lt;/li>
&lt;/ul>
&lt;p>الاستنتاج المهم الذي يمكن استخلاصه من هذه الصيغة هو أنه &lt;strong>في عالم تزداد فيه $A(t)$ بشكل أُسي، فإن المهارات التقليدية مثل سرعة الكتابة وحفظ لغات معينة سيكون لها تأثير ضئيل جدًا على الإنتاجية الإجمالية&lt;/strong>. بدلاً من ذلك، يصبح المعامل $\beta$، الذي يُستغل لمواكبة النمو الأُسي للذكاء الاصطناعي، و $S_{core}$، وهو المجال الذي لا يمكن للذكاء الاصطناعي تغطيته، العاملين المهيمنين اللذين يحددان القيمة السوقية للمهندس.&lt;/p>
&lt;hr>
&lt;h2 id="3-احتمالية-أتمتة-المهام-probability-of-automation">3. احتمالية أتمتة المهام (Probability of Automation)
&lt;/h2>&lt;p>إذن، ما هي المهام التي سيتم أتمتتها، وما هي المهام التي ستبقى في أيدي البشر؟
يمكن صياغة احتمالية أن تتم أتمتة مهمة معينة $T$ بالكامل بواسطة الذكاء الاصطناعي $P_{auto}(T)$ على النحو التالي:&lt;/p>
$$ P_{auto}(T) = 1 - \exp\left(-\lambda \cdot \frac{\text{Predictability}(T)}{\text{Complexity}(T) \times \text{Context Dependency}(T)}\right) $$
&lt;ul>
&lt;li>$\text{Predictability}(T)$: القدرة على التنبؤ بالمهمة (مدى وجود نمط في البيانات السابقة)&lt;/li>
&lt;li>$\text{Complexity}(T)$: تعقيد المهمة&lt;/li>
&lt;li>$\text{Context Dependency}(T)$: قوة &amp;ldquo;السياق الضمني (المعرفة الخاصة بالمجال أو العلاقات الإنسانية)&amp;rdquo; الذي تعتمد عليه المهمة&lt;/li>
&lt;li>$\lambda$: معدل التقدم التكنولوجي للذكاء الاصطناعي&lt;/li>
&lt;/ul>
&lt;p>المهام التي تتميز بقدرة عالية على التنبؤ واعتماد منخفض على السياق، مثل كتابة عمليات التوجيه (routing) في واجهات برمجة التطبيقات (API) أو إنشاء شاشات CRUD بسيطة، سيكون لها $P_{auto} \approx 1$ وسيتم أتمتتها بالكامل تقريبًا. من ناحية أخرى، المهام التي تعتمد بشكل كبير على السياق، مثل &amp;ldquo;كيفية دمج الأنظمة القديمة مع الخدمات المصغرة الجديدة بأمان&amp;rdquo; أو &amp;ldquo;كيفية تصميم تدفق مصادقة يلبي متطلبات الإدارة القانونية دون الإضرار بتجربة المستخدم&amp;rdquo;، يصعب أتمتتها.&lt;/p>
&lt;hr>
&lt;h2 id="4-العودة-من-بناء-الجملة-syntax-إلى-البنية-architecture">4. العودة من بناء الجملة (Syntax) إلى البنية (Architecture)
&lt;/h2>&lt;p>إن الفصل الواضح بين ما يجيده الذكاء الاصطناعي وما يجيده البشر هو شرط مطلق للبقاء.&lt;/p>
&lt;div class="mermaid">graph LR
Sub1["مجالات تفوق الذكاء الاصطناعي"]
Sub2["مجالات تفوق البشر"]
A["توليد الأكواد من المواصفات"] --> Sub1
B["إصلاح أخطاء بناء الجملة (Syntax) والشوائب (Bugs)"] --> Sub1
C["توليد الأكواد النمطية / الاختبارات"] --> Sub1
D["تحليل السجلات (Log) ومطابقة الأنماط"] --> Sub1
E["تصميم بنية النظام (Architecture)"] --> Sub2
F["حل المتطلبات الغامضة"] --> Sub2
G["التفاوض بين الفرق المختلفة"] --> Sub2
H["الأحكام الأخلاقية / تحمل المسؤولية"] --> Sub2&lt;/div>
&lt;p>يتفوق الذكاء الاصطناعي على البشر في &amp;ldquo;التحسين المحلي (Local Optimization)&amp;rdquo;. لا يمكن للبشر التغلب عليه من حيث السرعة والدقة في كتابة دالة واحدة، أو فئة (class) واحدة، أو وحدة واحدة. ومع ذلك، فإن الذكاء الاصطناعي ضعيف جدًا عندما يتعلق الأمر بـ &amp;ldquo;التحسين الشامل (Global Optimization)&amp;rdquo; أو &amp;ldquo;فقدان السياق (Missing Context)&amp;rdquo;.&lt;/p>
&lt;p>يجب على مبرمجي المستقبل أن يحولوا دورهم من &amp;ldquo;عمال يكتبون الأكواد&amp;rdquo; إلى &amp;ldquo;مهندسين معماريين ينسقون (orchestrate) المكونات التي لا حصر لها التي ينتجها الذكاء الاصطناعي&amp;rdquo;. النظر إلى النظام ككل، أين يمكن رسم حدود الخدمات المصغرة، وكيفية حل المفاضلة بين التوافر والاتساق في نظرية CAP بما يتماشى مع سياق العمل، وكيفية التحكم في الديون التقنية. هذه كلها مهام فكرية متقدمة لا يمكن أن يقوم بها إلا إنسان يفهم الصورة الكبيرة وأهداف العمل.&lt;/p>
&lt;hr>
&lt;h2 id="5-تحديد-المتطلبات-هو-هندسة-التلقين-prompt-engineering-الحقيقية">5. تحديد المتطلبات هو &amp;ldquo;هندسة التلقين (Prompt Engineering) الحقيقية&amp;rdquo;
&lt;/h2>&lt;p>غالبًا ما يُساء فهم مصطلح &amp;ldquo;هندسة التلقين&amp;rdquo; الذي نسمعه كثيرًا هذه الأيام على أنه &amp;ldquo;اختراق لخداع الذكاء الاصطناعي للحصول على المخرجات المطلوبة&amp;rdquo;. ومع ذلك، فإن جوهر هندسة التلقين في تطوير البرمجيات هو بلا شك &lt;strong>&amp;ldquo;هندسة المتطلبات المتقدمة (Requirements Engineering)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>من أجل توجيه الذكاء الاصطناعي باللغة الطبيعية لإنتاج البرنامج المطلوب كما هو مخطط، يجب التعبير عن العناصر التالية بشكل دقيق:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>الهدف (Why)&lt;/strong>: لماذا هذه الميزة مطلوبة؟ ما هي القيمة التجارية؟&lt;/li>
&lt;li>&lt;strong>القيود (Constraints)&lt;/strong>: متطلبات الأداء (زمن الوصول، الإنتاجية)، متطلبات الأمان، وقيود التكلفة.&lt;/li>
&lt;li>&lt;strong>الحالات الطرفية (Edge Cases)&lt;/strong>: العمليات البديلة (fallback) عندما يقوم المستخدم بإدخال بيانات غير متوقعة.&lt;/li>
&lt;li>&lt;strong>الواجهات (Interfaces)&lt;/strong>: مواصفات التكامل مع الأنظمة الحالية.&lt;/li>
&lt;/ol>
&lt;p>التعليمات الغامضة (prompts) ستؤدي فقط إلى بناء أنظمة غامضة وهشة. إن القدرة على الاستماع بعمق لمعرفة &amp;ldquo;ما يريده العميل حقًا&amp;rdquo;، وتنظيم المتطلبات المتناقضة، وإنشاء مستند مواصفات (prompt) خالٍ من العيوب المنطقية؛ هذه هي &amp;ldquo;مهارة البرمجة&amp;rdquo; الأقوى في عصر الذكاء الاصطناعي. سيقضي المبرمجون وقتًا أقل في مواجهة محررات الأكواد، ووقتًا أطول أمام Notion أو ملفات Markdown، لوصف الشكل الذي يجب أن يكون عليه النظام بدقة نصية.&lt;/p>
&lt;hr>
&lt;h2 id="6-التفوق-الساحق-لمعرفة-المجال-domain-knowledge">6. التفوق الساحق لمعرفة المجال (Domain Knowledge)
&lt;/h2>&lt;p>نظرًا لأن الذكاء الاصطناعي يتعلم من الأكواد مفتوحة المصدر والوثائق العامة حول العالم، فهو على دراية واسعة بتقنيات الويب والخوارزميات العامة. لكن هناك بيانات لا يمكن للذكاء الاصطناعي الوصول إليها. وهي &amp;ldquo;قواعد العمل الخاصة بشركتك&amp;rdquo; و &amp;ldquo;المعرفة العميقة بمجال معين (مثل الطب، والتمويل، والتصنيع، وغيرها)&amp;rdquo;.&lt;/p>
&lt;p>على سبيل المثال، لنفترض أننا نطور نظام سجلات طبية إلكترونية في شركة طبية ناشئة. قد يعرف الذكاء الاصطناعي &amp;ldquo;كيفية إنشاء واجهة مستخدم (UI) جدولية باستخدام React&amp;rdquo; أو &amp;ldquo;هياكل البيانات العامة لـ HL7 FHIR&amp;rdquo;. ومع ذلك، فإنه لم يتعلم المعرفة الضمنية مثل &amp;ldquo;في قسم معين من مستشفى أ، ما هو الترتيب الذي يجب أن يرى به الأطباء بيانات المرضى، وما هي واجهة المستخدم التي تقلل من مخاطر الأخطاء الطبية&amp;rdquo;.&lt;/p>
&lt;p>في عالم أصبحت فيه التكنولوجيا نفسها سلعة (commoditized)، تُخلق القيمة الحقيقية للمهندس عند تقاطع &amp;ldquo;التكنولوجيا&amp;rdquo; و&amp;quot;مجال العمل (business domain)&amp;quot;. لن نعتمد فقط على المهارات التقنية، بل الأشخاص الذين يمتلكون معرفة متخصصة عميقة في مجالات معينة مثل الطب، أو التمويل، أو الخدمات اللوجستية، أو الترفيه، ويمكنهم استخدام أداة قوية مثل الذكاء الاصطناعي لحل المشكلات في تلك المجالات، هم الذين سيقودون السوق في المستقبل.&lt;/p>
&lt;hr>
&lt;h2 id="7-مشكلة-العربة-في-تطوير-البرمجيات-من-يتحمل-المسؤولية">7. &amp;ldquo;مشكلة العربة&amp;rdquo; في تطوير البرمجيات: من يتحمل المسؤولية؟
&lt;/h2>&lt;p>مع تزايد اعتمادنا على الذكاء الاصطناعي، نواجه قضايا فلسفية وأخلاقية خطيرة. وهي مشكلة &amp;ldquo;تحديد المسؤولية&amp;rdquo; في هندسة البرمجيات.&lt;/p>
&lt;p>إذا تسببت الأكواد التي أنشأها الذكاء الاصطناعي بشكل مستقل في خطأ فادح (bug) في بيئة الإنتاج، مما أدى إلى خسارة ملايين الدولارات للشركة، أو تسبب في عطل في نظام طبي يمس حياة الإنسان، فمن سيتحمل المسؤولية؟ هل الشركة التي طورت نموذج الذكاء الاصطناعي؟ أم المهندس الذي أدخل الموجه (prompt)؟ لا يمكننا &amp;ldquo;طرد&amp;rdquo; أو &amp;ldquo;اعتقال&amp;rdquo; الذكاء الاصطناعي.&lt;/p>
&lt;p>إن دور &amp;ldquo;الإنسان&amp;rdquo; ككيان يتحمل &amp;ldquo;المسؤولية القانونية والأخلاقية (Accountability)&amp;rdquo; تجاه تأثير الأنظمة على المجتمع لن يختفي مهما تقدمت التكنولوجيا. في الواقع، كلما أصبحت عملية إنشاء الأكواد بمثابة صندوق أسود، زاد العبء الملقى على عاتق الإنسان ليتحمل مسؤولية كبيرة كـ &amp;ldquo;مانح الموافقة النهائية (Approver)&amp;rdquo; و&amp;quot;المشرف (Supervisor)&amp;quot; على النظام.&lt;/p>
&lt;p>يجب على الإنسان التدقيق فيما إذا كانت البنية والأكواد التي يقدمها الذكاء الاصطناعي تلبي معايير الأمان، وليس بها مشاكل أخلاقية (مثل التحيز)، وتلتزم باللوائح والقوانين، ومن ثم إعطاء الموافقة النهائية. هذا الفعل المتمثل في &amp;ldquo;تحمل المسؤولية&amp;rdquo; نفسه سيصبح جزءًا مهمًا من عمل المهندس.&lt;/p>
&lt;hr>
&lt;h2 id="8-البرمجة-الزوجية-مع-الذكاء-الاصطناعي-وإدارة-الحمل-المعرفي-cognitive-load">8. البرمجة الزوجية مع الذكاء الاصطناعي وإدارة الحمل المعرفي (Cognitive Load)
&lt;/h2>&lt;p>عند العمل مع الذكاء الاصطناعي، تتغير طبيعة &amp;ldquo;الحمل المعرفي (Cognitive Load)&amp;rdquo; البشري أيضًا. الحمل المعرفي لكتابة الكود من الصفر يختلف تمامًا عن الحمل المعرفي لـ &amp;ldquo;قراءة ومراجعة&amp;rdquo; مئات الأسطر من الأكواد المجهولة التي يولدها الذكاء الاصطناعي.&lt;/p>
&lt;p>وفقًا لنظرية الحمل المعرفي في علم النفس، عند معالجة معلومات معقدة لا تتناسب مع المخططات الحالية (بنية المعرفة في أدمغتنا)، تنفد الذاكرة العاملة لدى الإنسان بسرعة. فالأكواد التي يولدها الذكاء الاصطناعي قد تحتوي أحيانًا على تحسينات متقدمة لا يمكن للبشر التفكير فيها، ولكنها في نفس الوقت قد تحتوي على &amp;ldquo;هلوسات (Hallucinations)&amp;rdquo; تتجاهل السياق.&lt;/p>
&lt;p>لمنع ذلك، يجب وضع نظام لعملية المراجعة مع الذكاء الاصطناعي.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant H as "المهندس البشري (مهندس معماري)"
participant A as "وكيل الذكاء الاصطناعي"
participant S as "CI/CD والاختبار"
H->>A: "تحديد متطلبات وقيود صارمة"
A->>H: "اقتراح بنية النظام والأكواد الأولية"
Note over H,A: مرحلة المراجعة: حمل معرفي عالٍ
H->>A: "نقد خيارات التصميم، طلب إعادة هيكلة الأكواد"
A->>S: "توليد الأكواد النهائية ودفعها (Push)"
S-->>H: "نتائج الاختبارات الآلية والتحليل الثابت"
H->>H: "الموافقة النهائية وتحمل المسؤولية"&lt;/div>
&lt;p>يحتاج البشر إلى صقل مهاراتهم إلى أقصى حد في &amp;ldquo;القراءة السريعة واكتشاف العيوب المنطقية بشكل فوري (Code Reading &amp;amp; Auditing)&amp;rdquo; أكثر من مهارة &amp;ldquo;الكتابة&amp;rdquo;. تتزايد أهمية التطوير القائم على الاختبار (TDD) في عصر الذكاء الاصطناعي. قبل السماح للذكاء الاصطناعي بكتابة التعليمات البرمجية، سيصبح النهج السائد هو أن يكتب الإنسان أو ذكاء اصطناعي آخر أكواد اختبار صارمة، ويطلب من الذكاء الاصطناعي تعديل أكواده حتى ينجح في تلك الاختبارات.&lt;/p>
&lt;hr>
&lt;h2 id="9-استراتيجيات-بقاء-ملموسة-ما-الذي-يجب-أن-تتعلمه-غدا">9. استراتيجيات بقاء ملموسة: ما الذي يجب أن تتعلمه غدًا؟
&lt;/h2>&lt;p>بناءً على التحليل أعلاه، نقدم خطة عمل ملموسة للمبرمجين للبقاء على قيد الحياة في عصر الذكاء الاصطناعي.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>أعد تعلم &amp;ldquo;أساسيات&amp;rdquo; التكنولوجيا بشكل كامل&lt;/strong>: اترك كيفية استخدام أطر العمل (frameworks) للذكاء الاصطناعي. ولكن، لا غنى عن الفهم العميق لآليات نظام التشغيل (OS)، وبروتوكولات الشبكة (TCP/IP، HTTP/3)، والهياكل الداخلية لقواعد البيانات (B-Tree، مستويات عزل المعاملات)، وهياكل البيانات والخوارزميات. لكي تتمكن من الحكم على ما إذا كانت مخرجات الذكاء الاصطناعي صحيحة، فإن الأساس القوي في علوم الكمبيوتر أمر ضروري.&lt;/li>
&lt;li>&lt;strong>إتقان البنية السحابية (Cloud Architecture) والأنظمة الموزعة&lt;/strong>: ركز على كيفية الجمع بين الموارد السحابية مثل AWS و GCP و Azure لبناء أنظمة قابلة للتوسع، بدلاً من التركيز على الأكواد الفردية. افهم مفهوم البنية التحتية ككود (IaC) مثل Terraform، وطور القدرة على تصميم النظام بأكمله ككود.&lt;/li>
&lt;li>&lt;strong>كن خبيرًا في مجال عملك (Business Domain)&lt;/strong>: تعلم بعمق نماذج الأعمال، واللوائح القانونية، وسيكولوجية سلوك المستخدم في الصناعة التي تنتمي إليها. تجاوز حدود المهندس وامتلك منظورًا أقرب إلى مدير المنتج (PM).&lt;/li>
&lt;li>&lt;strong>اصقل مهارات التواصل والتيسير (Facilitation)&lt;/strong>: عملية حل &amp;ldquo;الغموض&amp;rdquo; بين البشر وبناء التوافق هي عملية لا يمكن للذكاء الاصطناعي استبدالها. إن المهارات الشخصية (Soft skills) للتواصل مع أصحاب المصلحة واكتشاف التحديات الحقيقية ستصبح المهارات الأكثر قيمة.&lt;/li>
&lt;li>&lt;strong>استخدم الذكاء الاصطناعي كـ &amp;ldquo;زميل عمل&amp;rdquo; إلى أقصى حد&lt;/strong>: لا تخف من تطور أدوات الذكاء الاصطناعي، بل استخدمها كأقوى أسلحتك. استخدم أحدث النماذج اللغوية الكبيرة (LLMs) ووكلاء البرمجة الذكية يوميًا، وقم ببناء &amp;ldquo;معرفة ضمنية&amp;rdquo; حول أين يفشل الذكاء الاصطناعي وكيفية ابتكار الموجهات (prompts) لاستخراج أفضل أداء منه.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="الخلاصة-لا-تخف-بل-اركب-الموجة">الخلاصة: لا تخف، بل اركب الموجة
&lt;/h2>&lt;p>أتمتة البرمجة بواسطة الذكاء الاصطناعي لا تعني &amp;ldquo;موت&amp;rdquo; مهنة المبرمج. بل إنها &lt;strong>&amp;ldquo;نهضة (Renaissance)&amp;rdquo;&lt;/strong> تحررنا من &amp;ldquo;المهام غير الأساسية&amp;rdquo; في تطوير البرمجيات، مثل إصلاح الأخطاء المطبعية، واستكشاف أخطاء إعداد البيئة، وكتابة الأكواد النمطية المملة.&lt;/p>
&lt;p>على مر التاريخ، عند ظهور أنوال النسيج الآلية، أو برامج الجداول الإلكترونية (مثل Excel)، ساد التشاؤم بأن الوظائف ستختفي. ولكن في الواقع، مع تحسن الإنتاجية بشكل كبير، تم خلق طلب جديد، وظهرت وظائف أكثر تقدماً. سيحدث الشيء نفسه في عالم البرمجيات. من خلال القدرة على &amp;ldquo;بناء الأنظمة بتكلفة منخفضة&amp;rdquo;، ستتغلغل البرمجيات في كل المجالات التي لم تكن مزودة بتكنولوجيا المعلومات من قبل بسبب التكلفة، وستتوسع التحديات (What) التي يجب على المهندسين حلها إلى ما لا نهاية.&lt;/p>
&lt;p>تُتاح لنا نحن المبرمجين اليوم فرصة التطور من حرفيين يكتبون الأكواد إلى &amp;ldquo;قادة أوركسترا&amp;rdquo; يوجهون ذكاءً هائلاً متمثلاً في الذكاء الاصطناعي. بدلاً من البقاء على الشاطئ خوفًا من موجة التكنولوجيا، دعونا نركب هذه الموجة في وقت مبكر وننطلق في رحلة لإنشاء أنظمة أكبر وأكثر قيمة. إن عصر الذكاء الاصطناعي هو بالضبط العصر الذي تبدأ فيه &amp;ldquo;الهندسة&amp;rdquo; الحقيقية.&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>