UpPetto

This is a real course generated by UpPetto — unedited.

AI-generated · source-grounded review: written by two AI models, cross-checked by a third. Yours takes ~5 minutes.

Create my own course

Адаптация к обновлениям моделей

Природа проблемы обновлений

Языковые модели обновляются регулярно: улучшается качество, расширяются возможности, меняется поведение. Промпт, идеально работавший на одной версии модели, может давать другие результаты на новой версии. Это особенность эволюции моделей.

Типы изменений при обновлениях:

  1. Улучшение capabilities: модель лучше понимает инструкции, требуется меньше примеров
  2. Изменение поведения: другая интерпретация неоднозначных инструкций
  3. Изменение формата: структура ответа может измениться даже при явном указании формата
  4. Регрессии: возможны ухудшения на специфичных задачах

Реальный пример проблемы:

# Промпт работал на модели v1
PROMPT_V1 = """
Извлеки из текста даты в формате ISO.
Текст: {text}
Ответ: список дат через запятую
"""

# На модели v1:
# Input: "Встреча 15 марта и 20 апреля"
# Output: "2024-03-15, 2024-04-20" ✅

# На модели v2 (после обновления):
# Output: "Даты из текста: 2024-03-15, 2024-04-20" ❌
# Добавился префикс, ломается парсинг

Стратегия регрессионного тестирования

1. Создание test suite для критичных промптов:

# test_prompts.py
import pytest
from typing import List, Dict

class PromptTestCase:
    def __init__(self, name: str, prompt_template: str, 
                 inputs: Dict, expected_output: Dict, 
                 validation_fn: callable):
        self.name = name
        self.prompt_template = prompt_template
        self.inputs = inputs
        self.expected_output = expected_output
        self.validation_fn = validation_fn

# Тест-кейсы для классификатора тикетов
TICKET_CLASSIFIER_TESTS = [
    PromptTestCase(
        name="technical_issue_high_priority",
        prompt_template=TICKET_CLASSIFIER_PROMPT,
        inputs={
            "ticket_text": "Не могу войти в систему, срочно нужен доступ",
            "customer_tier": "enterprise"
        },
        expected_output={
            "category": "technical",
            "priority": "high"
        },
        validation_fn=lambda out: (
            out["category"] == "technical" and 
            out["priority"] in ["high", "critical"] and
            out["confidence"] > 0.7
        )
    ),
    PromptTestCase(
        name="feature_request_low_priority",
        prompt_template=TICKET_CLASSIFIER_PROMPT,
        inputs={
            "ticket_text": "Было бы удобно добавить темную тему",
            "customer_tier": "basic"
        },
        expected_output={
            "category": "feature_request",
            "priority": "low"
        },
        validation_fn=lambda out: (
            out["category"] == "feature_request" and 
            out["priority"] == "low"
        )
    ),
    # ... еще тест-кейсы для покрытия edge cases
]

def run_regression_tests(model_name: str, test_cases: List[PromptTestCase]):
    results = []
    for test in test_cases:
        prompt = test.prompt_template.format(**test.inputs)
        output = call_llm(model_name, prompt)

        passed = test.validation_fn(output)
        results.append({
            "test_name": test.name,
            "passed": passed,
            "output": output,
            "expected": test.expected_output
        })

    pass_rate = sum(r["passed"] for r in results) / len(results)
    return pass_rate, results

# Запуск при обновлении модели
old_model_pass_rate, _ = run_regression_tests("model-v1", TICKET_CLASSIFIER_TESTS)
new_model_pass_rate, details = run_regression_tests("model-v2", TICKET_CLASSIFIER_TESTS)

if new_model_pass_rate < old_model_pass_rate - 0.05:  # Падение >5%
    print("⚠️ Регрессия обнаружена, требуется адаптация промпта")

2. Минимальный набор тестов:

Для каждого production промпта нужно минимум: - 3-5 типичных случаев (happy path) - 2-3 граничных случая (edge cases) - 1-2 негативных теста (что НЕ должно проходить)

3. Автоматизация проверки:

# .github/workflows/prompt_regression.yml
name: Prompt Regression Tests

on:
  schedule:
    - cron: '0 2 * * 1'  # Каждый понедельник в 2:00
  workflow_dispatch:  # Ручной запуск

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Run regression tests
        run: python test_prompts.py
      - name: Report results
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "⚠️ Prompt regression detected on new model version"
            }

Версионирование промптов и моделей

Стратегия связывания версий:

# prompt_registry.py
from dataclasses import dataclass
from typing import Dict, List

@dataclass
class PromptVersion:
    version: str
    prompt_template: str
    tested_models: List[str]
    performance_metrics: Dict[str, float]
    created_at: str
    deprecated: bool = False

class PromptRegistry:
    def __init__(self):
        self.prompts: Dict[str, List[PromptVersion]] = {}

    def register(self, prompt_id: str, version: PromptVersion):
        if prompt_id not in self.prompts:
            self.prompts[prompt_id] = []
        self.prompts[prompt_id].append(version)

    def get_for_model(self, prompt_id: str, model_name: str) -> PromptVersion:
        """Получить оптимальную версию промпта для конкретной модели"""
        versions = self.prompts.get(prompt_id, [])

        # Ищем версию, специально оптимизированную для этой модели
        for v in reversed(versions):  # Новые версии первыми
            if not v.deprecated and model_name in v.tested_models:
                return v

        # Fallback на последнюю не-deprecated версию
        for v in reversed(versions):
            if not v.deprecated:
                return v

        raise ValueError(f"No valid prompt version for {prompt_id}")

# Использование
registry = PromptRegistry()

registry.register("ticket_classifier", PromptVersion(
    version="2.0",
    prompt_template=TICKET_CLASSIFIER_V2,
    tested_models=["gigachat-pro", "gpt-4"],
    performance_metrics={"accuracy": 0.92},
    created_at="2024-01-15"
))

# В production коде
current_model = "gigachat-pro"
prompt_version = registry.get_for_model("ticket_classifier", current_model)
prompt = prompt_version.prompt_template.format(**inputs)

Мониторинг качества в production

1. Метрики для отслеживания:

# monitoring.py
from dataclasses import dataclass
from datetime import datetime
import numpy as np

@dataclass
class PromptMetrics:
    prompt_id: str
    model_version: str
    timestamp: datetime

    # Качественные метрики
    avg_confidence: float
    low_confidence_rate: float  # % ответов с confidence <0.7

    # Производительность
    avg_latency_ms: float
    p95_latency_ms: float

    # Стоимость
    avg_tokens: int

    # Валидация
    format_error_rate: float  # % ответов с невалидным форматом

def calculate_metrics(responses: List[Dict]) -> PromptMetrics:
    confidences = [r.get("confidence", 0) for r in responses]
    latencies = [r["latency_ms"] for r in responses]
    tokens = [r["tokens_used"] for r in responses]

    return PromptMetrics(
        prompt_id=responses[0]["prompt_id"],
        model_version=responses[0]["model"],
        timestamp=datetime.now(),
        avg_confidence=np.mean(confidences),
        low_confidence_rate=sum(c < 0.7 for c in confidences) / len(confidences),
        avg_latency_ms=np.mean(latencies),
        p95_latency_ms=np.percentile(latencies, 95),
        avg_tokens=int(np.mean(tokens)),
        format_error_rate=sum(r.get("format_valid", True) == False for r in responses) / len(responses)
    )

# Алерты при деградации
def check_for_degradation(current: PromptMetrics, baseline: PromptMetrics):
    alerts = []

    if current.avg_confidence < baseline.avg_confidence - 0.1:
        alerts.append(f"⚠️ Confidence dropped: {baseline.avg_confidence:.2f} → {current.avg_confidence:.2f}")

    if current.low_confidence_rate > baseline.low_confidence_rate * 1.5:
        alerts.append(f"⚠️ Low confidence rate increased")

    if current.format_error_rate > baseline.format_error_rate * 2:
        alerts.append(f"⚠️ Format errors increased")

    return alerts

2. Dashboard для мониторинга:

Ключевые графики: - Confidence distribution: гистограмма confidence scores за последние дни - Error rate timeline: динамика format_error_rate и low_confidence_rate - Latency percentiles: p50, p95, p99 по времени ответа - Cost tracking: стоимость на запросы, тренд

3. A/B тестирование при миграции:

# Постепенный переход на новую модель
class PromptRouter:
    def __init__(self, old_model: str, new_model: str, 
                 new_model_traffic_percent: int):
        self.old_model = old_model
        self.new_model = new_model
        self.new_model_traffic = new_model_traffic_percent

    def route(self, request_id: str) -> str:
        # Детерминированный выбор на основе request_id
        hash_val = hash(request_id) % 100
        return self.new_model if hash_val < self.new_model_traffic else self.old_model

# Миграция: 0% → 10% → 25% → 50% → 100% с мониторингом на каждом этапе
router = PromptRouter("model-v1", "model-v2", new_model_traffic_percent=10)
model = router.route(request_id)

Минимизация затрат на адаптацию

1. Принципы устойчивых промптов:

✅ Делайте инструкции явными и недвусмысленными
❌ "Ответь кратко" → ✅ "Ответь одним предложением, максимум 20 слов"

✅ Используйте структурированные форматы (JSON с schema)
❌ "Ответь списком" → ✅ "Ответь JSON: {"items": [...]}"

✅ Добавляйте примеры (few-shot) для критичных форматов

✅ Валидируйте выход программно, не полагайтесь на формат "как есть"

2. Fallback стратегии:

def robust_llm_call(prompt: str, model: str, max_retries: int = 2):
    """Вызов с автоматической адаптацией при проблемах"""

    for attempt in range(max_retries + 1):
        response = call_llm(model, prompt)

        # Валидация формата
        if validate_format(response):
            return response

        # Если формат неверный, уточняем промпт
        if attempt < max_retries:
            prompt = f"{prompt}\n\nВНИМАНИЕ: Строго соблюдай формат ответа. Пример:\n{EXAMPLE_OUTPUT}"

    # Последняя попытка: используем стабильную версию модели
    return call_llm(STABLE_MODEL, prompt)

3. Документирование изменений:

## Model Update Log: model-v1 → v2

**Дата миграции**: [дата]
**Затронутые промпты**: X из Y

### Изменения в поведении
1. **Ticket Classifier**: добавляет префикс в ответе
   - Решение: обновлён парсер, добавлена инструкция "ответь только JSON"
   - Статус: ✅ Исправлено

2. **Product Description Generator**: изменилась креативность
   - Решение: явно указан параметр temperature
   - Статус: ✅ Исправлено

### Затраты на адаптацию
- Время: несколько часов (тестирование + исправления)
- Downtime: минимальный (постепенная миграция через A/B)

### Lessons learned
- Few-shot примеры делают промпты более устойчивыми
- Явное указание параметров генерации критично
- Регрессионные тесты помогают найти проблемы до production

Обновления моделей неизбежны, но управляемы. Стратегия: (1) регрессионное тестирование с автоматизированным test suite для критичных промптов, (2) версионирование промптов с привязкой к версиям моделей через registry, (3) мониторинг метрик качества в production с алертами при деградации, (4) постепенная миграция через A/B тестирование. Устойчивые промпты (явные инструкции + few-shot + структурированный формат + программная валидация) минимизируют затраты на адаптацию. Документирование каждой миграции создаёт базу знаний для будущих обновлений.

AI-generated · source-grounded review

🛡 Fact-checked: 3 risky claims verified · 8 removed · confidence: high
[removed] GPT-4-0613, GPT-4-1106, GPT-4-turbo version numbers
Specific model version numbers not in knowledge base, replaced with generic version references
[removed] gigachat-pro-v1, gigachat-pro-v2 version numbers
Specific version numbers not verifiable, replaced with generic references
[removed] Accuracy improvements +3%, +5%
Specific percentage improvements not verifiable
[verified] Few-shot prompting technique
Explicitly mentioned in knowledge base under 'Техники промпт-инжиниринга'
[verified] Regression testing for prompts
Testing prompts on new model versions mentioned in knowledge base
[verified] A/B testing for model migration
Standard practice for gradual rollout, consistent with monitoring concepts
[removed] Removed specific model version names 'GPT-4-0613', 'GPT-4-1106', 'GPT-4-turbo', 'gigachat-pro-v1', 'gigachat-pro-v2' - replaced with generic 'model-v1', 'model-v2'
[removed] Removed specific dates from examples
[removed] Removed specific time savings '200 часов/месяц'
[removed] Removed specific cost '~500 RUB'
[removed] Removed specific accuracy improvements '+3% accuracy', '+5% accuracy'
[removed] Softened specific time estimates '8 часов' to 'несколько часов'
[removed] Removed specific downtime claim '0'
[removed] Removed specific confidence thresholds where not essential

A second opinion has not checked this lesson.

Key concepts: Обновления моделей Регрессионное тестирование Мониторинг качества Поддержка
Tell me more 🔒 Didn't understand — explain simply 🔒 Show examples 🔒 Sources 🔒

On your own course these buttons answer instantly, quizzes track what you've mastered, and lessons adapt to your gaps. Sign up free →

Check yourself

1. Что должен включать минимальный regression test suite для production промпта?
2. Как минимизировать риски при миграции на новую версию модели?
3. Какие метрики критичны для мониторинга качества промптов в production?
Sign up free to check your answers