Промпты, которые заставляют LLM думать: 12 приёмов от few-shot до ReAct на Python

Каждый разработчик, работающий с LLM, рано или поздно упирается в потолок: модель отвечает общими фразами, путает форматы, галлюцинирует или требует десятки итераций, чтобы выдать нужный JSON. Знакомо? Проблема не в модели, а в том, как мы формулируем задачу. Prompt engineering — это не магия, а инженерная дисциплина с конкретными приёмами, каждый из которых решает свою задачу. В этой подборке — 12 промптов-шаблонов, которые я лично использую в продакшене для извлечения данных, рассуждений, агентских циклов и контроля формата. Каждый приём сопровождается примером на Python с OpenAI API и указанием, когда его применять.

Мы пройдём путь от простых few-shot примеров до полноценных ReAct-агентов. Вы увидите, как chain-of-thought повышает точность на математических задачах, как self-consistency убирает случайные ошибки, а structured output через JSON Schema избавляет от парсинга «грязного» текста. Все примеры рабочие — скопируйте, запустите, адаптируйте под свою задачу. В конце вы сможете собрать собственный арсенал промптов под конкретные сценарии.

1. Few-shot prompting: покажи, а не рассказывай

Когда нужно, чтобы модель выдавала ответ в строго определённом стиле или формате, лучший способ — дать несколько примеров «вход → выход». Модель улавливает паттерн и воспроизводит его. Это называется few-shot prompting. Официальная документация OpenAI рекомендует использовать от 2 до 5 примеров для большинства задач.

Когда использовать: классификация, извлечение сущностей, генерация текста по шаблону.

from openai import OpenAI
client = OpenAI()

prompt = """Классифицируй отзыв как positive, negative или neutral.

Отзыв: "Доставка быстрая, но упаковка помята."
Класс: neutral

Отзыв: "Отличный сервис, всё пришло вовремя!"
Класс: positive

Отзыв: "Товар не соответствует описанию, вернул деньги."
Класс: negative

Отзыв: "Поддержка ответила через 5 минут, проблема решена."
Класс:"""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0
)
print(response.choices[0].message.content)  # positive

Совет: примеры должны быть разнообразными и покрывать пограничные случаи. Если в одном примере ответ «positive», а в другом «Positive» — модель начнёт путаться.

2. Chain-of-thought (CoT): заставь рассуждать пошагово

Модели часто ошибаются в арифметике и логике, если просить сразу ответ. Если же попросить «думать пошагово», точность значительно возрастает. Это подтверждено исследованием Google (Wei et al., 2022) — на задаче GSM8K точность выросла с 17% до 58% при использовании CoT.

Когда использовать: математические задачи, логические выводы, планирование.

prompt = """Задача: В корзине 5 яблок. Ты взял 2 яблока, потом добавил ещё 3. Сколько яблок стало?

Реши пошагово:
1. Изначально было 5 яблок.
2. Взял 2 — осталось 3.
3. Добавил 3 — стало 6.
Ответ: 6

Задача: У Пети 10 конфет. Он съел 3, потом купил ещё 5, а затем отдал половину другу. Сколько осталось?

Реши пошагово:"""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0
)
print(response.choices[0].message.content)

Модель выдаст цепочку рассуждений и итоговый ответ. Важно: при использовании CoT увеличивается расход токенов, но точность того стоит.

3. Self-consistency: несколько путей к одному ответу

Self-consistency — это развитие CoT: мы генерируем несколько независимых цепочек рассуждений с температурой > 0 и выбираем наиболее частый ответ. Этот метод предложен в работе Wang et al. (2022) и показывает прирост точности на задачах рассуждений.

Когда использовать: задачи с однозначным ответом, где важна надёжность.

import collections

prompt = """Реши задачу пошагово: В магазине было 120 кг картофеля. Продали 40%, потом привезли ещё 30 кг. Сколько стало?"""

answers = []
for _ in range(5):
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.7
    )
    answers.append(response.choices[0].message.content)

# Извлекаем итоговые числа и выбираем самое частое
# (упрощённо: ищем последнее число в ответе)
numbers = [int(s.split()[-1]) for s in answers]
print(collections.Counter(numbers).most_common(1))

В продакшене лучше использовать более надёжный парсинг, но идея ясна: агрегируем ответы и берём мажоритарный.

4. ReAct: агент, который думает и действует

ReAct (Yao et al., 2022) — это парадигма, где LLM чередует шаги рассуждения (Thought) и действия (Action), получая наблюдения (Observation) из внешней среды. Это основа большинства современных агентов.

Когда использовать: задачи, требующие взаимодействия с API, базами данных, поиском.

def get_weather(city: str) -> str:
    # Заглушка: в реальности вызов API
    return f"Погода в {city}: +20°C, солнечно"

tools = {"get_weather": get_weather}

prompt = """Ты агент. Отвечай в формате:
Thought: твои рассуждения
Action: имя_инструмента(аргумент)
Observation: результат
... (повторяй)
Final Answer: ответ

Вопрос: Какая погода в Москве?"""

# Первый шаг
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0
)
print(response.choices[0].message.content)
# Модель выдаст Thought: ... Action: get_weather(Москва)
# Далее вы парсите Action, вызываете функцию, добавляете Observation и снова запрашиваете модель.

Для полноценного цикла нужно реализовать парсинг и цикл while. Готовые фреймворки: LangChain, LlamaIndex.

5. Structured output через JSON Schema

OpenAI API поддерживает параметр response_format={"type": "json_schema", "json_schema": {...}}, который гарантирует, что модель вернёт валидный JSON по заданной схеме. Это избавляет от парсинга и ошибок.

Когда использовать: извлечение структурированных данных, интеграция с БД.

schema = {
    "name": "person",
    "schema": {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "age": {"type": "integer"},
            "city": {"type": "string"}
        },
        "required": ["name", "age", "city"],
        "additionalProperties": False
    }
}

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Извлеки: Иван, 30 лет, Москва"}],
    response_format={"type": "json_schema", "json_schema": schema},
    temperature=0
)
print(response.choices[0].message.content)  # {"name":"Иван","age":30,"city":"Москва"}

Этот приём критичен для продакшена: вы получаете предсказуемый формат без регулярных выражений.

6. Role prompting: надень маску эксперта

Назначение роли (system message) задаёт тон, стиль и уровень детализации. Модель как бы «входит в образ» и генерирует более релевантные ответы.

Когда использовать: генерация контента, код-ревью, обучение.

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "Ты senior Python-разработчик с 10-летним опытом. Отвечай кратко, с примерами кода и указанием на подводные камни."},
        {"role": "user", "content": "Как правильно логировать в FastAPI?"}
    ],
    temperature=0.5
)
print(response.choices[0].message.content)

Роль можно усилить, добавив ограничения: «не используй библиотеки, кроме стандартной», «пиши на русском».

7. Guardrails: защита от нежелательного вывода

Guardrails — это инструкции, которые ограничивают поведение модели. Например, запрет на выдумывание фактов, на использование определённых слов или на выход за рамки темы.

Когда использовать: чат-боты поддержки, образовательные ассистенты.

system_prompt = """Ты ассистент по продукту. Отвечай только на вопросы о продукте. Если вопрос не по теме, скажи: "Извините, я могу помочь только с вопросами о продукте." Не выдумывай факты. Если не знаешь ответ, скажи: "У меня нет этой информации, обратитесь в поддержку."""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": "А какая погода сегодня?"}
    ],
    temperature=0
)
print(response.choices[0].message.content)  # Извините, я могу помочь только с вопросами о продукте.

Guardrails можно комбинировать с пост-фильтрацией вывода.

8. Zero-shot с инструкцией: чётко и без примеров

Иногда few-shot избыточен. Если задача простая и модель хорошо обучена, достаточно дать чёткую инструкцию. Главное — избегать двусмысленности.

Когда использовать: простые трансформации, перевод, суммаризация.

prompt = """Переведи следующий текст на английский, сохраняя деловой стиль. Верни только перевод, без пояснений.

Текст: "Уважаемые коллеги, напоминаю о встрече в 15:00."""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0
)
print(response.choices[0].message.content)

Ключевые элементы: что сделать, как сделать, что вернуть.

9. Chain of Density: сжатие без потери смысла

Chain of Density (CoD) — техника итеративного суммирования, при которой мы постепенно увеличиваем плотность информации, добавляя пропущенные сущности. Предложена в исследовании (Adams et al., 2023).

Когда использовать: создание аннотаций, кратких выжимок из длинных текстов.

text = """(длинная статья)"""

prompt = f"""Сделай суммаризацию текста в 5 этапов. На каждом этапе добавляй 1-2 пропущенные сущности, сохраняя длину.

Текст: {text}

Этап 1:"""

# Далее итеративно запрашиваем следующие этапы, передавая предыдущий результат.

На практике это реализуется циклом с 5 итерациями.

10. Least-to-Most: разбей задачу на подзадачи

Least-to-Most (Zhou et al., 2022) — стратегия, где сложная задача разбивается на последовательность простых, каждая из которых решается отдельно. Модель сначала декомпозирует, потом решает по шагам.

Когда использовать: сложные многошаговые задачи, программирование.

prompt = """Задача: Напиши функцию на Python, которая принимает список чисел и возвращает сумму квадратов чётных чисел.

Разбей на подзадачи:
1. Отфильтровать чётные числа.
2. Возвести каждое в квадрат.
3. Просуммировать.

Реши каждую подзадачу:
1. [x for x in nums if x % 2 == 0]
2. [x**2 for x in ...]
3. sum(...)

Итоговый код:"""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0
)
print(response.choices[0].message.content)

11. Directional Stimulus: подсказка-стимул

Directional Stimulus Prompting (Li et al., 2023) — добавление в промпт ключевых слов или подсказок, которые направляют модель в нужную сторону. Например, при суммаризации можно указать: «включи слова: инновации, рост, риски».

Когда использовать: генерация текста с заданными акцентами.

prompt = """Напиши краткое резюме отзыва клиента. Обязательно упомяни: скорость доставки, качество упаковки, работу поддержки.

Отзыв: "Заказ пришёл за 2 дня, коробка была немного помята, но товар цел. Поддержка ответила быстро и помогла с возвратом."""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0.3
)
print(response.choices[0].message.content)

12. Program-Aided Language (PAL): код вместо вычислений

PAL (Gao et al., 2023) — подход, при котором модель генерирует не текстовый ответ, а код (обычно Python), который затем выполняется для получения точного результата. Это снимает с модели вычислительную нагрузку.

Когда использовать: математика, анализ данных, сложные вычисления.

prompt = """Напиши Python-код для решения задачи: найти сумму всех простых чисел до 100.

Код:"""

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    temperature=0
)
code = response.choices[0].message.content
print(code)
# Затем выполните код в безопасной среде (например, exec с ограничениями или отдельный процесс)

В продакшене используйте песочницы: exec в изолированном окружении или сервисы вроде E2B.

Как выбрать приём под задачу

Задача Рекомендуемый приём
Классификация, извлечение Few-shot, Structured output
Математика, логика Chain-of-thought, PAL
Надёжность ответа Self-consistency
Агентские сценарии ReAct
Контроль формата JSON Schema, Guardrails
Суммаризация Chain of Density, Directional Stimulus

Начните с простых приёмов (zero-shot, role prompting), затем добавляйте сложные по мере необходимости. Не бойтесь комбинировать: например, ReAct + JSON Schema для структурированных действий агента.

Все примеры кода доступны в документации OpenAI API. Экспериментируйте, замеряйте точность на своих данных и создавайте собственные шаблоны. Помните: хороший промпт — это итеративный процесс. Чем больше вы практикуетесь, тем точнее модель понимает ваши задачи.

Если хотите глубже изучить тему, рекомендую оригинальные статьи: Chain-of-Thought (Wei et al., 2022), ReAct (Yao et al., 2022), Self-Consistency (Wang et al., 2022). Они дают теоретическую базу, которая поможет адаптировать приёмы под ваши нужды.

← All posts

Comments