0Pricing
AI Prompt Engineering · Lekcja

Kompilowanie i optymalizowanie promptów

Praktyczne zastosowanie BootstrapFewShot, MIPRO i innych optymalizatorów DSPy.

Kompilowanie i optymalizowanie promptów to bezpłatna lekcja AI Prompt Engineering na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Prompt Engineering, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Prompt Engineering zawiera 4 lekcji w sumie.

Znaczenie optymalizacji w DSPy

Optymalizacja DSPy (nazywana kompilacją) znajduje najlepszą konfigurację promptu dla programu na podstawie zbioru treningowego i metryki. Optymalizator przeszukuje możliwe przykłady few-shot, instrukcje i demonstracje rozumowania.

Kompilację uruchamiają Państwo raz, zapisują jej wynik i wdrażają zoptymalizowany program. Podczas inferencji są to po prostu szybkie wywołania LLM — bez dodatkowego narzutu optymalizacji.

Definiowanie funkcji metryki

Każdy optymalizator DSPy potrzebuje funkcji metryki, która ocenia predykcję na podstawie oczekiwanego wyjścia. Zwraca ona liczbę lub wartość logiczną — wyższy wynik jest lepszy.

Metryka jest sygnałem używanym przez optymalizator do oceny, czy konfiguracja promptu jest dobra.

# 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)

Przygotowywanie zbioru treningowego

DSPy potrzebuje zbioru treningowego obiektów dspy.Example. Każdy przykład określa wejścia i oczekiwane wyjście. Nawet 20–50 przykładów często wystarcza w przypadku BootstrapFewShot.

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)

Optymalizator BootstrapFewShot

BootstrapFewShot to najczęściej używany optymalizator DSPy. Uruchamia program na zbiorze treningowym, zbiera pomyślne ślady (pary wejście–wyjście, dla których metryka została spełniona), a następnie wykorzystuje te ślady jako demonstracje few-shot w skompilowanym prompcie.

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')

Optymalizator MIPRO

MIPRO (Multi-prompt Instruction Proposal and Optimization) to bardziej zaawansowany optymalizator. Nie tylko wybiera przykłady few-shot, lecz także wyszukuje lepszy tekst instrukcji do umieszczenia w prompcie.

MIPRO wymaga większej liczby wywołań LLM podczas kompilacji, ale często zapewnia znacznie wyższą dokładność.

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')

Jak wygląda skompilowany prompt

Po kompilacji DSPy osadza w prompcie zoptymalizowane demonstracje few-shot. Można to sprawdzić, analizując predyktory skompilowanego programu.

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')

Interfejs teleprompter.compile()

Wszystkie optymalizatory DSPy korzystają z tego samego interfejsu compile(). Dzięki tej spójności mogą Państwo zmieniać optymalizatory bez modyfikowania kodu programu.

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 rozszerza BootstrapFewShot, generując wiele zestawów demonstracji i wybierając ten, który osiąga najlepsze wyniki na zbiorze walidacyjnym.

To dobry kompromis między prostotą BootstrapFewShot a możliwościami 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')

Kwestie kosztu kompilacji

Kompilacja wykonuje dodatkowe wywołania LLM w celu generowania i oceniania kandydujących promptów. Należy odpowiednio zaplanować budżet:

  • BootstrapFewShot: około 1–2 razy więcej wywołań LLM niż przykładów w zbiorze treningowym
  • RandomSearch z 8 kandydatami: około 8–10 razy więcej
  • MIPRO medium: około 30–50 razy więcej

Kompilację należy uruchamiać offline, zapisać jej wynik i wdrożyć zapisany program. Koszt inferencji w środowisku produkcyjnym pozostaje bez zmian.

Weryfikowanie skompilowanego programu

Po kompilacji należy zawsze przeprowadzić ewaluację na odłożonym zbiorze testowym, aby potwierdzić, że zoptymalizowany program rzeczywiście uogólnia wyniki. Nie należy sprawdzać wyłącznie wydajności na zbiorze treningowym.

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%}')

Połączenie wszystkich elementów

Kompletny proces optymalizacji w DSPy wygląda następująco: zdefiniowanie sygnatury → utworzenie modułu → przygotowanie danych treningowych → wybór optymalizatora → kompilacja → ewaluacja → zapis. To pełny cykl — od pomysłu do gotowego do produkcyjnego użycia, zoptymalizowanego potoku promptów.

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')

Sprawdzenie wiedzy: BootstrapFewShot

Czego używa BootstrapFewShot ze zbioru treningowego, aby ulepszyć skompilowany prompt?

Podsumowanie: kompilowanie i optymalizacja

Optymalizacja DSPy wyszukuje najlepszą konfigurację promptu przy użyciu funkcji metryki i zbioru treningowego. BootstrapFewShot znajduje dobre demonstracje few-shot na podstawie pomyślnych śladów. MIPROv2 dodatkowo wyszukuje lepszy tekst instrukcji. Wszystkie optymalizatory korzystają z interfejsu compile(program, trainset=...). Kompilacja jest jednorazowym kosztem ponoszonym offline — wynik należy zapisać za pomocą program.save(), a następnie wdrożyć zoptymalizowany program, aby podczas inferencji nie ponosić dodatkowych kosztów optymalizacji.

Często zadawane pytania

Czy lekcja „Kompilowanie i optymalizowanie promptów” jest bezpłatna?

Tak — pełny tekst „Kompilowanie i optymalizowanie promptów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Prompt Engineering, przejdź na CoddyKit PRO. Kurs AI Prompt Engineering zawiera 4 lekcji w sumie.

Co nauczysz się w „Kompilowanie i optymalizowanie promptów”?

Praktyczne zastosowanie BootstrapFewShot, MIPRO i innych optymalizatorów DSPy. Ćwiczysz AI Prompt Engineering z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć AI Prompt Engineering?

Nie wymagamy żadnego doświadczenia. AI Prompt Engineering w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Kompilowanie i optymalizowanie promptów”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji AI Prompt Engineering?

Tak. Każda lekcja AI Prompt Engineering zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wprowadzenie do frameworka DSPy
  2. Definiowanie sygnatur i modułów
  3. Kompilowanie i optymalizowanie promptów
  4. Ewaluacja potoków DSPy
← Powrót do AI Prompt Engineering