0Pricing
AI Prompt Engineering · Урок

Системный подход к отладке

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

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

Подход к отладке

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

Шаг 1: воспроизведите сбой

Перед отладкой надёжно воспроизведите сбой. Сбой, который нельзя стабильно воспроизвести, невозможно систематически отлаживать.

Запустите запрос 5 раз на одних и тех же входных данных. Если он даёт сбой каждый раз: детерминированный сбой — его легко отлаживать. Если сбой происходит иногда: вероятностный сбой — сначала установите temperature=0, чтобы устранить случайность, затем повторите проверку.

import openai
client = openai.OpenAI(api_key='sk-...')

def run_prompt(prompt, user_input, temperature=0):
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[
            {'role': 'system', 'content': prompt},
            {'role': 'user', 'content': user_input}
        ],
        temperature=temperature
    )
    return resp.choices[0].message.content

# Reproduce with temperature=0 to eliminate randomness
for i in range(5):
    output = run_prompt(failing_prompt, test_input, temperature=0)
    print(f'Run {i+1}:', output[:100])

Шаг 2: создайте минимальный воспроизводимый запрос

Минимальный воспроизводимый запрос (MRP) — это самый короткий запрос, который всё ещё вызывает сбой. Удаление не относящихся к делу частей изолирует проблемный раздел и делает сбой очевидным.

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

def binary_search_prompt(prompt_lines, user_input, fail_fn):
    '''Binary search: find the minimal set of lines that causes the failure.'''
    if len(prompt_lines) == 1:
        return prompt_lines  # Minimal failing unit found

    mid = len(prompt_lines) // 2
    first_half = prompt_lines[:mid]
    second_half = prompt_lines[mid:]

    # Test first half
    if fail_fn('\n'.join(first_half), user_input):
        return binary_search_prompt(first_half, user_input, fail_fn)
    # Test second half
    elif fail_fn('\n'.join(second_half), user_input):
        return binary_search_prompt(second_half, user_input, fail_fn)
    else:
        # Both halves pass — interaction effect between halves
        return prompt_lines

Проверка удалением

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

sections = {
    'role_instruction': 'You are a precise JSON API. Respond only with valid JSON.',
    'context': 'The user is asking about our product catalog.',
    'format_spec': 'Return a JSON object with keys: name, price, available.',
    'examples': 'Example: {"name": "Widget", "price": 9.99, "available": true}',
    'safety': 'Do not reveal internal pricing strategy.'
}

def test_without(section_to_remove, user_input):
    reduced = {k: v for k, v in sections.items() if k != section_to_remove}
    prompt = '\n'.join(reduced.values())
    output = run_prompt(prompt, user_input)
    print(f'Without {section_to_remove}: {evaluate(output)}')

for section in sections:
    test_without(section, 'What is the price of a Widget?')

A/B-сравнение разделов запросов

A/B-сравнение запросов означает создание двух версий одного раздела и сравнение их выходных данных на одних и тех же входных данных. В отличие от проверок удалением, A/B-сравнения оценивают альтернативные формулировки, а не наличие или отсутствие раздела.

# A/B test: vague vs precise format instruction
variant_A = 'Return a JSON object.'
variant_B = 'Return a valid JSON object. No markdown, no code fences, no prose. Only the raw JSON.'

test_inputs = [
    'What is the price of Widget A?',
    'List all available products.',
    'Is Widget B in stock?'
]

def run_ab_test(base_prompt, variant, inputs, n_runs=5):
    pass_count = 0
    for inp in inputs:
        for _ in range(n_runs):
            prompt = base_prompt.replace('{{FORMAT}}', variant)
            output = run_prompt(prompt, inp)
            if is_valid_json(output):
                pass_count += 1
    return pass_count / (len(inputs) * n_runs)

print('A pass rate:', run_ab_test(template, variant_A, test_inputs))
print('B pass rate:', run_ab_test(template, variant_B, test_inputs))

Сравнительная проверка

Сравнительная проверка сопоставляет два почти идентичных запроса, чтобы определить, какое изменение вызвало регрессию. Это полезно, когда «на прошлой неделе всё работало», а теперь — нет.

Сопоставьте старую версию запроса с новой, определите изменённые разделы, а затем проверьте каждый изменённый раздел отдельно.

import difflib

def show_prompt_diff(prompt_v1, prompt_v2):
    diff = difflib.unified_diff(
        prompt_v1.splitlines(),
        prompt_v2.splitlines(),
        fromfile='v1',
        tofile='v2',
        lineterm=''
    )
    for line in diff:
        print(line)

show_prompt_diff(working_prompt, failing_prompt)
# Output shows exactly which lines changed between versions
# Test reverting each changed section individually

Проверка входных данных и запросов

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

# Input complexity ladder
inputs_by_complexity = [
    'What is 2 + 2?',             # trivially simple
    'Summarize this sentence.',    # simple task
    'Analyze this 500-word essay.',  # moderate
    'Compare 10 documents and extract contradictions.'  # complex
]

# Find the complexity level where the prompt starts failing
for inp in inputs_by_complexity:
    output = run_prompt(failing_prompt, inp)
    result = 'PASS' if evaluate(output) else 'FAIL'
    print(f'{result}: {inp[:60]}')
# First FAIL indicates where the prompt breaks down

Шаблон минимального воспроизводимого запроса

MRP для сеанса отладки запроса имеет следующую структуру:

  1. Одно предложение с описанием роли (если необходимо)
  2. Одно предложение с инструкцией по задаче
  3. Инструкция по формату
  4. Минимальные входные данные, воспроизводящие сбой

Если этот четырёхстрочный запрос по-прежнему даёт сбой, проблема заключается в модели или формате. Возвращайте сложность по одному разделу за раз, пока сбой не появится снова — этот раздел и является причиной.

# Start minimal
MINIMAL_PROMPT = (
    'You are a data extractor.\n'
    'Extract the product name and price from the text.\n'
    'Respond with JSON: {"name": "...", "price": ...}\n'
)

minimal_input = 'Widget Pro costs $49.'

# Test: if this works, the problem is in something added on top
output = run_prompt(MINIMAL_PROMPT, minimal_input)
print(output)
# Expected: {"name": "Widget Pro", "price": 49.0}

Отслеживание сеанса отладки

Документируйте каждую проверку во время сеанса отладки. Без записей можно повторить одни и те же проверки или забыть, какие гипотезы были исключены.

debug_log = [
    {
        'test': 'base_prompt_v5',
        'hypothesis': 'failing due to format conflict',
        'result': 'FAIL',
        'notes': 'JSON prefix still present'
    },
    {
        'test': 'base_prompt_v5_no_markdown_hint',
        'hypothesis': 'removing markdown hint from user message fixes conflict',
        'result': 'PASS',
        'notes': 'Output is clean JSON. Root cause confirmed: format conflict.'
    }
]

import json
with open('debug_session.json', 'w') as f:
    json.dump(debug_log, f, indent=2)

Когда следует прекратить отладку и сменить стратегию

Иногда отладка запроса приносит всё меньше пользы. Признаки того, что пора сменить стратегию:

  • Вы потратили более 2 часов, пытаясь локализовать один и тот же сбой
  • Минимальный запрос по-прежнему даёт сбой при ясной и простой инструкции
  • A/B-сравнения не показывают статистически значимой разницы

Альтернативы: перейти к вызову функций (структурированные выходные данные), добавить этап проверки выходных данных после обработки, разложить задачу на два более простых запроса или обновить модель.

Исправление и повышение устойчивости

После обнаружения и устранения первопричины сделайте запрос устойчивее, чтобы предотвратить похожие сбои:

  • Добавьте случай, вызвавший сбой, в набор проверок как регрессионную проверку
  • Добавьте защитную инструкцию: «Даже если входные данные необычны, всегда возвращайте JSON»
  • Добавьте проверку выходных данных, чтобы сбой обнаруживался программно, а не в рабочей среде

Исправленный, но не сделанный устойчивым запрос снова даст сбой на следующем нестандартном случае.

def safe_run_prompt(prompt, user_input):
    output = run_prompt(prompt, user_input)
    try:
        parsed = json.loads(output)
        return parsed
    except json.JSONDecodeError:
        # Fallback: ask the model to fix its own output
        fix_prompt = f'The following is not valid JSON. Rewrite it as valid JSON only:\n{output}'
        fixed = run_prompt('', fix_prompt)
        return json.loads(fixed)

Проверка знаний

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

Повторение: систематическая отладка

Систематический подход к отладке запросов:

  • Воспроизведите: установите температуру на 0, запустите 5 раз и подтвердите, что сбой происходит стабильно
  • Минимизируйте: применяйте двоичный поиск по разделам запроса, чтобы найти минимальный запрос, вызывающий сбой
  • Проведите A/B-сравнение: сравните альтернативные формулировки проблемного раздела
  • Сопоставьте: сравните рабочую и нерабочую версии запроса, чтобы найти регрессию
  • Документируйте: заносите в журнал каждую проверку, гипотезу и результат
  • Сделайте устойчивее: добавьте исправленный случай в набор проверок

Следующий урок: стратегии журналирования и документирования для долгосрочного сопровождения запросов.

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

Урок «Системный подход к отладке» бесплатный?

Да — полный текст урока «Системный подход к отладке» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 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