AI Prompt Engineering · Урок

Оценка конвейеров DSPy

Метрики, наборы для разработки и функция evaluate() для автоматической оценки.

Урок 4 из 413 шагов

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

Почему важна оценка в DSPy

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

Класс dspy.Evaluate

dspy.Evaluate запускает вашу программу на наборе данных, применяет метрику и сообщает сводные оценки. Для быстрой оценки больших наборов данных поддерживается параллельное выполнение с помощью num_threads.

import dspy

# Build a devset of labeled examples
devset = [
    dspy.Example(question='What is 7 * 8?', answer='56').with_inputs('question'),
    dspy.Example(question='Name the largest planet.', answer='Jupiter').with_inputs('question'),
    # ... more examples
]

# Create evaluator
evaluate = dspy.Evaluate(
    devset=devset,
    metric=exact_match_metric,  # Your metric function
    num_threads=4,              # Parallel evaluation
    display_progress=True,      # Show progress bar
    display_table=True,         # Show per-example results
)

# Run
score = evaluate(my_program)
print(f'Overall score: {score:.1%}')

Написание функций метрик

Функции метрик имеют сигнатуру (example, prediction, trace=None) -> float. Они сравнивают прогноз программы с эталонным ответом в примере.

Параметр trace имеет значение, отличное от None, во время оптимизации, но не во время оценки — его можно использовать для применения разной логики при компиляции и оценке.

import dspy

def exact_match_metric(example, prediction, trace=None):
    return float(
        example.answer.strip().lower() == prediction.answer.strip().lower()
    )

def contains_metric(example, prediction, trace=None):
    """Check if expected answer appears anywhere in prediction."""
    return float(example.answer.lower() in prediction.answer.lower())

def length_penalized_metric(example, prediction, trace=None):
    """Reward correct answers, penalize overly long ones."""
    correct = float(example.answer.lower() in prediction.answer.lower())
    length_ok = float(len(prediction.answer.split()) <= 20)
    return correct * (0.8 + 0.2 * length_ok)

# Use any of these as the metric parameter
evaluate = dspy.Evaluate(devset=devset, metric=contains_metric)

Шаблоны с порогом прохождения

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

import dspy

def quality_metric(example, prediction, trace=None):
    """
    Multi-factor metric with pass/fail threshold.
    Returns float 0.0 to 1.0.
    During compilation (trace is not None), DSPy uses this to decide
    which traces to bootstrap as demos.
    """
    score = 0.0

    # Factor 1: Factual correctness (0.6 weight)
    if example.answer.lower() in prediction.answer.lower():
        score += 0.6

    # Factor 2: Conciseness (0.4 weight)
    word_count = len(prediction.answer.split())
    if word_count <= 15:
        score += 0.4
    elif word_count <= 30:
        score += 0.2

    # During optimization: only use examples scoring >= 0.6
    if trace is not None:
        return score >= 0.6

    return score

Разделение данных: обучение, разработка, тестирование

Следуйте стандартным правилам разделения данных машинного обучения в DSPy:

  • Обучающий набор: используется оптимизатором для начального создания демонстрационных примеров (20–200 примеров)
  • Набор разработки: используется оптимизатором для проверки во время поиска
  • Тестовый набор: полностью отложен и используется только для итоговой оценки
import random

# All labeled examples
all_examples = load_examples()  # Returns list of dspy.Example
random.shuffle(all_examples)

total = len(all_examples)
train_end = int(total * 0.6)
dev_end   = int(total * 0.8)

trainset = all_examples[:train_end]    # 60% for optimization
devset   = all_examples[train_end:dev_end]  # 20% for validation
testset  = all_examples[dev_end:]      # 20% held out

print(f'Train: {len(trainset)}, Dev: {len(devset)}, Test: {len(testset)}')

Сравнение оптимизированной и неоптимизированной программ

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

import dspy

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

# Baseline: unoptimized program
baseline_score = evaluate(unoptimized_program)
print(f'Baseline (no optimization): {baseline_score:.1%}')

# BootstrapFewShot compiled
bs_score = evaluate(bootstrap_compiled_program)
print(f'BootstrapFewShot compiled:  {bs_score:.1%}')

# MIPRO compiled
mipro_score = evaluate(mipro_compiled_program)
print(f'MIPRO compiled:             {mipro_score:.1%}')

# Pick the winner
print(f'Best improvement: +{max(bs_score, mipro_score) - baseline_score:.1%}')

Параллельное выполнение с num_threads

Оценка больших наборов данных при последовательном выполнении могла бы занять несколько часов. Параметр num_threads в dspy.Evaluate запускает прогнозирование параллельно, пропорционально сокращая фактическое время выполнения.

Согласуйте значение num_threads с ограничениями частоты запросов вашего программного интерфейса — слишком большое число потоков вызывает ошибки ограничения частоты запросов.

import dspy
import time

devset = [...]  # 200 examples

# Sequential evaluation
start = time.time()
evaluate_seq = dspy.Evaluate(devset=devset, metric=metric, num_threads=1)
score_seq = evaluate_seq(program)
print(f'Sequential: {time.time()-start:.0f}s')

# Parallel evaluation (4 threads)
start = time.time()
evaluate_par = dspy.Evaluate(devset=devset, metric=metric, num_threads=4)
score_par = evaluate_par(program)
print(f'Parallel (4 threads): {time.time()-start:.0f}s')
# Typically ~4x faster — same score, less wait time

Интерпретация результатов оценки

Если установлено значение display_table=True, DSPy показывает подробную таблицу с каждым примером, прогнозом и указанием, прошёл ли он проверку метрикой. Это незаменимо для диагностики закономерностей сбоев.

Ищите систематические сбои для определённого типа вопросов, пограничные случаи метрики и примеры, которые не представлены в вашем обучающем наборе.

import dspy

evaluate = dspy.Evaluate(
    devset=devset,
    metric=exact_match_metric,
    num_threads=2,
    display_progress=True,
    display_table=10,  # Show first 10 rows of results table
    return_outputs=True,  # Return (score, outputs) tuple
)

score, outputs = evaluate(program, return_all_scores=True)

# Find failing examples
failures = [
    (ex, pred, s)
    for ex, pred, s in outputs
    if s == 0.0
]
print(f'Failures: {len(failures)}/{len(devset)}')
for ex, pred, _ in failures[:3]:
    print(f'Q: {ex.question}')
    print(f'Expected: {ex.answer}')
    print(f'Got: {pred.answer}')

Использование метрик, оцениваемых LLM

Для открытых ответов, при оценке которых точное совпадение не работает, используйте LLM для оценки качества. DSPy упрощает эту задачу: ваша функция метрики сама может вызывать предиктор DSPy.

import dspy

class GradeAnswer(dspy.Signature):
    """Grade whether the predicted answer is correct given the reference."""
    question: str = dspy.InputField()
    reference_answer: str = dspy.InputField()
    predicted_answer: str = dspy.InputField()
    is_correct: bool = dspy.OutputField(
        desc='True if the predicted answer is semantically correct'
    )

grader = dspy.Predict(GradeAnswer)

def llm_graded_metric(example, prediction, trace=None):
    result = grader(
        question=example.question,
        reference_answer=example.answer,
        predicted_answer=prediction.answer,
    )
    return float(result.is_correct)

# Use this metric when answers can vary in phrasing
evaluate = dspy.Evaluate(devset=devset, metric=llm_graded_metric)

Регрессионное тестирование с помощью оценки

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

import json
import dspy

def run_and_save_evaluation(program, program_name, testset, metric):
    evaluate = dspy.Evaluate(
        devset=testset,
        metric=metric,
        num_threads=4,
    )
    score = evaluate(program)

    # Save score to history file
    history_file = 'eval_history.json'
    try:
        with open(history_file) as f:
            history = json.load(f)
    except FileNotFoundError:
        history = []

    history.append({'program': program_name, 'score': score})
    with open(history_file, 'w') as f:
        json.dump(history, f, indent=2)

    print(f'{program_name}: {score:.1%}')
    return score

Рекомендации по оценке

Основные принципы оценки конвейеров DSPy:

  • Строго отделяйте тестовый набор — никогда не оптимизируйте на нём
  • Используйте не менее 50–100 тестовых примеров для получения надёжных оценок
  • Согласуйте метрику с вашей реальной целью в рабочей среде
  • Сравнивайте несколько оптимизаторов — результаты зависят от задачи
  • Отслеживайте оценки во времени, чтобы обнаруживать регрессии
  • Вручную изучайте сбои, чтобы улучшать обучающие данные

Проверка знаний: параметр trace функции метрики

Что означает параметр trace со значением, отличным от None, в функции метрики DSPy?

Итоги: оценка конвейеров DSPy

dspy.Evaluate запускает вашу программу на размеченном наборе разработки, применяет функцию метрики и сообщает сводные оценки. Функции метрик следуют шаблону (example, prediction, trace=None) -> float. Используйте num_threads для параллельной оценки, а display_table=True — для диагностики сбоев. Всегда сравнивайте оптимизированные и неоптимизированные программы на отложенном тестовом наборе. Для открытых ответов метрики, оцениваемые LLM, превосходят сопоставление точных строк.

Можно начать бесплатно

Изучай AI Prompt Engineering с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
53
Уроки
199

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

Урок «Оценка конвейеров DSPy» бесплатный?

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

Чему я научусь в уроке «Оценка конвейеров DSPy»?

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

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

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

Сколько времени занимает урок «Оценка конвейеров DSPy»?

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

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

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

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

  1. Введение в фреймворк DSPy
  2. Определение сигнатур и модулей
  3. Компиляция и оптимизация запросов
  4. Оценка конвейеров DSPy
← Назад к AI Prompt Engineering