AI для новичковИнструкция
Проверка промпта на 20 примерах: точное совпадение в Python
Соберите набор из 20 примеров, оцените промпт точным совпадением коротким скриптом на Python и узнайте, помогла ли правка на самом деле.

Содержание
Промпт сработал на двух сообщениях, которые вы попробовали. Значит ли это, что он работает? Пока нет. Прогоните его через 20 настоящих сообщений с известными ответами, посчитайте, сколько он угадал, и прочитайте те, где ошибся. Считает короткий скрипт на Python, а когда вы поменяете промпт, тот же скрипт покажет, помогла ли правка, — и не придётся полагаться на ощущения.
Документация Anthropic про критерии успеха и оценочные тесты (проверено 7 ноября 2026 года) говорит то же самое: тесты должны быть про вашу задачу, в них нужны неудобные случаи, а много проверок, которые считает код, лучше, чем несколько, которые вы оцениваете вручную. Ниже — самая маленькая версия такого подхода, которую можно запустить сегодня.

Соберите набор: 20 сообщений и ответ, который вы ждёте#
Допустим, вы раскладываете сообщения клиентов по трём кучкам: positive, negative или mixed. Создайте файл cases.csv и запишите 20 сообщений, которые вам действительно могут прийти, а рядом — метку, которую поставили бы вы сами. Метки пишите до первого запуска. Если брать за «правильные» ответы самой модели, тест сможет только соглашаться с ней.
text,label
"Arrived a day early and works perfectly. Thank you!",positive
"The charger stopped working after two days.",negative
"Great screen, but the battery barely lasts until lunch.",mixed
"Support answered in five minutes and fixed it.",positive
"I waited three weeks and nobody replied.",negative
"Oh great, another update that deletes my settings.",negative
"Nice design. Pity about the price.",mixed
"Exactly what I ordered.",positive
"The box was crushed, but the headphones inside are fine and sound great.",mixed
"Refund took 10 days. Never again.",negative
"Love it!!",positive
"Cheaply made, but honestly it does the job for the price.",mixed
"Worst purchase of the year.",negative
"Five stars. Would buy again.",positive
"Fast delivery, wrong colour.",mixed
"It's fine. Not amazing, not terrible.",mixed
"Zero issues in six months of daily use.",positive
"The app crashes every time I open the camera.",negative
"Thanks for nothing.",negative
"Setup was a pain, but once it ran, it's been rock solid.",mixedПосмотрите на состав: 6 positive, 7 negative, 7 mixed. Саркастические строки («Oh great, another update…», «Thanks for nothing.») и пограничная («It's fine. Not amazing, not terrible.») тут специально. Набор из одних очевидных сообщений даст 100% и ничему не научит. Берите настоящие — из своей почты, тикетов или выгрузки чата; сложные случаи вы и так знаете, они вас раздражают. Сообщения здесь на английском, потому что и промпт английский; у вас они могут быть на любом языке.
Почему 20? Это стартовый размер, а не число из документации (в её примере 1000 твитов). Двадцать примеров можно вписать руками за полчаса, и при этом одна случайная удача не решает итог.
Скрипт: отправить каждый случай, сверить, вывести промахи#
План из четырёх шагов, код идёт строго по нему.
Расставьте по порядку
Расставьте шаги проверки по порядку
Перетащите элементы или используйте стрелки
- Загрузить 20 примеров из CSV
- Отправить каждое сообщение модели вместе с промптом
- Сверить ответ с вашей меткой
- Вывести точность и случаи, где модель ошиблась
Цикл работает, только если метки есть до первого вызова модели, а промахи идут последними, потому что именно их вы читаете и разбираете.
Установите SDK командой pip install openai и положите ключ в переменную окружения CHEAPTOKENS_. Любой OpenAI-совместимый API работает так же; здесь скрипт обращается к CheapTokens и модели GLM-5.3-Flash (подключение описано в документации).
import csv
import os
from openai import OpenAI
client = OpenAI(
base_url='https://api.cheaptokens.dev/v1',
api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'zai-org/GLM-5.3-Flash'
PROMPT = (
'Classify the customer message as positive, negative or mixed. '
'Answer with one word only.'
)
def ask(text):
r = client.chat.completions.create(
model=MODEL,
temperature=0,
max_tokens=100,
messages=[
{'role': 'system', 'content': PROMPT},
{'role': 'user', 'content': text},
],
)
return r.choices[0].message.content or ''
with open('cases.csv', newline='', encoding='utf-8') as f:
cases = list(csv.DictReader(f))
correct, failed = 0, []
for case in cases:
got = ask(case['text'])
ok = got.strip().strip('.').lower() == case['label']
correct += ok
if not ok:
failed.append((case['text'], case['label'], got.strip()))
print(f'Accuracy: {correct}/{len(cases)} = {correct / len(cases):.0%}')
for text, want, got in failed:
print(f'- {text!r}: expected {want}, got {got!r}')На три детали стоит взглянуть ещё раз.
temperature=0делает ответы максимально ровными, так что изменение счёта идёт от вашего промпта, а не от случайности.max_tokens=100намного больше, чем нужно метке из одного слова. Если ответ вдруг пустой или обрезан, посмотритеfinish_reason; разбор finish_reason "length" покажет, что увеличить.- Строка проверки — рецепт из документации:
strip().lower()и сравнение с верным ответом, плюс одно добавление: она ещё отбрасывает точку в конце, потому что «Negative.» и «negative» для вас один и тот же ответ.
Что вы увидите при запуске? Одну строку с точностью и по строке на каждый промах. Допустим, первый запуск выводит такое:
Accuracy: 14/20 = 70%
- 'Oh great, another update that deletes my settings.': expected negative, got 'positive'
- "It's fine. Not amazing, not terrible.": expected mixed, got 'positive'
…(Числа здесь — допущение, чтобы показать вид вывода; у вас будут другие.) Сарказм и пограничные формулировки — как раз то, что короткий промпт любит пропускать. Главное, что вы больше не гадаете: у вас есть список.
Меняйте одно, запускайте снова#
Теперь самое полезное. Прочитайте промахи, выберите причину, поменяйте промпт в одном месте и запустите заново. Правка за раз, иначе не поймёте, какая из них сдвинула счёт.
Сравнение
Промпт v1 → v2: добавили правило и два примера
v1
Classify the customer message as positive, negative or mixed.
Answer with one word only.v2
Classify the customer message as positive, negative or mixed.
Sarcasm counts as negative. Praise plus a complaint is mixed.
Answer with one word only.
Message: Lovely colour, but it arrived with a scratch.
Answer: mixed
Message: Sure, thanks a lot. Now my order is lost.
Answer: negativeДва примера придуманы нарочно. Не вставляйте в промпт сообщение из cases.csv: тогда модель проверяют на ответе, который вы ей же и подсказали, и счёт получится завышенным. Это few-shot, а тестовый набор показывает, окупился ли он. Если же v1 у вас пока расплывчатый, начните с материала как написать хороший промпт, а уже потом измеряйте.
Вставьте v2 в PROMPT (для нескольких строк подойдут тройные кавычки) и запустите скрипт ещё раз. Допустим, он печатает Accuracy: 17/. Ещё три случая верны, значит, v2 выглядит лучше. Насколько этому верить? В наборе из 20 случаев каждый стоит 5 пунктов, так что 70% → 85% — это три сообщения. Хороший намёк, но не доказательство. А если счёт упал, вы узнали не менее ценное и не выкатили промпт хуже прежнего.
Тот же набор, другая модель: держится ли счёт?#
Тот же файл отвечает на второй вопрос: не платите ли вы за больше модели, чем нужно этой задаче? Поменяйте одну строку и запустите снова:
MODEL = 'deepseek-ai/DeepSeek-V4-Flash-0731'Если точность на ваших 20 примерах та же, для этой задачи ответ готов — по вашим данным, а не по таблице лидеров. Если упала, посмотрите, какие сообщения сломались, прежде чем что-то решать.
Сколько это стоит? Возьмём около 150 входных токенов на случай (инструкция плюс сообщение) и около 5 выходных на метку из одного слова. Это 3000 входных и 100 выходных токенов на прогон из 20 случаев — $0.000064 на GLM-5.3-Flash. Десять перезапусков набора — 200 запросов; таблица ниже показывает эту нагрузку для каждой модели, рядом с OpenRouter. На этой нагрузке в сумме, с учётом входа и выхода, каждая модель из таблицы стоит меньше референсной цены OpenRouter.
| Модель | Вход $/1M | Выход $/1M | За запрос | 200 запросов | OpenRouter, 200 запросов |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.0000032 | $0.00064 | $0.0011 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0000028 | $0.00055 | $0.0022 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.0000083 | $0.0017 | $0.0198 |
150 входных и 5 выходных токенов на запрос. Цены за 1M токенов актуальны и меняются вместе с нашими тарифами; столбец OpenRouter показывает справочные цены для той же нагрузки.
В статье мы используем две из них. У GLM-5.3-Flash контекст 390K и до 8192 токенов в ответе; у DeepSeek-V4-Flash контекст 380K, до 32 768 токенов в ответе, одна цена в любое время суток и общий баланс со всеми остальными моделями. Актуальные цены — на странице цен, полный список — в моделях.
Где точное совпадение перестаёт работать#
Точное совпадение работает потому, что верный ответ — одно слово из фиксированного списка. Для открытого текста — пересказов, переписанных абзацев, объяснений — одной строки для сравнения нет. Документация описывает другой путь, оценку моделью, и советует брать в судьи не ту модель, что писала ответ. Всё равно начните с точного совпадения: там, где можно заставить модель отвечать коротко и по списку, это самый дешёвый и понятный тест. Правило из документации: много проверок, которые считает код, лучше, чем мало ручных.
Ещё одна привычка: когда v2 перестаёт улучшаться, не полируйте дальше на тех же 20 сообщениях. Добавьте 5–10 новых, лучше всего — настоящие промахи из работы, и запустите снова.
Быстрая проверка
v2 набрал 17/20, а v1 — 15/20 на тех же примерах. Какой вывод самый осторожный?
Показать ответ
Ответ: v2 выглядит лучше, но разница в два случая из 20 мала: добавьте новые примеры и запустите снова
Каждый случай — 5 пунктов, поэтому разрыв в два случая — повод присмотреться, а не приговор. Следующая проверка — новые примеры, которых v2 ещё не видел.



