<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LLM on kenji.blog</title><link>http://kenji.blog/ru/tags/llm/</link><description>Recent content in LLM on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 11:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ru/tags/llm/index.xml" rel="self" type="application/rss+xml"/><item><title>Использование llama.cpp и введение в кастомизацию на C++</title><link>http://kenji.blog/ru/p/llama-cpp-cxx-customization/</link><pubDate>Fri, 11 Sep 2026 11:00:00 +0900</pubDate><guid>http://kenji.blog/ru/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>В последние годы эволюция больших языковых моделей (LLM) поражает воображение, и сфера их применения расширяется с каждым днем. Однако для запуска моделей с миллиардами и десятками миллиардов параметров в локальной среде обычно требуются высокопроизводительные GPU с огромным объемом 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 и квантования, а также способы интеграции и кастомизации LLM в ваших собственных приложениях с использованием C++ API.&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++ разработчиком Георгием Гергановым. Изначально он был создан для быстрого запуска модели 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> является библиотека тензорных вычислений &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>: При загрузке весов модели в память используется системный вызов OS &lt;code>mmap&lt;/code>, что позволяет избежать полной загрузки в RAM, обеспечивая быстрый запуск и экономию памяти.&lt;/li>
&lt;li>&lt;strong>Тщательная оптимизация SIMD-инструкций&lt;/strong>: Для сверхбыстрого перемножения матриц используются специфичные для CPU наборы инструкций, такие как 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, используют архитектуру авторегрессионного (Auto-regressive) декодера Transformer. Ядром генерации текста является механизм &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$, так как обрабатывается по одному токену), то есть &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), который является частью матрицы весов $W$ в формате FP16. Этот блок аппроксимируется 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>Если входной вектор $x$ также квантуется как $x_i \approx \Delta_x \times q_{x, i}$ при вычислении скалярного произведения $y = w \cdot x$ с использованием квантованных весов, то:&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["Пользовательский ввод (String)"] --> B["Токенизатор llama.cpp"]
B --> C["ID токенов (int32 массив)"]
C --> D["Буфер контекста (KV Cache)"]
D --> E["Вычислительный граф ggml"]
E --> F["Слои Transformer"]
subgraph "Движок ggml"
F --> G["Self-Attention (RoPE)"]
G --> H["Feed Forward Network"]
H --> F
end
F --> I["Логиты (Размер словаря)"]
I --> J["Сэмплер (Temperature, Top-K, Top-P)"]
J --> K["Выбранный ID токена"]
K --> L["Детокенизатор llama.cpp"]
L --> M["Выходная строка"]
K -. "Авторегрессионный цикл" .-> D&lt;/div>
&lt;p>Генерация текста — это авторегрессионный цикл: каждый раз, когда выводится один токен, он добавляется в KV Cache как следующий вход и снова проходит через вычислительный граф.&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 является наиболее стандартным подходом. Включение платформозависимого ускорителя (бэкенда) позволяет ускорить вычисления.&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>build/bin/&lt;/code> будут сгенерированы исполняемые файлы, такие как &lt;code>llama-cli&lt;/code>, и библиотека &lt;code>llama&lt;/code> (а также библиотека &lt;code>ggml&lt;/code>) для линковки через C++ API, о котором пойдет речь ниже.&lt;/p>
&lt;hr>
&lt;h2 id="5-введение-в-кастомизацию-на-c-использование-api-llamacpp">5. Введение в кастомизацию на C++: Использование API llama.cpp
&lt;/h2>&lt;p>С этого момента мы перейдем к главной теме — управлению llama.cpp из кода на C++.
Чтобы не просто использовать инструмент командной строки, а встроить LLM в собственное приложение (например, игровой движок, десктопное приложение, встроенную систему и т. д.), необходимо напрямую обращаться к C++ API.&lt;/p>
&lt;p>llama.cpp предоставляет интерфейс на языке C в основном через заголовочный файл &lt;code>llama.h&lt;/code>. При вызове из C++ также используется этот интерфейс.&lt;/p>
&lt;h3 id="51-минимально-необходимые-инклуды-и-настройки">5.1 Минимально необходимые инклуды и настройки
&lt;/h3>&lt;p>При использовании llama.cpp в собственном проекте добавьте следующие &lt;code>#include&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;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-кэш) для инференса.&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, используемых для инференса
&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 не понимают текст напрямую, а обрабатывают его как последовательность целочисленных ID (токенов). Входную строку необходимо преобразовать в токены.&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">// Преобразование строки в массив ID токенов
&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">// Инициализация структуры для пакетной обработки (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">// Настройка вывода логитов (результатов предсказания) только для последнего токена промпта
&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">// Очистка
&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>Этот код реализует собственный цикл инференса с использованием базового API llama.cpp.
Группа токенов управляется с помощью структуры &lt;code>llama_batch&lt;/code>, а прямой проход (forward pass) нейронной сети выполняется с помощью &lt;code>llama_decode&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="6-продвинутые-примеры-кастомизации-управление-логитами-и-штрафами-на-c">6. Продвинутые примеры кастомизации: Управление логитами и штрафами на 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">// Получение массива необработанных логитов сразу после инференса и перед выполнением сэмплирования
&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">// Список ID запрещенных токенов (например, 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 (логит в минус бесконечность)
&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++ API, становится возможным &lt;strong>&amp;ldquo;вмешательство на микросекундном уровне на каждом цикле инференса&amp;rdquo;&lt;/strong>, что трудно реализовать или влечет за собой большие накладные расходы при использовании LangChain или Python.&lt;/p>
&lt;hr>
&lt;h2 id="7-секреты-настройки-производительности">7. Секреты настройки производительности
&lt;/h2>&lt;p>После завершения реализации на C++, вот несколько контрольных точек для максимизации скорости в преддверии запуска в производственную среду (production).&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Оптимизация пакетной обработки (Batching):&lt;/strong> При одновременной обработке запросов от нескольких пользователей включите несколько последовательностей в &lt;code>llama_batch&lt;/code> и вызовите &lt;code>llama_decode&lt;/code> один раз (Continuous Batching). Это позволяет объединить обращения к памяти и значительно повысить пропускную способность.&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>.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-в-заключение">8. В заключение
&lt;/h2>&lt;p>В этой статье мы подробно рассмотрели всё: от математической базы &lt;code>llama.cpp&lt;/code> и разбора его архитектуры до создания кастомного движка инференса с использованием C++ API.&lt;/p>
&lt;p>Хотя экосистема Python очень удобна для прототипирования, в производственных средах, где требуется деплой на edge-устройства, интеграция в игры или обработка в реальном времени, прямое управление через &lt;code>llama.cpp&lt;/code> на базе C/C++ демонстрирует подавляющее превосходство.&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 Official Repository&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/ggml" target="_blank" rel="noopener"
>ggml - Tensor Library&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 в среде Windows</title><link>http://kenji.blog/ru/p/local-llm-windows-2026/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/ru/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 в среде Windows" />&lt;h1 id="1-введение-почему-именно-сейчас-локальные-llm-на-windows">1. Введение: Почему именно сейчас локальные LLM на Windows?
&lt;/h1>&lt;p>По состоянию на 2026 год эволюция генеративного ИИ и больших языковых моделей (LLM) демонстрирует серьезный сдвиг парадигмы — от гигантских облачных API-сервисов к «локальным LLM», работающим на персональных ПК или в локальной среде (on-premise). Облачные ИИ, такие как GPT-5 от OpenAI или Claude 3.5 от Anthropic, очень мощны, но компании и частные лица не могут отправлять абсолютно все свои данные в облако. С точки зрения конфиденциальности, безопасности, задержек, а также долгосрочной и устойчивой стоимости, спрос на локальные LLM сейчас высок как никогда.&lt;/p>
&lt;p>В частности, экосистема локальных LLM для среды Windows переживает поразительное развитие. Еще несколько лет назад здравый смысл подсказывал, что «разработка и запуск ИИ означает Linux», но в 2026 году Windows превратилась в очень мощную и удобную платформу для ИИ.&lt;/p>
&lt;p>В этой статье представлено полное руководство по созданию, развертыванию и оптимизации локальных LLM в среде Windows с учетом последних технологических тенденций 2026 года. Мы детально и всесторонне рассмотрим всё: от простой настройки для новичков с помощью Ollama до экстремальной оптимизации для продвинутых пользователей с использованием llama.cpp, а также глубокого понимания архитектуры, математического подхода к расчету VRAM и локального файнтюнинга.&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), объединяющий метаданные и тензоры в один файл, стал абсолютным стандартом де-факто. Теперь достаточно скачать один файл с Hugging Face, чтобы запустить его в любой среде.&lt;/li>
&lt;li>&lt;strong>Демократизация архитектуры MoE (Mixture of Experts)&lt;/strong>: Выпущено множество небольших, но высокопроизводительных моделей MoE. Активируя при выводе (инференсе) лишь часть «экспертов», они достигают производительности, сопоставимой с гигантскими моделями, при этом снижая вычислительную нагрузку на потребительские ПК.&lt;/li>
&lt;li>&lt;strong>Высокий уровень абстракции и оптимизации движков вывода&lt;/strong>: Такие инструменты, как Ollama, LM Studio и AnythingLLM, стали настолько совершенными, что пользователям больше не нужно беспокоиться о сложных зависимостях, вроде установки драйверов CUDA. Кроме того, нативная поддержка FlashAttention 3 для Windows привела к резкому увеличению скорости инференса.&lt;/li>
&lt;li>&lt;strong>Использование NPU и развитие Windows Copilot+ PC&lt;/strong>: Технология запуска небольших LLM (SLM: Small Language Models) с низким энергопотреблением на ноутбуках без GPU с использованием встроенного NPU (Neural Processing Unit) достигла стадии практического применения.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="2-требования-к-аппаратному-обеспечению-и-подготовка-ос">2. Требования к аппаратному обеспечению и подготовка ОС
&lt;/h1>&lt;p>Чтобы локальная LLM работала с приемлемой скоростью (от 15 до 30+ токенов в секунду), самое важное — правильно выбрать аппаратное обеспечение.&lt;/p>
&lt;h2 id="21-рекомендуемая-конфигурация-оборудования">2.1 Рекомендуемая конфигурация оборудования
&lt;/h2>&lt;p>С развитием ИИ-ПК меняются и системные требования.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>ОС&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 ГБ или больше. Пропускная способность основной памяти (МБ/с) становится решающим узким местом при инференсе на CPU или переносе (offload) вычислений. В идеале использовать высокоскоростную память DDR5-6000 или выше.&lt;/li>
&lt;li>&lt;strong>GPU&lt;/strong>: Серия NVIDIA RTX 4000/5000. В локальных LLM наиболее важна не вычислительная мощность, а «объем VRAM».
&lt;ul>
&lt;li>&lt;strong>Начальный уровень&lt;/strong>: RTX 4060 Ti (версия 16 ГБ) — лучшее соотношение цены и качества. Идеально подходит для моделей класса 8B–14B.&lt;/li>
&lt;li>&lt;strong>Средний уровень&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 ГБ) — необходимы для запуска квантованных моделей класса 30B–70B.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Накопитель&lt;/strong>: NVMe SSD PCIe Gen4 или Gen5. Резко сокращает время загрузки моделей объемом в десятки гигабайт.&lt;/li>
&lt;/ul>
&lt;h2 id="22-настройка-wsl2-windows-subsystem-for-linux-2">2.2 Настройка WSL2 (Windows Subsystem for Linux 2)
&lt;/h2>&lt;p>Хотя многие инструменты с графическим интерфейсом работают в Windows нативно, WSL2 очень удобен для разработки на Python, компиляции новейших инструментов и файнтюнинга LoRA, о котором пойдет речь ниже. В последних версиях среды Windows 11 достаточно установить драйвер NVIDIA на хосте, чтобы прозрачно использовать GPU (CUDA) из WSL2.&lt;/p>
&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;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"># Обновление ядра&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-и-механизм-вывода-инференса">3. Архитектура локальных LLM и механизм вывода (инференса)
&lt;/h1>&lt;p>Понимание внутренней структуры того, как модель генерирует текст в локальной среде, очень полезно для устранения неполадок и оптимизации.&lt;/p>
&lt;p>Следующая диаграмма Mermaid показывает типичный конвейер инференса локальной LLM.&lt;/p>
&lt;div class="mermaid">graph TD
User["Пользовательский ввод (Промпт)"] --> Tokenizer["Токенизатор (Tokenizer)"]
Tokenizer --> Embedding["Слой встраивания (Embedding)"]
subgraph "Transformer Block (x Layers)"
Embedding --> Attn["Механизм внутреннего внимания (Self-Attention)"]
Attn --> KVCache["KV-кэш (Хранение Key/Value)"]
Attn --> FFN["Сеть прямой связи (FFN)"]
end
FFN --> Logits["Вычисление логитов (Logits)"]
Logits --> Sampler["Сэмплер (Temperature, Top-K, Top-P)"]
Sampler --> OutputToken["Выходной токен"]
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>: Фаза, в которой весь введенный промпт обрабатывается и понимается за один раз. Поскольку возможны параллельные вычисления, вычислительная мощность GPU (FLOPS) напрямую влияет на скорость. Если промпт длинный, эта фаза может занять несколько секунд.&lt;/li>
&lt;li>&lt;strong>Фаза Decode (Генерация токенов)&lt;/strong>: Фаза, в которой предсказывается по одному токену за раз, и результат передается на следующий вход (авторегрессия). Поскольку параллельные вычисления на этом этапе ограничены, пропускная способность VRAM (Memory Bandwidth) становится решающим узким местом.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="4-расчет-потребления-vram-и-математическое-понимание-размера-модели">4. Расчет потребления VRAM и математическое понимание размера модели
&lt;/h1>&lt;p>Чтобы правильно определить, «какая модель будет работать на моем ПК», необходимо понимать формулу расчета VRAM. Если из-за нехватки VRAM происходит откат (фолбэк) к системной памяти (RAM), скорость вывода падает в 10–100 раз.&lt;/p>
&lt;h2 id="41-базовый-объем-vram-на-основе-размера-параметров">4.1 Базовый объем VRAM на основе размера параметров
&lt;/h2>&lt;p>Это объем памяти, необходимый для загрузки весов модели в VRAM.
Он рассчитывается с использованием размера модели $P$ (количество параметров, единица измерения: 1 миллиард = 1B) и количества байт на 1 параметр $B$.&lt;/p>
$$
V_{base} = P \times B \quad \text{(ГБ)}
$$
&lt;p>Например, при загрузке модели с 8B (8 миллиардами) параметров в формате FP16 (полуточные числа с плавающей запятой, 16 бит = 2 байта):&lt;/p>
$$
V_{base} = 8 \times 2 = 16 \text{ ГБ}
$$
&lt;p>Другими словами, даже на GPU с 16 ГБ VRAM вы достигнете предела уже только при загрузке модели.&lt;/p>
&lt;h2 id="42-магия-квантования-quantization">4.2 Магия квантования (Quantization)
&lt;/h2>&lt;p>Вот здесь в игру вступает «квантование». Снижая точность параметров, размер модели кардинально уменьшается. В случае наиболее распространенного 4-битного квантования (например, Q4_K_M), на один параметр приходится в среднем около 0.55 байта.&lt;/p>
$$
V_{base\_4bit} = 8 \times 0.55 = 4.4 \text{ ГБ}
$$
&lt;p>Таким образом, имея 16 ГБ VRAM, вы сможете запускать модель 8B с достаточным запасом памяти.&lt;/p>
&lt;h2 id="43-расчет-kv-кэша-с-поддержкой-gqa">4.3 Расчет KV-кэша (с поддержкой GQA)
&lt;/h2>&lt;p>Во время вывода (инференса) «KV-кэш», предназначенный для сохранения прошлого контекста, потребляет 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>Упростив это, мы можем произвести вычисления с помощью количества голов Key и Value $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{ ГБ}$&lt;/p>
&lt;p>Обратите внимание, что чем больше длина контекста $s$, тем больше необходимо VRAM, и этот рост линеен.&lt;/p>
&lt;hr>
&lt;h1 id="5-практика-1-самая-быстрая-и-короткая-настройка-с-использованием-ollama">5. Практика 1: Самая быстрая и короткая настройка с использованием Ollama
&lt;/h1>&lt;p>Теперь, поняв теорию, давайте действительно запустим LLM в среде Windows.
По состоянию на 2026 год, самым удобным инструментом является «Ollama». Он предоставляет интуитивно понятный CLI в стиле Docker.&lt;/p>
&lt;h2 id="51-установка-и-запуск">5.1 Установка и запуск
&lt;/h2>&lt;ol>
&lt;li>Скачайте и запустите установщик для Windows с &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>При первом запуске произойдет загрузка модели. По завершении вы сможете вести диалог прямо в терминале.&lt;/p>
&lt;h2 id="52-создание-собственного-ии-с-помощью-modelfile">5.2 Создание собственного ИИ с помощью Modelfile
&lt;/h2>&lt;p>Вы можете легко создать ИИ с определенной персоной. Создайте файл &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">Вы — выдающийся старший инженер-программист (Senior Software Engineer).
&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>.
В настройках бэкенда таких расширений для VS Code, как Cursor или Continue.dev, просто укажите этот URL и имя модели (например, &lt;code>SeniorDev&lt;/code>), чтобы получить мощного локального помощника по программированию абсолютно бесплатно.&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>В среде Windows лучше всего собирать из исходного кода, используя 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 (Генерация с дополненной выборкой), воспользуйтесь графическими интерфейсами.&lt;/p>
&lt;h2 id="71-lm-studio">7.1 LM Studio
&lt;/h2>&lt;p>LM Studio — это отличное приложение, которое объединяет поиск моделей, их загрузку, предварительную проверку системных требований и пользовательский интерфейс для чата в одном месте. Просто нажав кнопку &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 --> EmbedModel["Модель встраивания (Embedding)"]
EmbedModel --> VectorDB["Векторная база данных"]
UserQuery["Запрос пользователя"] --> EmbedQuery["Встраивание запроса"]
EmbedQuery --> VectorDB
VectorDB --> |"Поиск по сходству"| RetrievedDocs["Извлеченные релевантные документы"]
UserQuery --> PromptBuilder["Генератор промпта"]
RetrievedDocs --> PromptBuilder
PromptBuilder --> LocalLLM["Локальная LLM"]
LocalLLM --> Answer["Итоговый ответ"]&lt;/div>
&lt;p>Используя десктопную версию AnythingLLM (для Windows), достаточно указать Ollama (как LLM и Embedding) на экране настроек и настроить использование локальной векторной БД (LanceDB), и эта архитектура будет готова за несколько минут. Так рождается приватный ИИ, который совершенно не отправляет данные наружу.&lt;/p>
&lt;hr>
&lt;h1 id="8-файнтюнинг-на-windows-в-wsl2-lora">8. Файнтюнинг на Windows в WSL2 (LoRA)
&lt;/h1>&lt;p>Если вы хотите не только локально запускать модели, но и обучать их на своих собственных данных, чтобы сделать умнее, вы можете использовать файнтюнинг с помощью LoRA (Low-Rank Adaptation). По состоянию на 2026 год, благодаря библиотеке под названием &amp;ldquo;Unsloth&amp;rdquo;, обучение 8B-модели в среде Windows WSL2 с 16 ГБ VRAM завершается всего за несколько часов.&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 до предела, так что скорость обучения примерно удваивается, а потребление VRAM снижается вдвое по сравнению со стандартными библиотеками Hugging Face. Просто запустите Jupyter Notebook, загрузите свой набор данных (в формате JSONL), и вы сможете выполнить несколько эпох обучения даже на RTX 4060 Ti с VRAM от 12 ГБ до 16 ГБ.&lt;/p>
&lt;hr>
&lt;h1 id="9-устранение-проблем-с-производительностью-troubleshooting">9. Устранение проблем с производительностью (Troubleshooting)
&lt;/h1>&lt;p>Часто возникающие проблемы и способы их решения.&lt;/p>
&lt;h3 id="1-скорость-вывода-крайне-низкая-1-2-tokenss">1. Скорость вывода крайне низкая (1-2 tokens/s)
&lt;/h3>&lt;p>&lt;strong>Причина&lt;/strong>: Модель не помещается в VRAM и выгружается (offload) в системную память (RAM).
&lt;strong>Решение&lt;/strong>: Проверьте параметр «Выделенная память графического процессора» в Диспетчере задач. Если он достиг предела, уменьшите размер контекста (&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>: Несоответствие шаблона промпта или неподдерживаемая модель.
&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 в среде Windows больше не является привилегией лишь избранных инженеров. Благодаря формату GGUF, ставшему стандартом де-факто, появлению продуманных экосистем, таких как Ollama и LM Studio, а также аппаратной оптимизации, включая FlashAttention, каждый может легко получить ИИ-среду корпоративного уровня.&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>«Демократизация» ИИ — это больше не модное словечко, а реальная система, работающая на вашем рабочем столе Windows. Освободитесь от затрат на облачные API и рисков утечки информации, и прямо сейчас сделайте шаг в свободный и мощный мир приватного ИИ.&lt;/p></description></item></channel></rss>