12 приёмов prompt engineering, которые превращают LLM из болтуна в точного исполнителя
Большинство разработчиков общаются с LLM как с человеком: пишут вежливое описание задачи и надеются на удачу. В продакшене это не работает — модель выдаёт то JSON, то Markdown, то внезапно начинает «объяснять» вместо того, чтобы вернуть данные. Разница между демо и рабочим пайплайном почти всегда лежит в одном месте — в промте.
Ниже — 12 приёмов prompt engineering, которые я регулярно применяю в задачах извлечения данных, рассуждений и агентских циклов. Каждый приём — это конкретный шаблон промта, пример на Python через OpenAI API и указание, когда его вообще стоит брать. Всё проверено на реальных проектах, а не переписано из туториалов.
Базовые понятия: prompt engineering — это проектирование входного текста так, чтобы модель стабильно выдавала нужный результат. Few-shot prompting — обучение модели на примерах прямо в промте. Chain-of-thought (CoT) — принудительное пошаговое рассуждение. ReAct — паттерн, где модель чередует рассуждение и вызов инструментов. Все примеры используют официальный SDK openai для Python.
1. Zero-shot с явной спецификацией формата
Самый недооценённый приём. Модель не угадывает формат — ей его описывают явно. Если нужен JSON, пишите «верни JSON», а не «верни структурированные данные».
from openai import OpenAI
client = OpenAI()
prompt = """Извлеки из текста название компании и год основания.
Верни ТОЛЬКО JSON вида {"company": string, "year": int}.
Без пояснений, без markdown-обёртки.
Текст: Компания Acme основана в 2011 году в Берлине."""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0,
)
print(resp.choices[0].message.content)
Когда применять: простые задачи извлечения, где формат критичен, а логика тривиальна. temperature=0 обязателен — иначе формат будет плавать.
2. Few-shot: три примера вместо трёх абзацев инструкций
Few-shot prompting заменяет длинное объяснение правил набором примеров «вход → выход». Модель выводит паттерн сама, и это работает надёжнее любого описания.
prompt = """Классифицируй тональность отзыва. Примеры:
Отзыв: "Быстро доставили, всё отлично" -> positive
Отзыв: "Товар пришёл с царапиной" -> negative
Отзыв: "Нормально, ничего особенного" -> neutral
Отзыв: "Поддержка ответила за 5 минут, но цена кусается" ->"""
Когда применять: классификация, разметка, приведение текста к единому стилю. Правило: 3–5 примеров покрывают большинство краевых случаев. Если нужно больше 8 — задача слишком сложная для промта, пора дообучать или строить пайплайн.
3. Chain-of-thought: «думай пошагово»
Chain-of-thought prompting заставляет модель проговаривать промежуточные шаги до финального ответа. Это резко повышает точность на задачах, где нужна арифметика или многошаговая логика. Техника описана в работе Wei et al. «Chain-of-Thought Prompting Elicits Reasoning in Large Language Models» (arXiv:2201.11903).
prompt = """Задача: В корзине 23 яблока. 7 съели, потом добавили в 3 раза больше, чем съели.
Сколько яблок стало?
Реши пошагово, затем дай финальный ответ строкой 'ОТВЕТ: <число>'."""
Важно: CoT несовместим с жёстким JSON-выводом в одном шаге. Либо разделяйте на два вызова (сначала рассуждение, потом структурирование), либо используйте поле reasoning внутри JSON.
4. Self-consistency: несколько прогонов и голосование
Self-consistency — надстройка над CoT: модель запускается несколько раз с temperature > 0, и финальный ответ выбирается большинством голосов. Описано в arXiv:2203.11171. Отлично работает на задачах с однозначным ответом.
from collections import Counter
import re
answers = []
for _ in range(5):
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": cot_prompt}],
temperature=0.7,
)
txt = r.choices[0].message.content
m = re.search(r"ОТВЕТ:\s*(\d+)", txt)
if m:
answers.append(m.group(1))
print(Counter(answers).most_common(1))
Когда применять: математика, логические задачи, извлечение чисел. Стоимость — N вызовов вместо одного. Для продакшена берите N=3–5.
5. Role prompting: задай роль и границы
Role prompting — задание модели конкретной роли и ограничений. Работает не магией, а тем, что сужает пространство стилей и лексики.
system = """Ты — senior Python-ревьюер. Отвечай кратко: список замечаний, каждое с указанием строки и severity (low/medium/high).
Не переписывай весь код. Не хвали. Только проблемы и предложения."""
Грабли: роль без границ даёт болтливость. «Ты — эксперт» ничего не значит. «Ты — эксперт, отвечай списком из максимум 5 пунктов, без вступлений» — уже инструмент.
6. Structured Output через JSON Schema
OpenAI API поддерживает response_format с JSON Schema — модель гарантированно вернёт валидную структуру. Это не промт, но это тот самый приём, который убирает 90% парсинга регулярок.
from pydantic import BaseModel
class Invoice(BaseModel):
vendor: str
total: float
currency: str
resp = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[{"role": "user", "content": "Извлеки данные из счёта: ООО Ромашка, 15000 RUB"}],
response_format=Invoice,
)
print(resp.choices[0].message.parsed)
Когда применять: любой продакшен, где ответ идёт в код. Официальная документация — platform.openai.com/docs/guides/structured-outputs.
7. ReAct: рассуждение + действие
ReAct (arXiv:2210.03629) — паттерн, где модель чередует Thought / Action / Observation. Это основа большинства агентов. Модель думает, выбирает инструмент, получает результат и продолжает.
tools = {
"calc": lambda x: str(eval(x)),
"now": lambda _: "2026-10-03",
}
system = """Отвечай строго в формате:
Thought: <рассуждение>
Action: <calc|now>
Action Input: <строка>
Если ответ готов: Final Answer: <ответ>"""
history = "Question: Сколько дней прошло с 2026-01-01?"
for _ in range(5):
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": system},
{"role": "user", "content": history}],
temperature=0,
)
out = r.choices[0].message.content
history += "\n" + out
if "Final Answer:" in out:
print(out); break
# ...парсинг Action и вызов tools[...]
Когда применять: задачи с внешними данными — поиск, API, калькулятор. Без инструментов ReAct бессмысленен.
8. Guardrails: явные запреты и fallback
Guardrails — это правила «что делать, если». Без них модель галлюцинирует вместо «не знаю».
system = """Если в тексте нет ответа — верни ровно строку NO_ANSWER.
Не придумывай факты. Не используй знания вне предоставленного контекста.
Отвечай только на русском."""
Когда применять: RAG, юридические и медицинские задачи, всё, где ошибка дороже отказа.
9. Negative prompting: что НЕ делать
Модели лучше следуют явным запретам, чем общим пожеланиям. «Не используй слово "важно"» работает точнее, чем «пиши естественно».
prompt = """Перепиши текст. Запрещено: слово 'является', пассивный залог, вводные 'стоит отметить'. Сохрани смысл и длину."""
10. Prompt chaining: разбей на шаги
Один сложный промт всегда хуже, чем три простых подряд. Каждый шаг получает чистый вход и отдаёт чистый выход.
def step(prompt, text):
return client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": f"{prompt}\n\n{text}"}],
temperature=0,
).choices[0].message.content
summary = step("Сократи текст до 3 предложений:", raw)
key_points = step("Выдели 5 тезисов списком:", summary)
Когда применять: суммаризация, генерация отчётов, любые многоэтапные трансформации. Плюс — каждый шаг легко тестировать.
11. Context injection: управляемый контекст
Модель не помнит ничего между вызовами. Весь контекст нужно подавать явно и в правильном порядке: сначала системные правила, потом данные, потом вопрос.
messages = [
{"role": "system", "content": "Отвечай только по документу ниже."},
{"role": "user", "content": f"Документ:\n{doc}\n\nВопрос: {q}"},
]
Правило: чем ближе к концу промта — тем сильнее влияние. Инструкции в конце работают лучше, чем в начале.
12. Meta-prompting: попроси модель улучшить промт
Самый быстрый способ отладить промт — попросить LLM переписать его. Работает на удивление хорошо.
meta = f"""Вот мой промт и проблемный ответ. Предложи улучшенный промт.
Промт: {my_prompt}
Проблема: {bad_output}
Верни только новый промт."""
Сводная таблица приёмов
| Приём | Задача | Стоимость | Сложность |
|---|---|---|---|
| Zero-shot + формат | Извлечение | 1 вызов | низкая |
| Few-shot | Классификация | 1 вызов | низкая |
| Chain-of-thought | Рассуждения | 1 вызов | низкая |
| Self-consistency | Точные ответы | 3–5 вызовов | средняя |
| Role prompting | Стиль ответа | 1 вызов | низкая |
| JSON Schema | Структура | 1 вызов | низкая |
| ReAct | Агенты | N вызовов | высокая |
| Guardrails | Безопасность | 1 вызов | низкая |
| Negative prompting | Стиль | 1 вызов | низкая |
| Prompt chaining | Пайплайны | 2–5 вызовов | средняя |
| Context injection | RAG | 1 вызов | средняя |
| Meta-prompting | Отладка | 2 вызова | низкая |
Что реально даёт результат
На практике 80% проблем решаются тремя вещами: явным форматом вывода, temperature=0 и разбиением задачи на шаги. Остальные приёмы — точечные инструменты под конкретный класс задач. ReAct нужен только там, где есть инструменты. Self-consistency — только там, где ответ однозначен. Few-shot — только там, где правила сложно описать словами.
Главное правило: промт — это код. Его нужно версионировать, тестировать на наборе примеров и переписывать, когда модель обновляется. Промт, который работал на GPT-3.5, может вести себя иначе на GPT-4o — и наоборот.
Возьмите любой приём из списка, примените к своей текущей задаче и сравните результат на 10 примерах. Это займёт 15 минут и покажет больше, чем любая статья.
Комментарии