<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Node.js on kenji.blog</title><link>http://kenji.blog/ru/tags/node.js/</link><description>Recent content in Node.js on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 02:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ru/tags/node.js/index.xml" rel="self" type="application/rss+xml"/><item><title>Простая настройка локальной LLM и интеграция API с помощью Ollama</title><link>http://kenji.blog/ru/p/ollama-local-llm-api-guide/</link><pubDate>Fri, 11 Sep 2026 02:00:00 +0900</pubDate><guid>http://kenji.blog/ru/p/ollama-local-llm-api-guide/</guid><description>&lt;img src="http://kenji.blog/p/ollama-local-llm-api-guide/img/eyecatch.jpg" alt="Featured image of post Простая настройка локальной LLM и интеграция API с помощью Ollama" />&lt;h1 id="введение-зачем-нужна-локальная-llm">Введение: Зачем нужна локальная LLM?
&lt;/h1>&lt;p>С появлением больших языковых моделей (LLM) наша жизнь и методы разработки претерпели радикальные изменения. Мощные облачные ИИ-сервисы, такие как ChatGPT, Claude и Gemini, продолжают развиваться с каждым днем, предоставляя чрезвычайно продвинутые возможности логического вывода. Однако облачные LLM не всегда являются оптимальным выбором для всех сценариев использования. У облачных LLM есть следующие проблемы:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Проблемы конфиденциальности и безопасности&lt;/strong>: Отправка данных, содержащих конфиденциальную или личную информацию, на внешние серверы часто недопустима с точки зрения корпоративного комплаенса и безопасности.&lt;/li>
&lt;li>&lt;strong>Неопределенность затрат&lt;/strong>: Поскольку плата за использование API зависит от количества токенов, для систем, обрабатывающих большие объемы данных или выполняющих частые запросы, существует риск неограниченного роста эксплуатационных расходов.&lt;/li>
&lt;li>&lt;strong>Задержка и зависимость от сети&lt;/strong>: Сетевая связь становится узким местом при использовании в автономных средах или на граничных устройствах (edge devices), где требуется крайне низкая задержка.&lt;/li>
&lt;li>&lt;strong>Привязка к поставщику (Vendor lock-in)&lt;/strong>: Зависимость от моделей конкретного провайдера может привести к тому, что вы пострадаете от прекращения предоставления услуг в будущем, изменений в условиях обслуживания или непредвиденных изменений в поведении из-за обновления моделей.&lt;/li>
&lt;/ol>
&lt;p>В качестве средства решения этих проблем большое внимание привлекают «Локальные LLM». Запуская модель на собственном оборудовании, вы можете свободно использовать ИИ, не отправляя никаких данных наружу и не беспокоясь о ежемесячных расходах.&lt;/p>
&lt;p>В этой статье мы подробно рассмотрим &lt;strong>Ollama&lt;/strong>, инструмент, который позволяет удивительно легко развертывать, управлять и интегрировать по API локальные LLM. Мы разберем всё: от основ и внутренней архитектуры до продвинутой интеграции API с использованием Python и Node.js, и даже математических формул для оптимизации производительности.&lt;/p>
&lt;hr>
&lt;h1 id="что-такое-ollama-ее-внутренняя-архитектура">Что такое Ollama? Ее внутренняя архитектура
&lt;/h1>&lt;p>Ollama — это платформа для простого запуска и управления большими языковыми моделями с открытым исходным кодом (Llama 3, Phi-3, Mistral, Gemma и т. д.) в локальной среде. До сих пор для настройки локальной среды LLM требовались очень сложные процедуры: настройка среды Python, установка набора инструментов CUDA, разрешение зависимостей PyTorch, загрузка огромных файлов моделей с Hugging Face и преобразование форматов (например, из Safetensors в GGUF).&lt;/p>
&lt;p>Ollama скрывает эти сложности, позволяя обращаться с LLM так же легко, как с Docker. С помощью одной команды вы можете скачать модель (&lt;code>pull&lt;/code>), запустить ее (&lt;code>run&lt;/code>) и поднять в качестве HTTP-сервера.&lt;/p>
&lt;h2 id="основная-технология-обертка-для-llamacpp">Основная технология: Обертка для llama.cpp
&lt;/h2>&lt;p>В качестве бэкенда механизма вывода Ollama выступает &lt;strong>llama.cpp&lt;/strong>, быстрая библиотека вывода LLM, написанная на C/C++. llama.cpp обладает способностью выполнять модели, максимально используя аппаратные возможности, будь то Apple Silicon (Metal), NVIDIA GPU (CUDA), AMD GPU (ROCm) или даже среды только с CPU.&lt;/p>
&lt;p>Ollama включает в себя llama.cpp и использует архитектуру, в которой серверный процесс, написанный на языке Go, предоставляет REST API, вызывая механизм вывода llama.cpp в фоновом режиме.&lt;/p>
&lt;p>Следующая диаграмма Mermaid показывает общую архитектуру Ollama.&lt;/p>
&lt;div class="mermaid">graph TD
A["Клиентские приложения (Python / Node.js)"] -- "HTTP/REST API" --> B["Сервер Ollama (Go)"]
B --> C["Менеджер моделей (обработка GGUF)"]
B --> D["Механизм вывода (llama.cpp)"]
D --> E["Ускорение GPU (CUDA / Metal / ROCm)"]
D --> F["Переход на CPU (AVX2 / AVX-512)"]
C --> G["Локальное хранилище моделей"]&lt;/div>
&lt;p>Благодаря этой архитектуре разработчики могут использовать продвинутые возможности вывода через стандартные HTTP-запросы, не беспокоясь о сборке C++ кода или детальных настройках драйверов GPU.&lt;/p>
&lt;hr>
&lt;h1 id="установка-ollama-и-начальная-настройка">Установка Ollama и начальная настройка
&lt;/h1>&lt;p>Установка Ollama предельно проста. Предоставляются оптимизированные бинарные файлы для каждой ОС.&lt;/p>
&lt;h2 id="macos--windows">macOS / Windows
&lt;/h2>&lt;p>Просто скачайте установщик с официального сайта (&lt;a class="link" href="https://ollama.com/" target="_blank" rel="noopener"
>https://ollama.com/&lt;/a>) и запустите его. Версия для macOS автоматически распознает Metal API от Apple Silicon, а версия для Windows — NVIDIA GPU (CUDA), и, если доступно, включает аппаратное ускорение.&lt;/p>
&lt;h2 id="linux">Linux
&lt;/h2>&lt;p>В средах Linux (например, Ubuntu) достаточно выполнить следующую однострочную команду, чтобы установить необходимые компоненты и запустить сервер Ollama в качестве службы systemd.&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;/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">curl -fsSL https://ollama.com/install.sh &lt;span class="p">|&lt;/span> sh
&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;/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">ollama --version
&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="запуск-с-использованием-docker">Запуск с использованием Docker
&lt;/h2>&lt;p>Если вы не хотите загрязнять существующую среду или хотите интегрировать инструмент в контейнерную инфраструктуру, вы также можете использовать официальный образ Docker. Для использования GPU необходимо установить NVIDIA Container Toolkit.&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-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Для запуска только на CPU&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
&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"># При использовании NVIDIA GPU&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -d --gpus&lt;span class="o">=&lt;/span>all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>По умолчанию сервер Ollama прослушивает &lt;code>http://localhost:11434&lt;/code>.&lt;/p>
&lt;hr>
&lt;h1 id="управление-моделями-и-основные-команды-cli">Управление моделями и основные команды CLI
&lt;/h1>&lt;p>Самая большая привлекательность Ollama заключается в том, что управление моделями очень интуитивно понятно. Вы можете тестировать различные модели с тем же ощущением, что и при работе с образами Docker.&lt;/p>
&lt;h2 id="1-запуск-модели-run">1. Запуск модели (&lt;code>run&lt;/code>)
&lt;/h2>&lt;p>Это наиболее часто используемая команда. Если указанной модели не существует, она автоматически скачивается (&lt;code>pull&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;/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">ollama run llama3.1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>При выполнении приведенной выше команды будет запущена новейшая модель от Meta — Llama 3.1 (версия с 8B параметров). При вводе сообщения в промпт ответ от модели будет отображаться в виде потока (streaming). Для выхода введите &lt;code>/bye&lt;/code> или нажмите &lt;code>Ctrl+D&lt;/code>.&lt;/p>
&lt;h2 id="2-скачивание-модели-pull">2. Скачивание модели (&lt;code>pull&lt;/code>)
&lt;/h2>&lt;p>Если вы хотите скачать модель в фоновом режиме заранее, используйте команду &lt;code>pull&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;/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">ollama pull phi3:instruct
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ollama pull mistral:v0.3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>В библиотеке моделей Ollama вы можете указать версию или уровень квантования в формате &lt;code>имя_модели:тег&lt;/code>. Если тег опущен, применяется &lt;code>latest&lt;/code>, но вы также можете явно указать определенную квантованную модель (например, &lt;code>llama3:8b-instruct-q4_0&lt;/code>).&lt;/p>
&lt;h3 id="что-такое-квантование-quantization">Что такое квантование (Quantization)?
&lt;/h3>&lt;p>Здесь стоит немного остановиться на понятии квантования. Обычная LLM хранит параметры весов в 16-битном формате с плавающей запятой (FP16). Для модели с 8 миллиардами (8B) параметров только одни веса потребляют около 16 ГБ VRAM. Квантование — это технология сжатия их до 4-битных (Q4) или 8-битных (Q8) целых чисел.&lt;/p>
&lt;p>Благодаря квантованию можно кардинально сократить требуемый объем памяти и пропускную способность памяти, при этом минимизируя ухудшение точности модели. Модели, распространяемые в Ollama, по умолчанию представлены в формате GGUF с примененным оптимальным квантованием (чаще всего 4-битным).&lt;/p>
&lt;h2 id="3-вывод-списка-моделей-list">3. Вывод списка моделей (&lt;code>list&lt;/code>)
&lt;/h2>&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;/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">ollama list
&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;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-text" data-lang="text">&lt;span class="line">&lt;span class="cl">NAME ID SIZE MODIFIED
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">llama3.1:latest 43f7a214e532 4.7 GB 2 hours ago
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">phi3:instruct a2c89ceaed85 2.3 GB 3 days ago
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="4-удаление-модели-rm">4. Удаление модели (&lt;code>rm&lt;/code>)
&lt;/h2>&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;/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">ollama rm phi3:instruct
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h1 id="настройка-модели-с-помощью-modelfile">Настройка модели с помощью Modelfile
&lt;/h1>&lt;p>В Ollama вы можете использовать механизм под названием &lt;strong>Modelfile&lt;/strong> для создания собственных пользовательских моделей путем внедрения системных промптов и настройки гиперпараметров в существующие модели. Эта концепция полностью аналогична Dockerfile в Docker.&lt;/p>
&lt;p>Следующая диаграмма показывает, как пользовательская модель создается на основе базовой модели.&lt;/p>
&lt;div class="mermaid">graph LR
A["Базовая модель (llama3.1)"] -->|"Добавить системный промпт"| B["Промежуточная конфигурация"]
B -->|"Установить Temperature и Top_p"| C["Пользовательская модель (kansai-coder)"]
C -->|"Запуск"| D["Интерактивный CLI / API"]&lt;/div>
&lt;p>В качестве примера давайте создадим модель помощника по программированию, который будет отвечать на кансайском диалекте (Кансай-бен).&lt;/p>
&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;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;/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"># Указываем базовую модель
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">FROM llama3.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># Устанавливаем гиперпараметры, такие как креативность (temperature)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER temperature 0.7
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER top_p 0.9
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER repeat_penalty 1.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER num_ctx 4096
&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">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">Пожалуйста, всегда отвечайте на технические вопросы пользователей в дружелюбной манере, используя &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">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Создаем (собираем) новую модель из этого Modelfile.&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;/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">ollama create kansai-coder -f Modelfile
&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-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama run kansai-coder
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;gt;&amp;gt;&amp;gt; Pythonでリストをソートするにはどうすればええの？
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Тогда вы получите кастомизированный ответ вроде: &amp;ldquo;それはな、Pythonの &lt;code>sorted()&lt;/code> 関数か &lt;code>sort()&lt;/code> メソッドを使えばええんやで！&amp;rdquo; (Это, понимаешь, можно сделать, использовав функцию &lt;code>sorted()&lt;/code> или метод &lt;code>sort()&lt;/code> в Python!). Таким образом, можно создавать и управлять бесчисленным множеством агентов локально, специализированных для конкретных случаев использования.&lt;/p>
&lt;hr>
&lt;h1 id="подробное-руководство-по-ollama-rest-api">Подробное руководство по Ollama REST API
&lt;/h1>&lt;p>Хотя взаимодействие через CLI удобно, истинная мощь Ollama в реальной разработке приложений раскрывается через ее мощный REST API. Отправляя HTTP-запросы серверному процессу (по умолчанию &lt;code>http://localhost:11434&lt;/code>), вы можете получать результаты вывода.&lt;/p>
&lt;p>Три основных эндпоинта:&lt;/p>
&lt;ol>
&lt;li>&lt;code>/api/generate&lt;/code>: Генерация текста из одиночного промпта&lt;/li>
&lt;li>&lt;code>/api/chat&lt;/code>: Генерация чата (диалога) в формате, близком к OpenAI API&lt;/li>
&lt;li>&lt;code>/api/embeddings&lt;/code>: Генерация векторных представлений (Embeddings)&lt;/li>
&lt;/ol>
&lt;h2 id="генерация-текста-с-использованием-apigenerate">Генерация текста с использованием /api/generate
&lt;/h2>&lt;p>Это самый базовый эндпоинт для генерации. Давайте отправим запрос с помощью cURL.&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-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -X POST http://localhost:11434/api/generate -d &lt;span class="s1">&amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;model&amp;#34;: &amp;#34;llama3.1&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;prompt&amp;#34;: &amp;#34;Explain the concept of quantum entanglement in simple terms.&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: false
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Указав &lt;code>&amp;quot;stream&amp;quot;: false&lt;/code>, вы получите JSON сразу после завершения всей генерации. По умолчанию (&lt;code>true&lt;/code>), сгенерированные токены отправляются последовательно в формате JSON Lines, что подходит для реализации пользовательского интерфейса со стримингом.&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;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-json" data-lang="json">&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="nt">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;llama3.1&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="nt">&amp;#34;created_at&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2026-09-11T10:00:00.000Z&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="nt">&amp;#34;response&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Quantum entanglement is like having a pair of magical dice...&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="nt">&amp;#34;done&amp;#34;&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 class="nt">&amp;#34;context&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">128006&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">882&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">128007&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">271&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10445&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;total_duration&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">4567890000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;load_duration&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1234000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prompt_eval_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">14&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;eval_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;eval_duration&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">4321000000&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>context&lt;/code> закодировано состояние предыдущего разговора, и, включив его в следующий запрос, можно сохранить контекст. Однако для более простого управления историей разговоров используется следующий эндпоинт &lt;code>/api/chat&lt;/code>.&lt;/p>
&lt;h2 id="генерация-диалога-с-использованием-apichat">Генерация диалога с использованием /api/chat
&lt;/h2>&lt;p>Поскольку современные LLM дообучены (fine-tuned) для формата чата, при разработке приложений рекомендуется использовать &lt;code>/api/chat&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;/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">curl -X POST http://localhost:11434/api/chat -d &lt;span class="s1">&amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;model&amp;#34;: &amp;#34;llama3.1&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;messages&amp;#34;: [
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;system&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;You are a helpful AI assistant.&amp;#34; },
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;What is the capital of France?&amp;#34; },
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;assistant&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;The capital of France is Paris.&amp;#34; },
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;What is its famous tower?&amp;#34; }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ],
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: false
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Таким образом, передавая массив объектов сообщений с ролями (&lt;code>role&lt;/code> — system, user, assistant), вы можете легко обрабатывать сложный контекст диалога.&lt;/p>
&lt;hr>
&lt;h1 id="интеграция-с-приложениями-python">Интеграция с приложениями Python
&lt;/h1>&lt;p>Python является самым стандартным языком в разработке ИИ. Существует несколько способов использования Ollama из Python, но использование официального пакета &lt;code>ollama-python&lt;/code> является самым простым и надежным.&lt;/p>
&lt;h2 id="установка">Установка
&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;/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 ollama
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="использование-синхронного-api-synchronous">Использование синхронного API (Synchronous)
&lt;/h2>&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;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-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ollama&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">messages&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 class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;system&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&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>&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">def&lt;/span> &lt;span class="nf">chat_with_ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&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="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_input&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"># Вызов Ollama API&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="n">ollama&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&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="s1">&amp;#39;llama3.1&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="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">messages&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">assistant_reply&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;message&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;content&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="n">messages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;assistant&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">assistant_reply&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="n">assistant_reply&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="n">chat_with_ollama&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="использование-асинхронного-стриминга-async-streaming">Использование асинхронного стриминга (Async Streaming)
&lt;/h2>&lt;p>При разработке веб-приложений (FastAPI или Starlette) или ботов для Discord / Slack важно использовать асинхронный API и стриминг, чтобы избежать блокировки (blocking).&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-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">from&lt;/span> &lt;span class="nn">ollama&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AsyncClient&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">generate_stream&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AsyncClient&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"># При указании stream=True возвращается асинхронный генератор&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">chunk&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&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="s1">&amp;#39;llama3.1&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="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Объясните подробно декораторы в Python.&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="n">stream&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&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="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunk&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;message&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">flush&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>&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="c1"># Перевод строки в конце&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">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">generate_stream&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>Написав это таким образом, вы можете легко реализовать UX, в котором символы появляются один за другим, подобно интерфейсу ChatGPT.&lt;/p>
&lt;h2 id="интеграция-с-langchain-и-llamaindex">Интеграция с LangChain и LlamaIndex
&lt;/h2>&lt;p>Ollama имеет встроенную поддержку в LangChain и LlamaIndex, которые часто используются при создании систем RAG (Retrieval-Augmented Generation).&lt;/p>
&lt;p>Пример с LangChain:&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-python" data-lang="python">&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>&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.1&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">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&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;Explain dark matter.&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">response&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>Вы можете запускать мощные функции цепочек и агентов LangChain локально, не устанавливая никаких внешних API-ключей.&lt;/p>
&lt;hr>
&lt;h1 id="интеграция-с-приложениями-nodejs">Интеграция с приложениями Node.js
&lt;/h1>&lt;p>Для фронтенд-инженеров и fullstack-разработчиков возможность вызова локальных LLM из среды TypeScript/Node.js является огромным преимуществом. Мы будем использовать официальный NPM-пакет &lt;code>ollama&lt;/code>.&lt;/p>
&lt;h2 id="установка-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;/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">npm install ollama
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="пример-реализации-чат-бота-с-использованием-typescript">Пример реализации чат-бота с использованием TypeScript
&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;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-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">ollama&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">Message&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s1">&amp;#39;ollama&amp;#39;&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">async&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="nx">runChatbot() {&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">messages&lt;/span>: &lt;span class="kt">Message&lt;/span>&lt;span class="p">[]&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 class="nx">role&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;system&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">content&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;You are a concise expert.&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="p">{&lt;/span> &lt;span class="nx">role&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">content&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;Explain RESTful APIs.&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="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 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">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="nx">ollama&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">chat&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="s1">&amp;#39;llama3.1&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="nx">messages&lt;/span>: &lt;span class="kt">messages&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">stream&lt;/span>: &lt;span class="kt">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>&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="s2">&amp;#34;Assistant:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">response&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">content&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="nx">error&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="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 class="s2">&amp;#34;Error communicating with Ollama:&amp;#34;&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;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="nx">runChatbot&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="создание-сервера-express-с-поддержкой-стриминга">Создание сервера Express с поддержкой стриминга
&lt;/h2>&lt;p>Это пример реализации бэкенд API, который возвращает ответы веб-фронтенду потоком (streaming). Фрагменты отправляются с использованием SSE (Server-Sent Events) или обычного HTTP-стриминга.&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">express&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;express&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="kr">import&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">Ollama&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;ollama&amp;#39;&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">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">express&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">use&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">express&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">json&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">ollama&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">Ollama&lt;/span>&lt;span class="p">({&lt;/span> &lt;span class="nx">host&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;http://127.0.0.1:11434&amp;#39;&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="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;/api/stream-chat&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kr">async&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">req&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">res&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&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="kr">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">prompt&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">req&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">body&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">// Настройка HTTP-заголовков ответа (передача по частям - chunked)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">setHeader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;text/plain; charset=utf-8&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="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">setHeader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Transfer-Encoding&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;chunked&amp;#39;&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 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">stream&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="nx">ollama&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">generate&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="s1">&amp;#39;llama3.1&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="nx">prompt&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">prompt&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">stream&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="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="kr">await&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kr">const&lt;/span> &lt;span class="nx">chunk&lt;/span> &lt;span class="k">of&lt;/span> &lt;span class="nx">stream&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="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">chunk&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">response&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="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">end&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="nx">err&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="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">status&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Error generating response.&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">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">end&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="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">listen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&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="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="s1">&amp;#39;Server is running on port 3000&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="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h1 id="метрики-производительности-и-математический-анализ">Метрики производительности и математический анализ
&lt;/h1>&lt;p>Чтобы предоставить локальные LLM на уровне, пригодном для реального использования, необходим анализ задержки (latency) и пропускной способности (throughput). Ответы API Ollama содержат подробные метрики, касающиеся производительности.&lt;/p>
&lt;h2 id="математическая-модель-скорости-генерации-токенов">Математическая модель скорости генерации токенов
&lt;/h2>&lt;p>Время отклика LLM, напрямую связанное с пользовательским опытом, можно разделить на две основные составляющие: «&lt;strong>Время до первого токена (Time To First Token, TTFT)&lt;/strong>» и «&lt;strong>Время на выходной токен (Time Per Output Token, TPOT)&lt;/strong>».&lt;/p>
&lt;p>Общее время генерации $T_{total}$, если предположить, что количество сгенерированных токенов равно $N$, может быть сформулировано следующим образом:&lt;/p>
$$
T_{total} = t_{ttft} + \sum_{i=1}^{N-1} t_{tpot}^{(i)}
$$
&lt;p>Здесь, если аппроксимировать среднее время, затрачиваемое на генерацию каждого токена, как $\bar{t}_{tpot}$, формула упрощается:&lt;/p>
$$
T_{total} \approx t_{ttft} + (N - 1) \times \bar{t}_{tpot}
$$
&lt;p>Соответствие с полями ответа API Ollama выглядит следующим образом:&lt;/p>
&lt;ul>
&lt;li>&lt;code>prompt_eval_duration&lt;/code>: Это примерно соответствует $t_{ttft}$ (время оценки промпта). Возвращается в наносекундах.&lt;/li>
&lt;li>&lt;code>eval_duration&lt;/code>: Время, затраченное на весь процесс генерации.&lt;/li>
&lt;li>&lt;code>eval_count&lt;/code>: Количество сгенерированных токенов $N$.&lt;/li>
&lt;/ul>
&lt;p>Следовательно, скорость генерации токенов в секунду (Tokens Per Second: TPS) можно рассчитать по следующей формуле:&lt;/p>
$$
TPS = \frac{eval\_count}{(eval\_duration / 10^9)} \quad [\text{tokens/sec}]
$$
&lt;p>Например, в случае &lt;code>eval_count: 256&lt;/code>, &lt;code>eval_duration: 4321000000&lt;/code> (около 4.32 секунды):
&lt;/p>
$$
TPS = \frac{256}{4.321} \approx 59.24 \text{ tokens/sec}
$$
&lt;p>
Если скорость в локальной среде превышает 50 токенов в секунду, это намного быстрее скорости чтения человека, поэтому можно сказать, что обеспечивается очень комфортный опыт отклика.&lt;/p>
&lt;h2 id="формула-оценки-требуемого-объема-vram">Формула оценки требуемого объема VRAM
&lt;/h2>&lt;p>При запуске модели локально ключевым фактором производительности является то, помещается ли модель в VRAM видеокарты. Если она не помещается в VRAM и система переходит на основную память (RAM), скорость генерации значительно падает.&lt;/p>
&lt;p>Упрощенная формула для оценки требуемого объема памяти $M$ (в гигабайтах) выглядит следующим образом:&lt;/p>
$$
M \approx \frac{P \times Q}{8 \times 1024} + C
$$
&lt;ul>
&lt;li>$P$: Количество параметров модели (например: 8B = $8000 \times 10^6$)&lt;/li>
&lt;li>$Q$: Битность квантования (например: 4-bit, 8-bit, 16-bit)&lt;/li>
&lt;li>$C$: Дополнительная память для контекстного окна (KV-кэш и т. д. Зависит от модели и настроек, но обычно составляет около 1–2 ГБ)&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Пример расчета&lt;/strong>: Запуск Llama 3 (8B параметров) с 4-битным квантованием
&lt;/p>
$$
M_{model} = \frac{8,000 \times 4}{8 \times 1024} = \frac{32,000}{8192} \approx 3.9 \text{ GB}
$$
&lt;p>
Добавив к этому память для контекста, мы видим, что при наличии примерно 5-6 ГБ VRAM можно полностью развернуть модель на GPU (Full Offload). Даже с графическими процессорами среднего класса с 8 ГБ VRAM (например, RTX 4060) последних лет вполне возможно запускать достаточно мощные LLM.&lt;/p>
&lt;hr>
&lt;h1 id="продвинутые-сценарии-использования-и-заключение">Продвинутые сценарии использования и заключение
&lt;/h1>&lt;p>Открыв Ollama в качестве API в локальной сети, становятся возможными различные применения помимо обычных чат-ботов.&lt;/p>
&lt;h3 id="1-создание-локального-rag-retrieval-augmented-generation">1. Создание локального RAG (Retrieval-Augmented Generation)
&lt;/h3>&lt;p>Комбинируя локальную векторную базу данных, такую как ChromaDB или Qdrant, с эндпоинтом &lt;code>/api/embeddings&lt;/code> от Ollama (с использованием моделей встраивания, таких как &lt;code>nomic-embed-text&lt;/code>), можно создать полностью автономную, безопасную систему RAG для ответов на вопросы с загрузкой конфиденциальных внутренних документов.&lt;/p>
&lt;h3 id="2-ии-помощник-для-ide-и-редакторов">2. ИИ-помощник для IDE и редакторов
&lt;/h3>&lt;p>Указав Ollama в качестве бэкенда для расширений VS Code (например, Continue.dev) или плагинов Neovim, вы можете бесплатно получать автодополнение и объяснение кода в стиле GitHub Copilot, используя локальные модели (например, &lt;code>codellama&lt;/code> или &lt;code>deepseek-coder&lt;/code>).&lt;/p>
&lt;h3 id="3-интеграция-в-скрипты-автоматизации">3. Интеграция в скрипты автоматизации
&lt;/h3>&lt;p>Встраивая API-запросы к Ollama в Python или shell-скрипты, вы можете привнести мощь ИИ в различные аспекты ежедневного рабочего процесса, такие как автоматическое резюмирование логов, автоматическая генерация сообщений коммитов Git, а также задачи классификации стандартных текстов.&lt;/p>
&lt;h2 id="заключение">Заключение
&lt;/h2>&lt;p>С появлением Ollama порог для внедрения локальных LLM резко снизился. Сочетание простой системы команд, напоминающей работу с контейнерами Docker, и REST API, который легко использовать из внешних приложений, можно смело назвать текущим стандартом де-факто для локальной разработки ИИ.&lt;/p>
&lt;p>Разработчикам, которые сталкиваются с ограничениями по стоимости или безопасности облачных LLM, настоятельно рекомендуется использовать шаги, описанные в этой статье, для создания локальной среды LLM с помощью Ollama и интеграции ее в свои приложения. Вы должны почувствовать потенциал ИИ гораздо свободнее и ближе.&lt;/p></description></item></channel></rss>