Регрессионное тестирование при обновлении моделей
Запускайте наборы тестов при переходе с GPT-4 на GPT-4o или с Claude 3 на 3.5.
«Регрессионное тестирование при обновлении моделей» — бесплатный урок AI Prompt Engineering на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Prompt Engineering, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Prompt Engineering содержит 4 уроков всего.
Почему обновления моделей нарушают работу промптов
Поставщики LLM регулярно обновляют свои модели: GPT-4 → GPT-4o → GPT-4o-2024-11-20, Claude 3 → Claude 3.5 → Claude 3.7. Каждое обновление меняет поведение модели: обычно большинство задач выполняется лучше, но для некоторых промптов иногда возникают регрессии.
Без набора тестов регрессии остаются незаметными, пока на них не укажут пользователи. С набором тестов Вы обнаружите регрессии в течение нескольких минут после обновления модели.
Проблема обновления моделей
Обновления моделей могут привести к трём типам изменений:
- Улучшения: ранее завершавшиеся ошибкой тестовые сценарии теперь проходят — это хорошо
- Нейтральные изменения: поведение не изменилось — так происходит с большинством тестов
- Регрессии: ранее успешно проходившие тестовые сценарии теперь завершаются ошибкой — это требует расследования
Даже частота регрессий в 1% значительна: если у Вас есть 200 тестовых сценариев и после обновления модели 2 начинают завершаться ошибкой, эти 2 сценария могут относиться к самым важным вариантам использования.
MODEL_HISTORY = [
{'model': 'gpt-4', 'deployed': '2023-03-14', 'pass_rate': 0.87},
{'model': 'gpt-4-turbo', 'deployed': '2023-11-06', 'pass_rate': 0.91},
{'model': 'gpt-4o', 'deployed': '2024-05-13', 'pass_rate': 0.93},
{'model': 'gpt-4o-2024-11-20', 'deployed': '2024-11-20', 'pass_rate': None}, # to be measured
]
# Goal: measure pass_rate for the new model before deploying to productionЗапуск набора тестов на новой модели
Когда объявлена новая версия модели, запустите полный набор тестов и на старой, и на новой модели. Сравните доли успешных тестов. Определите, в каких именно тестовых сценариях изменилось поведение.
import openai
client = openai.OpenAI(api_key='sk-...')
def run_suite_on_model(test_cases, system_prompt, model):
results = []
for test in test_cases:
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': test['input']}
],
temperature=0
)
output = resp.choices[0].message.content
passed = test['evaluator'](output)
results.append({'id': test['id'], 'passed': passed, 'output': output})
pass_rate = sum(r['passed'] for r in results) / len(results)
return results, pass_rate
old_results, old_rate = run_suite_on_model(TEST_CASES, PROMPT, 'gpt-4o')
new_results, new_rate = run_suite_on_model(TEST_CASES, PROMPT, 'gpt-4o-2024-11-20')
print(f'Old: {old_rate:.1%} | New: {new_rate:.1%} | Delta: {(new_rate-old_rate):+.1%}')Сравнение результатов разных версий модели
После запуска обоих наборов найдите сценарии, в которых изменился статус: успешно → ошибка (регрессии) и ошибка → успешно (улучшения).
def diff_results(old_results, new_results):
old_by_id = {r['id']: r for r in old_results}
new_by_id = {r['id']: r for r in new_results}
regressions = []
improvements = []
for test_id, new_r in new_by_id.items():
old_r = old_by_id.get(test_id)
if old_r is None:
continue
if old_r['passed'] and not new_r['passed']:
regressions.append({'id': test_id, 'old_output': old_r['output'], 'new_output': new_r['output']})
elif not old_r['passed'] and new_r['passed']:
improvements.append({'id': test_id})
print(f'Regressions: {len(regressions)}')
print(f'Improvements: {len(improvements)}')
for reg in regressions:
print(f' REGRESSED: {reg["id"]}')
print(f' Old: {reg["old_output"][:60]}')
print(f' New: {reg["new_output"][:60]}')
return regressions, improvements
regressions, improvements = diff_results(old_results, new_results)Отслеживание версии модели в журналах тестирования
Каждая запись журнала тестирования должна содержать точный идентификатор модели — не просто «gpt-4o», а полную строку с версией «gpt-4o-2024-11-20». OpenAI и Anthropic часто обновляют модель, скрытую за псевдонимом (например, «gpt-4o»), не меняя имя псевдонима, поэтому журнал необходим для отладки поведения в прошлом.
import openai, json
from datetime import datetime, timezone
client = openai.OpenAI(api_key='sk-...')
def run_test_with_version_tracking(test, system_prompt, model_alias):
resp = client.chat.completions.create(
model=model_alias,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': test['input']}
],
temperature=0
)
output = resp.choices[0].message.content
return {
'test_id': test['id'],
'model_alias': model_alias,
'model_actual': resp.model, # The exact versioned model ID returned by the API
'timestamp': datetime.now(timezone.utc).isoformat(),
'output': output,
'passed': test['evaluator'](output)
}Расследование регрессий
Обнаружив регрессию, проведите расследование, прежде чем обновлять промпт. Спросите себя: промпт стал хуже или модель стала лучше, но из-за этого её поведение изменилось?
Например, преемник GPT-4o может строже следовать инструкциям по формату, из-за чего тест завершается ошибкой: старый тест ожидал результат, лишь немного не соответствующий требованиям. В этом случае модель улучшилась, а обновить нужно тест, а не промпт.
def investigate_regression(test_id, old_output, new_output, prompt, user_input):
# Step 1: check if old behavior was actually wrong
judge_prompt = (
f'Given this task prompt: {prompt}\n'
f'And this user input: {user_input}\n\n'
f'Which output is better?\n'
f'A) {old_output}\n'
f'B) {new_output}\n\n'
'Reply with A or B and one sentence explanation.'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': judge_prompt}],
temperature=0
)
verdict = resp.choices[0].message.content
print(f'Judge verdict for {test_id}: {verdict}')
# If judge says B (new output) is better: update the test, not the promptКогда обновлять промпт, а когда — тест
После расследования регрессии выберите одно из трёх действий:
- Обновить промпт: новой модели нужны другие формулировки инструкций, чтобы получить то же поведение
- Обновить тест: ожидаемый результат старого теста был неверным или неоптимальным; новый результат на самом деле лучше
- Принять регрессию: новая модель не может надёжно выполнять эту задачу; используйте для этого варианта применения псевдоним старой модели
REGRESSION_ACTIONS = {
'prompt_updated': {
'when': 'New model ignores instruction the old model followed. Same behavior needed.',
'action': 'Add stronger/rephrased instruction. Re-run tests on new model.'
},
'test_updated': {
'when': 'New model output is objectively better but fails old test criteria.',
'action': 'Update expected output in test. Document the improvement.'
},
'model_pinned': {
'when': 'New model cannot perform this task reliably despite prompt changes.',
'action': 'Pin the model alias to the old versioned ID for this endpoint.'
}
}Фиксация версий моделей
Если обновление модели вызывает неприемлемые регрессии, зафиксируйте предыдущий идентификатор с версией, пока проводите расследование. Не используйте псевдоним (например, «gpt-4o») в рабочей среде — всегда указывайте конкретную версию.
# Bad practice: alias can point to different model versions over time
client.chat.completions.create(
model='gpt-4o', # could be any version at any time
messages=[...]
)
# Good practice: pin to a specific version for production
client.chat.completions.create(
model='gpt-4o-2024-11-20', # guaranteed behavior
messages=[...]
)
# Track in config
MODEL_CONFIG = {
'sentiment_classifier': 'gpt-4o-2024-11-20',
'code_generator': 'gpt-4o-2024-11-20',
'summarizer': 'gpt-4o-mini-2024-07-18',
}Автоматическое регрессионное тестирование в CI
Автоматически запускайте набор регрессионных тестов при изменении версии модели в конфигурации. Используйте GitHub Actions или аналогичную систему непрерывной интеграции, чтобы обнаруживать регрессии до развёртывания.
# .github/workflows/prompt_regression.yml (YAML, shown as comment)
# name: Prompt Regression Tests
# on:
# push:
# paths:
# - 'config/models.json' # triggers when model version changes
# - 'prompts/*.txt' # triggers when prompts change
# jobs:
# test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Install dependencies
# run: pip install pytest openai jsonschema
# - name: Run prompt test suite
# run: pytest tests/prompts/ -v --junitxml=results.xml
# env:
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# In Python: read model version from config
import json
with open('config/models.json') as f:
MODEL_CONFIG = json.load(f)
MODEL = MODEL_CONFIG['sentiment_classifier']Обработка регрессий между поставщиками
Регрессионное тестирование применяется и при смене поставщика: GPT-4o → Claude, Claude → Gemini. Один и тот же набор тестов показывает, какие промпты нужно изменить из-за различий в поведении нового поставщика.
def cross_provider_test(test_cases, system_prompt, providers):
all_results = {}
for provider, config in providers.items():
results, rate = run_suite_on_model(
test_cases, system_prompt, model=config['model']
)
all_results[provider] = {'rate': rate, 'results': results}
print(f'{provider}: {rate:.1%}')
# Find cases that fail on one provider but not another
for test in test_cases:
outcomes = {
p: next(r for r in all_results[p]['results'] if r['id'] == test['id'])['passed']
for p in providers
}
if not all(outcomes.values()):
failing = [p for p, passed in outcomes.items() if not passed]
print(f' {test["id"]}: FAILS on {failing}')
return all_resultsОтслеживание тенденций доли успешных тестов
Стройте график доли успешных тестов во времени, считывая данные из журнала истории тестирования. Снижающаяся тенденция указывает на ухудшение промпта или дрейф модели. Резкое падение указывает на событие регрессии — обновление модели или изменение промпта.
import json
def plot_pass_rate_trend(history_file='test_history.jsonl'):
runs = []
with open(history_file) as f:
for line in f:
runs.append(json.loads(line))
runs.sort(key=lambda r: r['run_id'])
print('Pass rate trend:')
for run in runs[-10:]: # last 10 runs
bar = '#' * int(run['pass_rate'] * 40)
print(f"{run['run_id'][:10]} {run['model']:30} {run['pass_rate']:.0%} |{bar}|")
# Detect regression
if len(runs) >= 2:
delta = runs[-1]['pass_rate'] - runs[-2]['pass_rate']
if delta < -0.05:
print(f'ALERT: pass rate dropped {delta:.0%} since last run!')
plot_pass_rate_trend()Проверка знаний
Когда новая версия модели приводит к ошибке в тесте, а расследование показывает, что результат новой модели на самом деле лучше старого, какое действие будет правильным?
Итоги: регрессионное тестирование при обновлении моделей
Основные методы регрессионного тестирования при обновлении моделей:
- Запускайте полный набор тестов на старой и новой модели — сравнивайте доли успешных тестов и выявляйте различия в конкретных сбоях
- Отслеживайте точную версию модели в каждом журнале тестирования — не только псевдоним
- Расследуйте каждую регрессию: это проблема промпта, теста или возможностей модели?
- Фиксируйте модели в рабочей среде по конкретным идентификаторам с версией, а не по псевдонимам
- Автоматизируйте процесс в CI — запускайте его при изменении конфигурации модели или файла промпта
В следующем уроке Вы узнаете, как создать полный набор тестов промпта с помощью инструментов.
Часто задаваемые вопросы
Урок «Регрессионное тестирование при обновлении моделей» бесплатный?
Да — полный текст урока «Регрессионное тестирование при обновлении моделей» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Prompt Engineering, подпишись на CoddyKit PRO. Курс AI Prompt Engineering содержит 4 уроков всего.
Чему я научусь в уроке «Регрессионное тестирование при обновлении моделей»?
Запускайте наборы тестов при переходе с GPT-4 на GPT-4o или с Claude 3 на 3.5. Ты практикуешь AI Prompt Engineering с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Prompt Engineering?
Предыдущий опыт не требуется. AI Prompt Engineering на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Регрессионное тестирование при обновлении моделей»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Prompt Engineering?
Да. Каждый урок AI Prompt Engineering включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Написание тестовых случаев для запросов
- Тестирование запросов на основе утверждений
- Регрессионное тестирование при обновлении моделей
- Создание набора тестов для запросов