Мигрируем 35 КБ препромптов с Opus на Ollama: подводные камни
Реальный инженерный постмортем: как перенести большие препромпты с Claude Opus на self-hosted Ollama и не сломать агентов
Введение: когда «всё работает» — вдруг перестаёт
Вы потратили недели на выточенный препромпт для Claude Opus. Агент знает контекст, уверенно вызывает инструменты, не галлюцинирует. Потом вы решаете перейти на self-hosted Ollama — ради приватности, экономии или независимости от вендора. И в первые же три минуты агент начинает вести себя как человек с амнезией: перечитывает файлы, которые уже обработал, переписывает готовую работу, зависает в петле повторных вызовов.
Это не баг конкретной модели. Это системная проблема, с которой сталкиваются все, кто переносит тяжёлые препромпты с облачных API на локальный инференс. Данный инженерный постмортем вскрывает реальные режимы отказа при переносе больших production-промптов с проприетарных API — и показывает, как с ними бороться.
Проблема №1: Контекстное окно — ваш главный враг
Клаудиные Opus или GPT-4 работают на огромных контекстных окнах — сотни тысяч токенов. Это создаёт у разработчиков ложное ощущение, что «большой препромпт — не проблема».
Self-hosted системы имеют значительно меньшие контекстные окна. Промпт плюс история сессии быстро превышают максимум — например, 65 тысяч токенов у типичного локального развёртывания.
На практике 35-килобайтный препромпт мгновенно поглощает 14% всего контекстного окна — и агент сразу начинает «сомневаться» в инструкциях: делает лишние вызовы инструментов, перечитывает файлы. Контекст насыщается за несколько циклов — иногда ещё до первого реального ответа.
num_ctx вручную в Modelfile — вы потеряете большую часть своего препромпта ещё до первого обмена с агентом.Контекстную длину нужно явно задавать в Ollama. Значения по умолчанию катастрофически малы.
Пример минимального Modelfile:
FROM gemma3:27b
PARAMETER num_ctx 65536
PARAMETER num_predict 4096
PARAMETER rope_freq_base 1000000
SYSTEM """
[ВАШ ПРЕПРОМПТ ЗДЕСЬ]
"""
Параметр num_ctx должен быть достаточно большим, чтобы вместить весь системный промпт плюс диалоговые обороты. Параметр rope_freq_base расширяет разрешение позиционного кодирования для контекстов длиннее нативной тренировочной длины модели.
Проблема №2: Агентский тромбоз — петли и трэшинг
Когда вы пытаетесь использовать большие препромпты, хорошо работающие у облачных провайдеров, Ollama начинает «захлёбываться» уже через три минуты. Агент зависает в петлях повторных вызовов инструментов, перечитывает уже обработанные файлы, переписывает завершённую работу.
Это явление — не случайность, а закономерный симптом контекстного насыщения.
Системный промпт, безупречно работающий на GPT-4o или Claude Sonnet, может молча рассыпаться в Ollama. Инженеры, мигрирующие большие промпты на локальные LLM, регулярно сталкиваются с одним и тем же паттерном: деградация последовательности персонажа, частичное игнорирование многошаговых инструкций, обвал качества — без единого сообщения об ошибке. Модель выглядит рабочей, но перестаёт следовать правилам, которые «закопаны» в середине промпта.
Сигналы отказа, которые нужно мониторить
Вот признаки контекстного истощения, которые стоит отслеживать в логах: ошибки парсинга вызовов инструментов (tool-call parse failures). Разбор ответов инструментов вталкивает в контекст столько сырых данных, что уничтожает сессию — как прорыв трубы прямо на вечеринке.
Другие тревожные сигналы:
- Агент снова и снова читает один и тот же файл
- Переписывает код, который уже сгенерировал
- Игнорирует инструкции из середины промпта
- Отвечает неполными или обрезанными JSON-структурами
graph TD
A[Большой препромпт 35KB] --> B{Контекст заполнен?}
B -- Нет --> C[Нормальная работа агента]
B -- Да --> D[Трэшинг и петли]
D --> E[Повторные вызовы инструментов]
D --> F[Перечитывание файлов]
D --> G[Переписывание готового]
E --> H[Ошибки парсинга tool-call]
F --> H
G --> H
H --> I[Сессия уничтожена]
Проблема №3: Архитектура промпта не переносится 1-в-1
Это, пожалуй, самый болезненный сюрприз: то, что работает на Opus, требует фундаментального переосмысления для локальной модели.
Негативные инструкции работают хуже
Правило для self-hosted агентов: перечитывайте только нужный срез данных, сокращайте число вызовов инструментов на каждый шаг и — важнейшее — замените «не делай X» на позитивные директивы: «делай только Y».
Это не каприз — это следствие меньших параметров модели. 27B-модель менее устойчива к двойному отрицанию и длинным цепочкам запретов.
Монолитный промпт нужно разбить
Если вы планируете переносить агентов с Frontier Provider на self-hosted open weight системы — изучите разбивку препромптов на единицы «одна проблема / одно решение», по одной цели на каждую.
Реструктурируйте системный промпт по принципу «закладок»: критические инструкции — в начале и в конце, референсные данные — в середине.
Управление состоянием сессии
Агентам потребуется логировать состояние сессии на диск, чтобы обеспечить более частые передачи между сессиями. Это нетипично для облачных провайдеров с огромными окнами, но критично для локального инференса.
Проблема №4: Скрытая цена «дешёвого» self-hosting
Переход на Ollama мотивирован экономией и приватностью. Но у него есть невидимые издержки.
Сравнение: облако vs self-hosted
| Параметр | Claude Opus / GPT-5 (API) | Self-hosted Ollama |
|---|---|---|
| Контекстное окно | 200K–1M токенов | 32K–128K токенов |
| Настройка промпта | Минимальная | Глубокая реструктуризация |
| Данные сессий | Уходят провайдеру | Остаются локально |
| Стоимость запроса | Per-token billing | CAPEX на железо |
| Стабильность агента | Высокая | Требует ручной настройки |
| Цензура / отказы | Встроены в модель | Управляется вами |
| Latency | Зависит от сети | Предсказуема локально |
Один из главных активов, которые мы получаем от Frontier Providers — не модель, а большое контекстное окно. Они располагают железом для вашего инференса. И в результате получают доступ к данным вашей сессии.
Возможно, самая ценная информация — не ваши данные, а метаданные о ваших сессиях: паттерны запросов, стратегии промптинга, цепочки рассуждений.
Для стабильной высокообъёмной нагрузки локальный инференс позволяет избежать per-token затрат и сохраняет данные на своей машине. Для случайных задач облачный API зачастую дешевле с учётом железа и времени настройки. Точка безубыточности зависит от объёма и ценности приватности.
Практический план миграции
На основе реальных уроков выстраивается следующий порядок действий:
Шаг 1: Аудит и измерение
- Посчитайте токены вашего препромпта (не байты!)
- Определите, сколько токенов занимает типичная сессия
- Установите соотношение: промпт / окно контекста целевой модели
Запустите «канарейковые» диагностические промпты, чтобы измерить, где именно деградирует внимание модели по всему контекстному окну.
Шаг 2: Декомпозиция промпта
Монолитный 35KB промпт
↓
Модуль А: Контекст задачи (5KB)
Модуль Б: Правила поведения (3KB)
Модуль В: Инструменты (4KB)
Модуль Г: Примеры (загружаются по запросу)
Каждый специализированный агент получает только свой модуль — не весь промпт целиком.
Шаг 3: Настройка Ollama
# Создаём Modelfile с правильными параметрами
ollama create my-agent -f ./Modelfile
# Проверяем, что контекст выставлен
ollama show my-agent --modelfile | grep num_ctx
Шаг 4: Мониторинг сигналов деградации
Добавьте в логи агента детектор этих паттернов:
FAILURE_SIGNALS = [
"tool_call_parse_error",
"repeated_file_read", # один файл читается 2+ раза
"rewrite_completed_block", # агент трогает готовые блоки
"instruction_contradiction", # противоречие с ранними инструкциями
]
def detect_context_exhaustion(agent_log: list[str]) -> bool:
return any(
signal in entry
for entry in agent_log
for signal in FAILURE_SIGNALS
)
Шаг 5: State persistence
Агент должен логировать состояние сессии на диск для поддержки частых передач. Перечитывайте только нужный срез — не всё состояние сразу.
{
"session_id": "abc123",
"completed_steps": ["read_repo", "analyze_deps"],
"current_objective": "write_tests",
"artifacts": {"tests_path": "./tests/unit/"},
"context_tokens_used": 18400
}
При передаче новой сессии агент загружает только current_objective и artifacts — не всю историю.
Заключение: self-hosting — это не замена, это другая игра
Эта история о миграции промптов задела нерв у разработчиков, обеспокоенных vendor lock-in: сообщество делится собственными подводными камнями и подтверждает трудно добытые уроки автора.
Главный вывод прост, но его легко пропустить: большой препромпт — это не файл конфигурации, который можно скопировать из одной системы в другую. Это архитектурное решение, завязанное на конкретные характеристики инфраструктуры.
Переход на Ollama даёт реальные преимущества — приватность данных, предсказуемую latency, отсутствие per-token billing. Но он требует:
- Явной настройки контекста — дефолты Ollama для production непригодны
- Декомпозиции монолитного промпта — один агент, одна задача, один срез контекста
- Переписывания запретов в позитивные директивы — меньшие модели плохо держат длинные цепочки «не делай…"
- Реализации state persistence — сессии живут короче, передача должна быть явной
- Мониторинга сигналов деградации — context exhaustion не бросает исключений
Self-hosting меняет уравнение: промпты никогда не покидают ваш сервер, вы получаете стабильную производительность без API rate limits и контролируете расходы — никаких неожиданных счетов, когда команда увлекается AI.
Но за это вы платите инженерными усилиями. И чем больше был ваш исходный препромпт — тем больше этих усилий потребуется.