0Pricing
AI Prompt Engineering · Урок

Стратегии развёртывания и отката

Сине-зелёное развёртывание запросов, флаги функций и откат при регрессии.

«Стратегии развёртывания и отката» — бесплатный урок AI Prompt Engineering на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Prompt Engineering, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Prompt Engineering содержит 4 уроков всего.

Проблемы развёртывания промптов

Развёртывание новой версии промпта в рабочую среду сопряжено с реальным риском — изменение, улучшающее среднее качество, может ухудшить обработку пограничных случаев, вызвать скачки задержки или запутать пользователей. Стратегии контролируемого развёртывания управляют этим риском, ограничивая радиус воздействия и обеспечивая быстрый откат.

Сине-зелёное развёртывание промптов

Сине-зелёное развёртывание поддерживает две среды: синюю (текущая рабочая среда) и зелёную (новая версия). После проверки трафик атомарно переключается с синей среды на зелёную. Если зелёная среда не работает, переключение мгновенно выполняется обратно.

  • Переключение без простоя
  • Обе версии одновременно остаются готовыми к работе
  • Откат — это одно изменение конфигурации, а не повторное развёртывание
# prompt_router.py — blue/green traffic control
class PromptRouter:
    def __init__(self):
        self.slots = {
            'blue': None,   # {'prompt_id': ..., 'version': ...}
            'green': None,
        }
        self.active_slot = 'blue'

    def load_slot(self, slot, prompt_id, version, template):
        self.slots[slot] = {
            'prompt_id': prompt_id,
            'version': version,
            'template': template
        }
        print(f'Loaded {prompt_id}@{version} into {slot} slot')

    def switch_to(self, slot):
        if not self.slots[slot]:
            raise ValueError(f'Slot {slot} is empty')
        self.active_slot = slot
        info = self.slots[slot]
        print(f'Traffic now routed to {slot}: {info["prompt_id"]}@{info["version"]}')

    def get_active_template(self):
        return self.slots[self.active_slot]['template']

Разделение трафика для постепенного развёртывания

Вместо того чтобы сразу переключать 100% трафика, постепенно увеличивайте долю запросов, направляемых на новую версию. Распространённая последовательность: 1% → 5% → 10% → 25% → 50% → 100%, с мониторингом качества на каждом этапе.

import random

class TrafficSplitter:
    def __init__(self):
        # version_weights: {version_id: percentage}
        self.version_weights = {
            'v1.1.0': 90,
            'v1.2.0': 10
        }

    def select_version(self):
        versions = list(self.version_weights.keys())
        weights = list(self.version_weights.values())
        return random.choices(versions, weights=weights, k=1)[0]

    def update_split(self, new_weights):
        assert sum(new_weights.values()) == 100, 'Weights must sum to 100'
        self.version_weights = new_weights
        print(f'Traffic split updated: {new_weights}')

# Usage
splitter = TrafficSplitter()
for _ in range(5):
    print(splitter.select_version())

# Ramp to 25%
splitter.update_split({'v1.1.0': 75, 'v1.2.0': 25})

Функциональные флаги для развёртывания промпта

Функциональные флаги позволяют включить новую версию промпта для определённых пользователей или сегментов (бета-пользователей, сотрудников компании) до полного развёртывания. Это сочетает безопасность постепенного развёртывания с целевой проверкой на реальных сценариях использования.

# Feature flag-based prompt selection
BETA_USER_IDS = {'user_123', 'user_456', 'user_789'}

def select_prompt_version(user_id, prompt_id, registry):
    # Check if user is in beta cohort
    if user_id in BETA_USER_IDS:
        # Try to get a beta version tagged for this prompt
        beta = registry.get_version_by_tag(prompt_id, tag='beta')
        if beta:
            return beta
    # Default: serve active (stable) version
    return registry.get_active(prompt_id)

# Example: LaunchDarkly-style flag check
def select_prompt_ld(user_id, ld_client, registry):
    use_new = ld_client.variation(
        'use-summarize-v2', {'key': user_id}, default=False
    )
    version = 'v2.0.0' if use_new else 'v1.1.0'
    return registry.get_version(prompt_id='summarize-article', version=version)

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

После перенаправления трафика на новую версию отслеживайте эти показатели в реальном времени:

  • Доля ошибок: ошибки API, некорректные выходные данные, ошибки разбора
  • Задержка: время отклика P95 (новые промпты могут быть длиннее и медленнее)
  • Оценка качества: автоматическая оценка от оценщика на основе LLM или метрики
  • Сигналы от пользователей: доля отрицательных оценок, доля повторных запросов, уход из сеанса
from collections import defaultdict
import time

class VersionMonitor:
    def __init__(self):
        self.metrics = defaultdict(lambda: {
            'calls': 0, 'errors': 0,
            'latency_sum': 0, 'quality_sum': 0
        })

    def record(self, version, latency_ms, quality_score, error=False):
        m = self.metrics[version]
        m['calls'] += 1
        m['latency_sum'] += latency_ms
        m['quality_sum'] += quality_score
        if error:
            m['errors'] += 1

    def report(self, version):
        m = self.metrics[version]
        n = m['calls'] or 1
        return {
            'version': version,
            'calls': m['calls'],
            'error_rate': round(m['errors'] / n, 3),
            'avg_latency_ms': round(m['latency_sum'] / n),
            'avg_quality': round(m['quality_sum'] / n, 2)
        }

Автоматический откат при ухудшении качества

Ручной откат слишком медленный для инцидентов в рабочей среде. Определите условия отката — пороговые значения, при нарушении которых система автоматически возвращается к предыдущей версии.

ROLLBACK_THRESHOLDS = {
    'error_rate': 0.05,      # > 5% errors trigger rollback
    'avg_latency_ms': 10000, # > 10s avg latency triggers rollback
    'avg_quality': 3.5       # < 3.5 quality score triggers rollback
}

def check_and_rollback(monitor, registry, version, previous_version):
    report = monitor.report(version)
    triggers = []

    if report['error_rate'] > ROLLBACK_THRESHOLDS['error_rate']:
        triggers.append(f'error_rate={report["error_rate"]}')
    if report['avg_latency_ms'] > ROLLBACK_THRESHOLDS['avg_latency_ms']:
        triggers.append(f'latency={report["avg_latency_ms"]}ms')
    if report['avg_quality'] < ROLLBACK_THRESHOLDS['avg_quality']:
        triggers.append(f'quality={report["avg_quality"]}')

    if triggers:
        print(f'ROLLBACK TRIGGERED: {triggers}')
        registry.activate_version('summarize-article', previous_version)
        alert_oncall(f'Prompt auto-rolled back to {previous_version}: {triggers}')
        return True
    return False

Модель канареечного развёртывания

Канареечная группа — это небольшая доля трафика (1–5%), которая первой получает новую версию промпта. Если после периода наблюдения канареечная группа работает стабильно, трафик постепенно переводится на новую версию. Если нет, затронуты будут только пользователи канареечной группы.

import time

def canary_deploy(registry, splitter, monitor, new_version, prev_version,
                  soak_minutes=30, stages=[1, 5, 25, 50, 100]):
    for pct in stages:
        splitter.update_split({
            prev_version: 100 - pct,
            new_version: pct
        })
        print(f'Stage: {pct}% canary. Soaking for {soak_minutes} min...')
        time.sleep(soak_minutes * 60)  # wait soak period

        should_rollback = check_and_rollback(
            monitor, registry, new_version, prev_version
        )
        if should_rollback:
            splitter.update_split({prev_version: 100})
            print('Canary aborted. Fully reverted to', prev_version)
            return False
        print(f'Stage {pct}% passed quality check.')

    print(f'Canary complete. {new_version} now at 100%.')
    return True

Оркестрация конвейера развёртывания

Полный конвейер развёртывания промпта объединяет проверку, запуск канареечной группы, цикл мониторинга и окончательный перевод трафика или откат — всё автоматизировано, с этапами, требующими одобрения человека.

# deploy_prompt.py — full pipeline
import argparse

def deploy(prompt_id, new_version, prev_version, dry_run=False):
    print(f'=== Deploying {prompt_id}: {prev_version} -> {new_version} ===')

    # 1. Validate new version exists in registry
    artifact = registry.get_version(prompt_id, new_version)
    print(f'Found artifact: {artifact["version"]}')

    # 2. Run offline eval suite
    score = run_eval_suite(artifact['template'])
    if score < 0.90:
        raise RuntimeError(f'Eval score {score} below threshold 0.90')
    print(f'Eval passed: {score}')

    if dry_run:
        print('Dry run complete. Not deploying.')
        return

    # 3. Canary deploy with automatic rollback
    success = canary_deploy(
        registry, splitter, monitor,
        new_version, prev_version,
        soak_minutes=15, stages=[1, 5, 25, 100]
    )

    print('Deployment', 'SUCCEEDED' if success else 'FAILED')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--new', required=True)
    parser.add_argument('--prev', required=True)
    parser.add_argument('--dry-run', action='store_true')
    args = parser.parse_args()
    deploy('summarize-article', args.new, args.prev, args.dry_run)

Процедура ручного отката

Если автоматический откат не срабатывает, но человек замечает проблемы с качеством, инструкция по ручному откату обеспечивает быстрые и последовательные действия.

# RUNBOOK: Manual Prompt Rollback
# Estimated time to execute: 2-3 minutes

# Step 1: Identify current and target versions
python manage.py prompt list-versions --prompt-id summarize-article
# Output:
#   v1.2.0  [ACTIVE]  2024-08-15  alice
#   v1.1.0  [stable]  2024-07-01  alice

# Step 2: Activate previous stable version
python manage.py prompt activate --prompt-id summarize-article --version v1.1.0
# Output: Activated summarize-article@v1.1.0

# Step 3: Verify traffic is serving old version
python manage.py prompt verify --prompt-id summarize-article
# Output: Active version: v1.1.0  Serving: 100%

# Step 4: Log the incident
python manage.py incident create \
  --title 'Prompt rollback: summarize-article v1.2.0 -> v1.1.0' \
  --severity P2 \
  --reason 'Quality score dropped from 4.1 to 3.2 after v1.2.0 deploy'

Конфигурация развёртывания как код

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

# deployments/summarize-article.yaml
prompt_id: summarize-article
current_stable: '1.1.0'
canary_config:
  stages: [1, 5, 25, 50, 100]
  soak_minutes_per_stage: 15
rollback_thresholds:
  error_rate_max: 0.05
  latency_p95_max_ms: 8000
  quality_score_min: 3.5
feature_flags:
  beta_group: [user_123, user_456]
alerts:
  pagerduty_key: 'PD_KEY_PLACEHOLDER'
  slack_channel: '#prompt-alerts'

# Load and apply with a deploy script
import yaml

with open('deployments/summarize-article.yaml') as f:
    config = yaml.safe_load(f)

print('Deploying with config:', config['canary_config'])

Инструкции для дежурных и разборы инцидентов

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

# Post-mortem template (stored in docs/post-mortems/)

## Incident: summarize-article v1.2.0 quality regression
## Date: 2024-08-15
## Severity: P2
## Duration: 47 minutes (09:15 - 10:02 UTC)

### What happened
Deployed v1.2.0 of summarize-article. At 5% canary, quality score dropped
from 4.1 to 3.0 for articles over 2000 words.

### Root cause
New prompt template removed the explicit length constraint instruction.
Long articles caused the model to generate overly verbose summaries.

### Timeline
09:15  v1.2.0 deployed to 5% canary
09:28  Quality monitor detected avg_quality < 3.5
09:29  Auto-rollback triggered to v1.1.0
09:32  Incident acknowledged by on-call
10:02  Post-mortem drafted

### Action items
- [ ] Add length regression test to eval suite
- [ ] Update canary monitoring to separate metrics by article length
- [ ] Add changelog requirement: 'length behavior' field

Быстрая проверка

Что происходит при сине-зелёном развертывании промпта, если зелёная среда не проходит проверки качества?

Обзор стратегии развертывания

Развертывание промпта в рабочую среду требует структурированных стратегий управления рисками:

  • Сине-зелёное развертывание: две работающие среды и мгновенное атомарное переключение
  • Канареечное развертывание: поэтапное увеличение трафика 1% → 5% → 25% → 100% с проверками качества на каждом этапе
  • Флаги функций: сначала нацеливание на бета-пользователей, затем широкое развертывание
  • Автоматический откат: возврат к предыдущей версии при достижении порога (частота ошибок, задержка, качество)
  • Операционные инструкции: документированные процедуры ручного отката для дежурных инженеров
  • Постмортемы: непрерывное улучшение после каждого инцидента

Часто задаваемые вопросы

Урок «Стратегии развёртывания и отката» бесплатный?

Да — полный текст урока «Стратегии развёртывания и отката» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Prompt Engineering, подпишись на CoddyKit PRO. Курс AI Prompt Engineering содержит 4 уроков всего.

Чему я научусь в уроке «Стратегии развёртывания и отката»?

Сине-зелёное развёртывание запросов, флаги функций и откат при регрессии. Ты практикуешь AI Prompt Engineering с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать AI Prompt Engineering?

Предыдущий опыт не требуется. AI Prompt Engineering на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Стратегии развёртывания и отката»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке AI Prompt Engineering?

Да. Каждый урок AI Prompt Engineering включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Архитектура реестра запросов
  2. Контроль версий запросов
  3. Стратегии развёртывания и отката
  4. Мониторинг производительности запросов в рабочей среде
← Назад к AI Prompt Engineering