Библиотека · AI на своём компьютере и своём сервере

Локальные AI модели — Ollama, LM Studio и приватный AI

Строитель75 минОбновлено: октябрь 2026
76 из 105 в библиотеке

Модуль: 13. Профессиональная практика | Время: ~30 мин теории + 45 мин практики


Суть урока

Всё что ты говоришь Claude — уходит в облако Anthropic. Для большинства задач это нормально. Но что если клиент — больница, юридическая фирма или банк? Что если нужно обработать 100 000 документов без бюджета на API? Что если интернета нет?

Локальные модели — это AI который работает прямо на твоём компьютере. Данные никуда не уходят. Inference почти ничего не стоит (электричество и износ железа). Работает в самолёте.

Про названия моделей. Каталог открытых моделей обновляется каждые несколько месяцев. Примеры в уроке взяты из семейств, которые были популярны на момент написания (Llama 3, Mistral, Qwen 2.5, Phi, Gemma, DeepSeek). К октябрю 2026 вышли более новые поколения этих семейств и другие открытые модели, например gpt-oss от OpenAI. Принцип выбора от этого не меняется: актуальные названия и размеры смотри в каталоге ollama.com/library. Нужную команду подставь вместо тега из примера.

🎨 Образ: Облачный AI — как такси. Удобно, надёжно, но водитель всё видит и слышит, а поездка стоит денег. Локальный AI — как своя машина в гараже. Едешь куда хочешь, когда хочешь, никто не слушает. Платишь только за бензин (электричество).


Ключевые концепции

  • Ollama — главный инструмент для запуска локальных моделей (macOS, Windows, Linux)
  • LM Studio — GUI-альтернатива, drag & drop интерфейс
  • GGUF — формат квантизации: большая модель сжимается в разумный размер
  • Квантизация — сжатие точности весов (32-bit → 4-bit) ради скорости и памяти
  • OpenAI-compatible API — Ollama отдаёт тот же API формат что OpenAI, поэтому код для OpenAI API работает с Ollama почти без изменений
  • Apple Silicon advantage — M-чипы используют общую память CPU+GPU, что даёт большое преимущество для локальных моделей
  • LLM Router — паттерн: выбираешь модель под задачу, а не одну модель для всего

Теория

Зачем локальные модели — пять реальных причин

Не теоретические причины, а конкретные ситуации из практики.

Причина 1: Приватность по требованию клиента

Медицинская клиника хочет автоматизировать обработку историй болезней. Юридическая фирма — анализ конфиденциальных договоров. Банк — обработку внутренних документов.

Они не против AI. Они против того чтобы данные пациентов/клиентов/партнёров уходили на серверы Anthropic или OpenAI. Это не паранойя — это GDPR, HIPAA, NDA.

Локальная модель — единственный способ дать им AI без compliance-рисков.

Причина 2: Стоимость при массовой обработке

Допустим нужно обработать 50 000 документов по 2 страницы каждый. Через Claude Sonnet это:

  • 50 000 × ~1 000 токенов = 50M токенов
  • Стоимость входных токенов: 50 × цена за 1M токенов. При $2 за 1M (цена Sonnet 5.5 на октябрь 2026) это около $100
  • Плюс output токены

Если это повторяется еженедельно — сотни долларов в месяц только на эту задачу. Для массовой фоновой обработки в облаке есть Batch API со скидкой 50%, но и тогда расходы заметны. А если задача не требует уровня Sonnet (классификация, извлечение данных) — локальная модель справится почти бесплатно. Актуальные цены: Актуальное сейчас.

Причина 3: Оффлайн — везде

Самолёт. Дача. Стройка без интернета. Конференция с плохим WiFi. Emergencyситуация когда облако лежит.

Локальная модель работает всегда. Это не экзотика — это реальный use case для любого кто работает в поле.

Причина 4: Compliance-регуляции

Некоторые страны и индустрии имеют жёсткие требования по data residency — данные не могут покидать определённую юрисдикцию или сервер. Банки в ряде стран вообще не могут использовать публичные облачные AI.

Для этого клиентского сегмента локальный AI — не опция, а единственный вариант.

Причина 5: Fine-tuning на своих данных

Хочешь модель которая говорит в точном стиле твоего клиента? Которая знает его продукт наизусть? Которая отвечает именно так как нужно для его бизнеса?

Свои веса Claude ты дообучить не можешь (закрытая модель). Но можно взять открытую модель (например, из семейств Llama, Qwen, Gemma, Mistral), обучить её на нескольких сотнях примеров — и получить специализированного ассистента именно для этого бизнеса. Подробнее: Fine-tuning — когда промптов мало.

🎨 Образ: Облачные модели — как универсальный швейцарский нож. Локальные с fine-tuning — как инструмент сделанный точно под твою руку для одной конкретной задачи.


Ollama — главный инструмент

Ollama — это runtime для локальных моделей. Устанавливаешь один раз, командой запускаешь любую модель из каталога. Автоматически скачивает, оптимизирует под твоё железо, запускает API сервер.

Установка:

bash
# macOS через Homebrew
brew install ollama

# Или скачать напрямую: ollama.com/download
# Windows и Linux — тоже есть, installer на сайте

# Проверка установки
ollama --version

Запуск первой модели:

bash
# Запустить Llama 3.2 (3B параметров, ~2GB, быстро на любом Mac). Тег из примера: актуальные модели смотри в каталоге Ollama
ollama run llama3.2

# Теперь у тебя интерактивный чат прямо в терминале
>>> Привет! Объясни что такое API простым языком.

Популярные модели:

bash
# Быстрые (для простых задач, работают на 8GB RAM)
ollama run llama3.2          # 3B параметров, ~2GB диска
ollama run phi4              # Microsoft, 14B, очень эффективный
ollama run gemma3            # Google, хорошее качество/размер

# Для кода (оптимизированы на код)
ollama run mistral:7b        # Французский, отличный general purpose
ollama run qwen2.5-coder     # Alibaba, специализирован на коде
ollama run deepseek-coder    # DeepSeek, сильный в коде и дебаггинге
ollama run codellama         # Meta, специально для кода

# Тяжёлые (нужно 32GB+ RAM, Mac Studio уровень)
ollama run llama3.1:70b      # Заметно сильнее малых моделей
ollama run qwen2.5:72b       # Alibaba, очень сильная

# Управление
ollama list                  # Список скачанных моделей
ollama ps                    # Запущенные сейчас
ollama rm llama3.2           # Удалить модель
ollama pull llama3.2         # Скачать без запуска

Ключевой факт: OpenAI-compatible API

Ollama запускает локальный API сервер на http://localhost:11434. Этот сервер совместим с форматом OpenAI API. Это означает: код написанный для OpenAI API обычно работает с Ollama почти без изменений — просто меняешь base_url и название модели.

bash
# API работает автоматически когда Ollama запущен
curl http://localhost:11434/v1/models

# Тест через curl (как OpenAI)
curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.2",
    "messages": [{"role": "user", "content": "Привет!"}]
  }'

LM Studio — GUI для тех кто не любит терминал

LM Studio (lmstudio.ai) — визуальный интерфейс для локальных моделей. Если Ollama = терминальный инструмент, то LM Studio = приложение с интерфейсом.

Что умеет:

  • Скачать модели с HuggingFace прямо из интерфейса (поиск встроен)
  • Drag & drop установка GGUF файлов
  • Встроенный чат с историей
  • Встроенный API сервер (тоже OpenAI-compatible)
  • Настройка параметров: temperature, context length, GPU layers
  • Мониторинг RAM и GPU в реальном времени

Когда LM Studio лучше Ollama:

  • Показываешь локальный AI клиенту (визуально понятнее)
  • Нужно быстро попробовать много разных моделей
  • Хочешь настроить параметры без командной строки
  • Работаешь с GGUF файлами из HuggingFace напрямую

Когда Ollama лучше LM Studio:

  • Автоматизация через скрипты
  • Серверный деплой (Linux, без GUI)
  • Интеграция в код (проще через CLI)
  • Быстрое переключение моделей в терминале

🎨 Образ: Ollama — как git в командной строке. LM Studio — как GitHub Desktop. Один и тот же результат, разный интерфейс. Профессионалы используют оба.


Понимание параметров и RAM

Прежде чем выбирать модель — нужно понять связь между параметрами, размером и качеством.

Что такое параметры модели

🎨 Образ: Параметры — как нейроны в мозге. У человека ~86 миллиардов нейронов. У маленькой модели на 3B — 3 миллиарда весов. У большой на 70B — 70 миллиардов. Больше — обычно умнее, но требует больше памяти.

Что такое квантизация

Оригинальные веса модели хранятся в 32-битной точности (fp32). Это огромный размер. Квантизация — сжатие до 4-битной (Q4) или 8-битной (Q8) точности с минимальной потерей качества.

Результат: 7B модель в Q4 занимает ~4GB вместо ~28GB. Запускается на обычном MacBook.

Напиши в чат
Q2 — очень сильное сжатие, заметная потеря качества
Q4 — хороший баланс (рекомендуется для большинства)
Q5 / Q6 — выше качество, больше памяти
Q8 — почти оригинальное качество, 2x RAM от Q4
fp16 — полная точность, нужен профессиональный GPU

Практическая таблица: что запустится на чём

RAM компьютера Максимальная модель (Q4) Что это даёт
8GB 7B параметров Хорошие общие задачи, базовый код
16GB 13B параметров Заметно лучше качество текста
32GB 30B параметров Очень хорошее качество
64GB 70B параметров Сильные модели прошлого поколения
128GB+ 120B+ параметров Очень крупные открытые модели

Важно для Apple Silicon: M-чипы Apple используют унифицированную память — CPU и GPU делят один пул RAM. Это большое преимущество. На PC с отдельной видеокартой: нужно чтобы модель поместилась в VRAM видеокарты (видеокарта с 8GB VRAM = модели порядка 7B). На Mac с 24GB большая часть памяти доступна модели. Таблица выше ориентировочная: реальный размер зависит от квантизации и длины контекста.


Apple Silicon: почему Mac выигрывает у PC для локального AI

🎨 Образ: Обычный PC — как офис где юристы (CPU) и бухгалтеры (GPU) работают в разных зданиях и постоянно курьерят документы между собой. Mac Apple Silicon — как open space где все сидят рядом и мгновенно передают документы.

Архитектурное преимущество:

На PC:

  • CPU имеет 64GB RAM
  • GPU имеет 8GB VRAM отдельно
  • Модель 70B (требует 40GB) = не помещается в VRAM = работает медленно через CPU

На Mac M3/M4:

  • CPU + GPU = один пул памяти
  • Mac с 64GB унифицированной памяти — 70B модель Q4 запускается
  • GPU accelerates inference через Metal framework

Скорость: конкретные цифры tokens/sec зависят от модели, квантизации, версии Ollama и железа, поэтому здесь их нет. Общая картина такая: мощная видеокарта обычно быстрее на маленьких моделях, а на очень больших выигрывает Mac с большой унифицированной памятью, потому что большая модель просто помещается. И Mac — ноутбук, везде с тобой. Измерь скорость на своём железе: ollama run <модель> --verbose покажет eval rate в токенах в секунду.

Mac с большой памятью — точка перехода:

Если серьёзно работаешь с локальными моделями — Mac Studio с очень большим объёмом унифицированной памяти меняет картину: крупные модели становятся практичными для обычного чата.


Интеграция с кодом: LLM Router паттерн

Самый важный паттерн при работе с локальными моделями — LLM Router. Не одна модель для всего. Разные задачи — разные модели.

🎨 Образ: LLM Router — как HR-директор который знает кому дать какую задачу. Сложный анализ — идёт к Sonnet. Простая классификация — идёт к локальной модели (бесплатно). Конфиденциальные данные — только к локальной (никуда не уходит).

Простая реализация роутера:

python
# llm_router.py
import anthropic
import openai
from enum import Enum

class TaskType(Enum):
    COMPLEX_CODE = "complex_code"       # Claude Sonnet
    SIMPLE_TEXT = "simple_text"         # Локальная: llama3.2
    CODE_REVIEW = "code_review"         # Локальная: deepseek-coder
    PRIVATE_DATA = "private_data"       # Локальная: любая (данные не уходят)
    CREATIVE = "creative"               # Claude Sonnet (лучшее качество)
    CLASSIFICATION = "classification"  # Локальная (дёшево, быстро)

def get_client_and_model(task_type: TaskType):
    """Возвращает (client, model_name) под задачу"""
    
    # Anthropic Claude — сложные задачи, креатив
    if task_type in [TaskType.COMPLEX_CODE, TaskType.CREATIVE]:
        return (
            anthropic.Anthropic(),
            "claude-sonnet-5-5"  # название модели на октябрь 2026, проверь актуальное
        )
    
    # Ollama — локально, бесплатно
    ollama_client = openai.OpenAI(
        base_url="http://localhost:11434/v1",
        api_key="ollama"  # Ollama игнорирует ключ, но параметр обязателен
    )
    
    model_map = {
        TaskType.SIMPLE_TEXT: "llama3.2",
        TaskType.CODE_REVIEW: "deepseek-coder",
        TaskType.PRIVATE_DATA: "mistral:7b",  # Данные не уходят с компьютера
        TaskType.CLASSIFICATION: "llama3.2",
    }
    
    return (ollama_client, model_map[task_type])


def run_task(task_type: TaskType, prompt: str) -> str:
    """Выполняет задачу через правильную модель"""
    client, model = get_client_and_model(task_type)
    
    # Anthropic API (другой формат)
    if isinstance(client, anthropic.Anthropic):
        message = client.messages.create(
            model=model,
            max_tokens=1024,
            messages=[{"role": "user", "content": prompt}]
        )
        return "".join(b.text for b in message.content if b.type == "text")
    
    # OpenAI-compatible API (Ollama)
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content


# Пример использования
if __name__ == "__main__":
    # Сложный код — идёт к Claude
    result = run_task(
        TaskType.COMPLEX_CODE,
        "Напиши async Python функцию для обработки очереди Celery"
    )
    
    # Классификация — идёт к локальной (бесплатно)
    category = run_task(
        TaskType.CLASSIFICATION,
        "Категоризируй этот текст: 'Хочу узнать о ценах на квартиру в Куэнке'"
        "\nКатегории: [запрос цены, запрос района, общий вопрос]"
    )
    
    # Приватные данные — только локально
    analysis = run_task(
        TaskType.PRIVATE_DATA,
        "Извлеки ключевые даты из этого договора: [текст договора]"
    )

Более умный роутер с автовыбором:

python
# smart_router.py
import re

ROUTING_RULES = [
    # (паттерн в промпте, task_type)
    (r"(конфиденциальн|NDA|приватн|секрет)", TaskType.PRIVATE_DATA),
    (r"(напиши код|function|class|async|debug)", TaskType.COMPLEX_CODE),
    (r"(категоризируй|классифицируй|тип|вид)", TaskType.CLASSIFICATION),
    (r"(проверь код|code review|найди баги)", TaskType.CODE_REVIEW),
]

def auto_route(prompt: str) -> TaskType:
    """Автоматически определяет тип задачи из промпта"""
    prompt_lower = prompt.lower()
    for pattern, task_type in ROUTING_RULES:
        if re.search(pattern, prompt_lower):
            return task_type
    return TaskType.SIMPLE_TEXT  # Дефолт — локальная модель

# Использование
task = auto_route("Проверь этот код на баги: def foo(): pass")
result = run_task(task, "Проверь этот код на баги: def foo(): pass")

Сравнение моделей для разных задач

Таблица отражает семейства на момент написания, более новые поколения смотри в каталоге Ollama.

Модель Параметры RAM (Q4) Лучше для Слабее для Скорость
Llama 3.2 3B 3B 2GB Быстрый чат, простые вопросы Сложный код, длинные тексты Очень быстро
Phi-4 14B 9GB Рассуждения, математика Длинный контекст Быстро
Mistral 7B 7B 5GB Общие задачи, инструкции Многошаговое рассуждение Быстро
Qwen 2.5 Coder 7B 7B 5GB Код, SQL, дебаггинг Креативный текст Быстро
DeepSeek Coder 6.7B 6.7B 4GB Код, объяснение кода Длинный контекст Быстро
Llama 3.1 8B 8B 5GB Хорошее general purpose Нет специализации Быстро
Llama 3.1 70B 70B 40GB Сильная модель прошлого поколения Нужно 64GB+ RAM Медленно
Qwen 2.5 72B 72B 45GB Лучшее локальное качество Нужно 64GB+ RAM Медленно

Рекомендации по выбору:

Напиши в чат
Старт (8-16GB RAM):
  Общие задачи: mistral:7b
  Код: qwen2.5-coder или deepseek-coder
  Быстро и просто: llama3.2

Нормальная работа (32GB):
  Основная: llama3.1:8b (хороший баланс)
  Код: qwen2.5-coder:14b

Профессиональный уровень (64GB+):
  Всё: llama3.1:70b
  Код: qwen2.5-coder:32b

Ollama MCP — локальные модели прямо из Claude Code

Можно добавить Ollama как MCP-сервер и вызывать локальные модели прямо из сессии Claude Code. Полезно когда хочешь попросить Claude делегировать часть задачи локальной модели.

bash
# Установка Ollama MCP (пакет от стороннего автора: проверь его репозиторий перед установкой)
claude mcp add ollama-mcp -- npx -y ollama-mcp

# Проверка что добавлен
claude mcp list

После установки в сессии Claude Code можно писать:

Напиши в чат
"Используй ollama с моделью qwen2.5-coder чтобы проверить этот код"

И Claude делегирует задачу через MCP на твой локальный Ollama. Данные не уходят в облако — обработка на твоём компьютере.

Альтернатива: прямой API вызов из Claude Code:

python
# Этот скрипт Claude Code может написать и запустить
import openai

client = openai.OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

response = client.chat.completions.create(
    model="qwen2.5-coder",
    messages=[{
        "role": "user",
        "content": "Review this Python code for bugs:\n" + code_content
    }]
)
print(response.choices[0].message.content)

Когда локальные vs облако: честное сравнение

Не нужно выбирать одно. Паттерн — использовать оба под разные задачи.

Локальные модели ВЫИГРЫВАЮТ:

Напиши в чат
✅ Данные клиента под NDA / HIPAA / GDPR
✅ Массовая обработка документов (тысячи штук, без платы за токены)
✅ Работа без интернета
✅ Fine-tuning под конкретный бизнес
✅ Compliance в регулируемых отраслях
✅ Длительный R&D без счётчика токенов
✅ Повторяющиеся простые задачи (классификация, извлечение)

Облако (Claude Sonnet/Opus) ВЫИГРЫВАЕТ:

Напиши в чат
✅ Сложные многошаговые задачи (качество лучше)
✅ Очень большой контекст (у крупных моделей Claude до миллиона токенов)
✅ Computer Use и браузерная автоматизация
✅ Быстрый старт без скачивания 8GB
✅ Всегда актуальная модель (сама обновляется)
✅ Сложный код, архитектурные решения
✅ Когда нужен лучший результат с первой попытки

🎨 Образ: Локальный AI — как свой повар дома: дёшево, приватно, доступен в любое время. Облачный Claude — как Michelin-звёздный ресторан: когда нужен высший уровень для важного события. Умный предприниматель использует оба в зависимости от ситуации.

Матрица решений:

Задача Рекомендация Почему
Черновик контента для правки Локальная Дёшево, правка всё равно нужна
Финальный текст для публикации Облако Качество критично
Обработка 1000 PDF клиента Локальная Без платы за токены + данные не уходят
Сложный агентный воркфлоу Облако Надёжность и контекст
Классификация заявок Локальная Простая задача, массово
Генерация кода с нуля Облако (Claude) Лучшее качество
Code review готового кода Локальная (DeepSeek) Достаточно для проверки
Конфиденциальный анализ Локальная Данные не уходят

Fine-tuning: когда и как

Fine-tuning — дообучение уже обученной модели на своих данных. Результат: модель которая говорит как твой клиент, знает его продукт, отвечает в нужном стиле.

Когда fine-tuning стоит делать:

Напиши в чат
✅ Специфический стиль общения (тон, терминология бренда)
✅ Нишевые знания (медицинские термины, юридические формулировки)
✅ Конкретный формат вывода (JSON определённой структуры всегда)
✅ Массовая генерация однотипного контента
✅ Когда промпт-инженерия уже не даёт нужного качества

Когда fine-tuning НЕ нужен:

Напиши в чат
❌ Просто "хочу чтобы ChatGPT знал больше" — это RAG, не fine-tuning
❌ Задача решается хорошим промптом
❌ Данных меньше 200-300 примеров
❌ Нет времени на итерацию (fine-tuning = эксперименты)

Инструменты для fine-tuning:

LoRA (Low-Rank Adaptation) — самый популярный метод. Не переобучает всю модель — добавляет небольшие адаптеры. Дёшево по вычислениям, быстро.

Напиши в чат
Полный fine-tuning 7B модели: нужен серьёзный облачный GPU (класса A100), аренда считается за час
LoRA fine-tuning 7B модели: достаточно мощной потребительской видеокарты или Mac с большой памятью

Unsloth — инструмент который делает LoRA в 2-5x быстрее с меньшим потреблением памяти:

bash
pip install unsloth

# Базовый пример fine-tuning с Unsloth
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/llama-3.2-3b-instruct",
    max_seq_length=2048,
    load_in_4bit=True  # Квантизация для экономии памяти
)

Формат данных для fine-tuning:

jsonl
{"messages": [
  {"role": "user", "content": "Как купить квартиру в Куэнке?"},
  {"role": "assistant", "content": "Процесс покупки в Эквадоре включает..."}
]}
{"messages": [
  {"role": "user", "content": "Нужен ли нотариус при покупке?"},
  {"role": "assistant", "content": "Да, в Эквадоре все сделки с недвижимостью..."}
]}

Минимум 200-300 таких пар. Claude Code может помочь сгенерировать датасет — описываешь стиль и типичные вопросы, он создаёт примеры.

Где обучать:

Напиши в чат
Runpod.io — GPU в облаке с почасовой оплатой (цены на сайте)
Google Colab — дешевле, но лимиты
Mac с большой унифицированной памятью — локально, если есть железо
Modal.com — serverless GPU, платишь только за время обучения

Практика: установи Ollama + напиши обработчик документов

Шаг 1: Установка и первый запуск

bash
# Установка
brew install ollama

# Запуск сервиса (в фоне)
ollama serve &

# Скачать и запустить первую модель
ollama run mistral:7b

После запуска увидишь интерактивный чат. Напиши что-нибудь — убедись что работает. Ctrl+D для выхода.

bash
# Проверка что API работает
curl http://localhost:11434/api/tags
# Должен вернуть список моделей

# Для кода — скачать ещё одну модель
ollama pull qwen2.5-coder

Шаг 2: Python скрипт для обработки документов

Создай файл document_processor.py:

python
"""
Локальный обработчик документов через Ollama.
Данные не уходят с компьютера.
"""

import openai
import json
from pathlib import Path

# Подключаемся к локальному Ollama
client = openai.OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

def extract_info_from_document(text: str, model: str = "mistral:7b") -> dict:
    """
    Извлекает структурированную информацию из текста документа.
    Использует локальную модель — данные не уходят.
    """
    prompt = f"""Проанализируй этот документ и извлеки информацию в JSON формате.

Нужно найти:
- дата документа (поле "date")
- стороны договора (поле "parties", список)
- сумма если есть (поле "amount")
- тип документа (поле "type")
- ключевые обязательства (поле "obligations", список)

Верни ТОЛЬКО валидный JSON без пояснений.

ДОКУМЕНТ:
{text}"""

    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        temperature=0.1  # Низкая температура для структурированного вывода
    )
    
    raw = response.choices[0].message.content.strip()
    
    # Очищаем если модель добавила markdown
    if raw.startswith("```"):
        raw = raw.split("```")[1]
        if raw.startswith("json"):
            raw = raw[4:]
    
    try:
        return json.loads(raw)
    except json.JSONDecodeError:
        return {"error": "Не удалось распарсить JSON", "raw": raw}


def classify_document(text: str, model: str = "llama3.2") -> str:
    """
    Быстрая классификация типа документа.
    Используем маленькую модель — дёшево и быстро.
    """
    prompt = f"""Определи тип документа одним словом из списка:
[договор, счёт, акт, письмо, заявление, другое]

ДОКУМЕНТ (первые 500 символов):
{text[:500]}

Ответь только одним словом."""

    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        max_tokens=10
    )
    return response.choices[0].message.content.strip().lower()


def process_folder(folder_path: str) -> list:
    """
    Обрабатывает все .txt файлы в папке.
    Возвращает список с результатами.
    """
    results = []
    folder = Path(folder_path)
    
    for file_path in folder.glob("*.txt"):
        print(f"Обрабатываю: {file_path.name}")
        
        text = file_path.read_text(encoding="utf-8")
        
        # Шаг 1: Классификация (быстрая маленькая модель)
        doc_type = classify_document(text, model="llama3.2")
        print(f"  Тип: {doc_type}")
        
        # Шаг 2: Извлечение информации (модель получше)
        info = extract_info_from_document(text, model="mistral:7b")
        
        results.append({
            "file": file_path.name,
            "classified_type": doc_type,
            "extracted_info": info
        })
        
        print(f"  Готово: {json.dumps(info, ensure_ascii=False, indent=2)[:200]}...")
    
    return results


# Демо-режим если нет реальных документов
def demo():
    sample_text = """
    ДОГОВОР АРЕНДЫ №123
    
    г. Куэнка, 15 января 2026 года
    
    ООО "Эквадор Риэлти" (Арендодатель) и Иванов Иван Иванович (Арендатор)
    заключили настоящий договор о следующем:
    
    1. Арендодатель сдаёт квартиру площадью 65 кв.м. по адресу: ул. Примера 45.
    2. Ежемесячная оплата: $500 USD.
    3. Срок аренды: 12 месяцев с 1 февраля 2026 года.
    4. Арендатор обязуется своевременно оплачивать аренду.
    """
    
    print("=== ДЕМО: Обработка документа локальной моделью ===\n")
    print("Документ:")
    print(sample_text[:200] + "...\n")
    
    print("Классификация (llama3.2)...")
    doc_type = classify_document(sample_text)
    print(f"Тип: {doc_type}\n")
    
    print("Извлечение информации (mistral:7b)...")
    info = extract_info_from_document(sample_text)
    print("Результат:")
    print(json.dumps(info, ensure_ascii=False, indent=2))
    
    print("\n✅ Все данные обработаны локально — никуда не ушли!")


if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1:
        # Если передана папка — обрабатываем
        folder = sys.argv[1]
        results = process_folder(folder)
        
        output_file = "results.json"
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(results, f, ensure_ascii=False, indent=2)
        
        print(f"\n✅ Результаты сохранены в {output_file}")
    else:
        # Иначе демо
        demo()

Запуск:

bash
# Убедись что Ollama запущен и модели скачаны
ollama list  # Должны быть llama3.2 и mistral:7b

# Демо с тестовым документом
python document_processor.py

# Обработка папки с документами
python document_processor.py /path/to/documents/

Шаг 3: Добавить в Claude Code через CLAUDE.md

Добавь в CLAUDE.md своего проекта:

Напиши в чат
## Локальный AI стек

При работе с конфиденциальными данными клиентов — использовать Ollama (локально).
API endpoint: http://localhost:11434/v1
Доступные модели: mistral:7b (general), qwen2.5-coder (код), llama3.2 (быстро)

Паттерн вызова: openai.OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")

Частые ошибки

Ошибка 1: Ollama не отвечает

bash
# Проверь что сервис запущен
curl http://localhost:11434/api/tags

# Если нет — запусти
ollama serve

# На macOS Ollama запускается как приложение (иконка в menu bar)
# или через launchctl

Ошибка 2: Модель отвечает очень медленно

Если меньше 3-5 токенов/сек — модель не помещается в RAM и уходит в swap. Решение: выбрать модель меньшего размера или уменьшить квантизацию.

bash
# Проверь сколько RAM использует Ollama
ollama ps  # Показывает активные модели и память

# Выбери меньшую модель
ollama run llama3.2  # 3B вместо 7B

Ошибка 3: JSON из модели не парсится

Локальные модели иногда добавляют markdown обёртку. Всегда обрабатывай:

python
def clean_json(text: str) -> str:
    """Убирает markdown обёртку из ответа модели"""
    text = text.strip()
    if "```json" in text:
        text = text.split("```json")[1].split("```")[0]
    elif "```" in text:
        text = text.split("```")[1].split("```")[0]
    return text.strip()

Ошибка 4: Разные результаты при одном промпте

Нормально при высокой temperature. Для структурированного вывода (JSON, классификация) используй temperature=0.0 или temperature=0.1.


Итог урока

Что ты теперь умеешь:

  • Установить Ollama и запустить локальную модель за считанные минуты
  • Выбрать правильную модель под задачу (размер, специализация)
  • Интегрировать локальную модель в Python код через OpenAI-compatible API
  • Реализовать LLM Router паттерн: разные задачи — разные модели
  • Обработать папку конфиденциальных документов локально, без отправки данных в облако

Главная идея:

Локальные модели — не замена Claude. Это дополнительный инструмент в арсенале. Умный предприниматель использует оба: локальные там где нужна приватность или объём, облако там где нужно качество.

🎨 Финальный образ: LLM Router — как умный менеджер проекта. Он знает: простую задачу → дать джуниору (быстро и дёшево), сложную → дать сеньору (качественно но дороже), конфиденциальную → только внутреннему сотруднику (никаких внешних). Именно так работает правильный AI стек.


Домашнее задание

Уровень 1 (обязательно):

  1. Установи Ollama
  2. Скачай mistral:7b и llama3.2
  3. Запусти демо-скрипт из урока
  4. Убедись что обработка работает локально (без интернета — должно работать)

Уровень 2 (рекомендуется):

  1. Возьми реальный документ из своего бизнеса (без конфиденциальных данных для теста)
  2. Адаптируй prompt в extract_info_from_document под свой тип документа
  3. Обработай 5-10 документов, проверь качество
  4. Сравни результат с тем же промптом через Claude Sonnet — зафиксируй разницу в качестве

Уровень 3 (для продвинутых):

  1. Реализуй smart_router.py из теоретической части
  2. Добавь логирование: модель использованная / время ответа / примерная стоимость (для облака)
  3. Найди задачу в своём бизнесе где локальная модель достаточно хороша — посчитай экономию за месяц

Ссылки


Следующий урок: Fine-tuning — когда промптов мало

Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс