0Pricing
AI Prompt Engineering · Урок

Компиляция и оптимизация запросов

Практическое применение BootstrapFewShot, MIPRO и других оптимизаторов DSPy.

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

Что означает оптимизация в DSPy

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

Вы выполняете компиляцию один раз, сохраняете результат и развёртываете оптимизированную программу. Во время вывода выполняются только быстрые вызовы LLM — дополнительные затраты на оптимизацию отсутствуют.

Определение функции метрики

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

Метрика — это сигнал, по которому оптимизатор определяет, насколько хороша конфигурация промпта.

# Metric: exact match on answer field
def exact_match_metric(example, prediction, trace=None):
    """
    example: a training example with .answer
    prediction: the module's output with .answer
    Returns 1.0 if correct, 0.0 otherwise
    """
    expected = example.answer.strip().lower()
    predicted = prediction.answer.strip().lower()
    return float(expected == predicted)

# Metric: F1 score for token overlap (common in QA)
def token_f1_metric(example, prediction, trace=None):
    gold_tokens = set(example.answer.lower().split())
    pred_tokens = set(prediction.answer.lower().split())
    if not pred_tokens:
        return 0.0
    precision = len(gold_tokens & pred_tokens) / len(pred_tokens)
    recall = len(gold_tokens & pred_tokens) / len(gold_tokens)
    if precision + recall == 0:
        return 0.0
    return 2 * precision * recall / (precision + recall)

Подготовка обучающей выборки

DSPy требуется обучающая выборка из объектов dspy.Example. Каждый пример задаёт входные данные и ожидаемый результат. Для BootstrapFewShot часто достаточно даже 20–50 примеров.

import dspy

# Build training examples
trainset = [
    dspy.Example(
        question='What is the capital of Germany?',
        answer='Berlin'
    ).with_inputs('question'),

    dspy.Example(
        question='Who wrote Romeo and Juliet?',
        answer='William Shakespeare'
    ).with_inputs('question'),

    dspy.Example(
        question='What year did World War II end?',
        answer='1945'
    ).with_inputs('question'),
    # ... add more examples
]

print(f'Training set size: {len(trainset)} examples')
print(trainset[0].question, '->', trainset[0].answer)

Оптимизатор BootstrapFewShot

BootstrapFewShot — самый распространённый оптимизатор DSPy. Он запускает вашу программу на обучающей выборке, собирает успешные трассировки (пары ввода и вывода, для которых метрика пройдена) и использует эти трассировки как демонстрации с малым числом образцов в скомпилированном промпте.

import dspy
from dspy.teleprompt import BootstrapFewShot

# Define your program
class QA(dspy.Signature):
    """Answer factual questions."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

program = dspy.ChainOfThought(QA)

# Set up the optimizer
optimizer = BootstrapFewShot(
    metric=exact_match_metric,
    max_bootstrapped_demos=4,   # Up to 4 few-shot examples per predictor
    max_labeled_demos=4,        # Use labeled examples directly if available
)

# Compile!
compiled_program = optimizer.compile(program, trainset=trainset)
print('Compilation complete')

Оптимизатор MIPRO

MIPRO (предложение и оптимизация инструкций для нескольких промптов) — более мощный оптимизатор. Он не только выбирает примеры с малым числом образцов, но и ищет более удачный текст инструкций для включения в промпт.

Во время компиляции MIPRO требует больше вызовов LLM, но часто обеспечивает значительно более высокую точность.

import dspy
from dspy.teleprompt import MIPROv2

class QA(dspy.Signature):
    """Answer factual questions."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

program = dspy.ChainOfThought(QA)

# MIPRO: optimizes both instructions AND few-shot examples
optimizer = MIPROv2(
    metric=exact_match_metric,
    auto='medium',      # 'light' / 'medium' / 'heavy' for optimization budget
    num_threads=4,      # Parallel evaluation threads
)

compiled_program = optimizer.compile(
    program,
    trainset=trainset,
    num_trials=20,       # Number of candidate prompts to evaluate
)
print('MIPRO compilation complete')

Как выглядит скомпилированный промпт

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

import dspy

# After compiling, inspect the optimized state
compiled_program = dspy.ChainOfThought('question -> answer')
# (Assume this was returned by optimizer.compile(...))

# Inspect the demos that were found
for demo in compiled_program.demos:
    print('Input:', demo.question)
    print('Reasoning:', demo.get('reasoning', 'N/A'))
    print('Answer:', demo.answer)
    print('---')

# Save the compiled state
compiled_program.save('compiled_qa_program.json')
print('Saved compiled program')

Интерфейс teleprompter.compile()

Все оптимизаторы DSPy используют один и тот же интерфейс compile(). Благодаря такой согласованности вы можете менять оптимизаторы, не изменяя код программы.

from dspy.teleprompt import BootstrapFewShot, MIPROv2, COPRO

# All optimizers use the same interface:
# compiled = optimizer.compile(program, trainset=trainset)

# BootstrapFewShot: fast, uses successful traces as demos
opt1 = BootstrapFewShot(metric=exact_match_metric)

# MIPRO: slower, optimizes instructions too
opt2 = MIPROv2(metric=exact_match_metric, auto='light')

# COPRO: coordinate descent over instruction proposals
opt3 = COPRO(metric=exact_match_metric, depth=3)

# Swap between them with one line change:
compiled = opt1.compile(program, trainset=trainset)
# or: compiled = opt2.compile(program, trainset=trainset)

BootstrapFewShotWithRandomSearch

BootstrapFewShotWithRandomSearch расширяет BootstrapFewShot: он создаёт множество наборов демонстраций-кандидатов и выбирает тот, который лучше всего работает на проверочной выборке.

Это удачный компромисс между простотой BootstrapFewShot и возможностями MIPRO.

from dspy.teleprompt import BootstrapFewShotWithRandomSearch

# Split data into train and validation
trainset = examples[:40]
devset = examples[40:60]

optimizer = BootstrapFewShotWithRandomSearch(
    metric=exact_match_metric,
    max_bootstrapped_demos=4,
    num_candidate_programs=8,  # Try 8 different demo sets
    num_threads=4,
)

compiled_program = optimizer.compile(
    program,
    trainset=trainset,
    valset=devset,  # Picks the best program based on validation
)
print('Best program selected from 8 candidates')

Затраты на компиляцию

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

  • BootstrapFewShot: примерно 1–2-кратный размер обучающей выборки по числу вызовов LLM
  • RandomSearch с 8 кандидатами: примерно 8–10-кратное число вызовов
  • MIPRO в среднем режиме: примерно 30–50-кратное число вызовов

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

Проверка скомпилированной программы

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

import dspy

# Evaluate on test set
evaluate = dspy.Evaluate(
    devset=testset,
    metric=exact_match_metric,
    num_threads=4,
    display_progress=True,
)

# Compare uncompiled vs compiled
uncompiled_score = evaluate(uncompiled_program)
compiled_score = evaluate(compiled_program)

print(f'Uncompiled accuracy: {uncompiled_score:.1%}')
print(f'Compiled accuracy:   {compiled_score:.1%}')
print(f'Improvement: +{compiled_score - uncompiled_score:.1%}')

Объединение всех элементов

Полный рабочий процесс оптимизации DSPy: определить сигнатуру → создать модуль → подготовить обучающие данные → выбрать оптимизатор → выполнить компиляцию → оценить результат → сохранить. Это полный цикл от идеи до готового к использованию в рабочей среде оптимизированного конвейера промптов.

import dspy
from dspy.teleprompt import BootstrapFewShot

# 1. Configure LM
dspy.configure(lm=dspy.LM('openai/gpt-4o-mini', api_key='sk-...'))

# 2. Define signature and module
class QA(dspy.Signature):
    """Answer questions accurately."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

program = dspy.ChainOfThought(QA)

# 3. Compile
optimizer = BootstrapFewShot(metric=exact_match_metric)
compiled = optimizer.compile(program, trainset=trainset)

# 4. Save
compiled.save('production_qa.json')
print('Production program ready')

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

Что BootstrapFewShot использует из вашей обучающей выборки для улучшения скомпилированного промпта?

Повторение: компиляция и оптимизация

Оптимизация DSPy ищет лучшую конфигурацию промпта, используя функцию метрики и обучающую выборку. BootstrapFewShot находит удачные демонстрации с малым числом образцов по успешным трассировкам. MIPROv2 дополнительно ищет более удачный текст инструкций. Все оптимизаторы используют общий интерфейс compile(program, trainset=...). Компиляция выполняется один раз вне рабочей среды — сохраните результат с помощью program.save() и развёртывайте оптимизированную программу, не неся дополнительных затрат во время вывода.

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

Урок «Компиляция и оптимизация запросов» бесплатный?

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

Чему я научусь в уроке «Компиляция и оптимизация запросов»?

Практическое применение BootstrapFewShot, MIPRO и других оптимизаторов DSPy. Ты практикуешь 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. Введение в фреймворк DSPy
  2. Определение сигнатур и модулей
  3. Компиляция и оптимизация запросов
  4. Оценка конвейеров DSPy
← Назад к AI Prompt Engineering