localaiforum
Войти
Руководство › Работа с моделями

Промпты и чат-шаблоны

Каждое отправленное вами сообщение оборачивается в разметку до того, как модель его увидит. Чат-шаблон превращает ваши сообщения с ролевыми тегами в одну плоскую токен-строку, и модель обучена читать именно эту строку — а не ваши аккуратные API-объекты. Правильный конверт — и instruct-модель на 3B ведёт себя прилично; неправильный — и модель на 70B выдаёт словесную кашу.

Конверт: один чат, три диалекта

Ваш API открывает роли: system, user, assistant. Модель видит специальные токены. Один и тот же разговор из двух сообщений, отрендеренный тремя способами.

ChatML — модели семейства Qwen и файнтюны линии Hermes:

<|im_start|>system
You are a concise assistant.<|im_end|>
<|im_start|>user
Summarize this file.<|im_end|>
<|im_start|>assistant

Стиль Llama 2 — системные маркеры вложены в первую инструкцию:

<s>[INST] <<SYS>>You are a concise assistant.<</SYS>>

Summarize this file. [/INST] The file implements a tokenizer... </s>

Стиль Gemma — системной роли нет; инструкции едут на первом пользовательском ходе, а ассистент называется model:

<bos><start_of_turn>user
You are a concise assistant.

Summarize this file.<end_of_turn>
<start_of_turn>model

Тот же разговор, три несовместимых конверта. Модель, обученная на ChatML, не «догадается» про разметку Llama — она примет чужую разметку за обычный текст и ответит в том же духе.

Движки читают шаблон из файла модели

Метаданные GGUF встраивают chat_template (сниппет Jinja). llama.cpp, Ollama, LM Studio и Open WebUI читают его и рендерят ваши сообщения автоматически — вот почему чат работает из коробки с правильным GGUF. Две классические ловушки: сырой эндпоинт дополнения (/completion) пропускает шаблон и суёт модели голый текст — используйте чат-эндпоинт; и GGUF может прийти с отсутствующим или неверным шаблоном — передайте его явно (--chat-template в llama.cpp, Modelfile в Ollama) или возьмите другой квант той же модели у источника, который сделал правильно.

Симптомы неверного шаблона

  • Мгновенный пустой ответ — отрендеренный промпт уже выглядит как законченный разговор, и модель сразу выдаёт EOS.
  • Утечка ролей — вывод читается как user: sure thing! assistant: — модель имитирует конверт вместо ответа.
  • Мусор — словесная каша базовой модели от модели, которая час назад нормально болтала, потому что вы сменили файл, не сменив шаблон.

Для диагностики дампьте отрендеренный промпт — сервер llama.cpp логирует его подробно, OLLAMA_DEBUG=1 показывает его в Ollama. Затем чините шаблон или файл: диагностика.

Системные промпты и приоритет

Системная роль задаёт устойчивое поведение: персону, язык, формат вывода, позицию безопасности. Это контекст, а не прошивка — длинный разговор может его смыть, а маленькие модели взвешивают его меньше, чем вы надеетесь. Два практичных правила: всё несущее (язык, форматный контракт, жёсткие ограничения) кладите в системный промпт и повторяйте в финальном сообщении пользователя; побеждают инструкции, ближайшие к генерации.

Zero-shot против few-shot

Zero-shot просит; few-shot показывает. Извлечение структурированных полей из баг-репортов моделью 3B, zero-shot — «Extract the title, component, and severity as JSON» — даёт валидный JSON с постоянными ключами примерно в двух третях случаев, с дрейфом имён ключей (severity в один ход, priority в следующий).

Few-shot: та же модель, два разобранных примера, третий отчёт оставлен открытым:

Report: "Login button does nothing on Safari 17."
{"title": "Login button unresponsive", "component": "auth", "severity": "medium"}

Report: "App crashes when uploading 4K video."
{"title": "Crash on 4K upload", "component": "upload", "severity": "high"}

Report: "Dark mode makes settings text unreadable."

Примеры несут форматный контракт, так что сэмплер выбирает содержание вместо изобретения схемы. На этом классе задач частота форматных провалов обычно падает с ~30% до нескольких процентов. Два-три примера — колено кривой; дальше вы платите токенами контекста. Для строгих схем пропустите угадывание совсем: структурированный вывод.

Паттерны, которые выживают на маленьких моделях

Паттерн Почему работает
Одна задача на промпт Задачи конкурируют за внимание; проигравшие теряются
Явный формат вывода («JSON с ключами a, b, c») Превращает формат в почти детерминированный выбор
Нумерованные шаги («1) найти 2) объяснить 3) патчить») Цепочка держится на рельсах вместо блужданий
Примеры вместо описаний Модели имитируют лучше, чем подчиняются прозе
Короткие мета-инструкции Каждое лишнее правило разбавляет каждое другое

Середина контекста — где инструкции умирают

Внимание сильнее всего в начале и в конце промпта — эффект «потерянных в середине», стабильный по семействам моделей. Практичная расстановка: цель и форматный контракт сверху, документ для обработки снизу, а для длинных документов — однострочное повторение инструкции после полезной нагрузки. Позиция несуща так же, как содержание, — и каждая лишняя реплика контекста стоит памяти: KV-кэш.

Стоп-последовательности

Генерация заканчивается, когда модель выдаёт свой токен EOS — шаблон определяет, какой это токен. Дополнительные стоп-последовательности (параметр stop на сервере llama.cpp и OpenAI-совместимых API) обрезают по строке: полезно, когда болтливая модель начинает писать ваш следующий ход пользователя. Выбирайте стопы, которые могут означать только «ход окончен» (\n<|im_start|> на ChatML-моделях), никогда строки, встречающиеся внутри легитимных ответов, — голый перевод строки обрежет многострочный код посреди блока.

Краткость бьёт многословие ниже ~7B

Маленькие instruct-модели следуют инструкции на 40 слов лучше, чем рубрике на 400: их ограниченное внимание размазывается по всему, что вы им дали. Структура и примеры заменяют правила-прозу. Эссе-промпты приберегите большим моделям; только они читают каждую строку.

Переиспользуемые шаблоны-сниппеты

Извлечение:

Extract from the text below: person names, dates, money amounts.
Return a JSON array, one object per item, keys: name, date, amount.
No prose before or after the JSON.
Text: {text}

Суммаризация:

Summarize in exactly 3 bullet points, each under 15 words,
for someone who skipped the meeting. Most important decision first.
Text: {text}

Ревью кода:

Review the diff below. List at most 5 findings, ordered by severity.
Format each as: [severity] file:line — problem — suggested fix.
Skip praise and summary. Diff: {diff}

Связанные разделы: токены · структурированный вывод · параметры движка · диагностика