DSPy: как автоматически оптимизировать промпты и LLM-программы вместо ручного prompt engineering
Большинство LLM-проектов долго живёт в режиме «поменяем ещё пару строк в system prompt и посмотрим». DSPy предлагает другой подход: описать задачу как программу, задать примеры и функцию качества, а instructions и few-shot demonstrations подбирать алгоритмически. Это особенно интересно там, где prompt уже стал частью production-логики и его нужно улучшать воспроизводимо, а не «на глаз».
DSPy отделяет «что должна сделать модель» от конкретного текста prompt
В обычном prompt engineering developer вручную редактирует instructions, добавляет examples, меняет порядок полей и снова тестирует. В DSPy задача сначала выражается через Signature и Module, а prompt становится параметром программы, который можно оптимизировать по данным.
Вы описываете входы и выходы, а не пишете длинную окончательную формулировку prompt вручную.
Optimizer пытается улучшить именно измеряемое качество, а не «сделать prompt красивее».
Инструкции и few-shot demonstrations подбираются из training/evaluation loop.
DSPy работает поверх разных providers и локальных OpenAI-compatible backends.
DSPy не заменяет ни fine-tuning, ни agent framework
Установка
python -m venv .venv
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
pip install dspy==3.3.1
Пакет dspy-ai сейчас оставлен как compatibility alias.
Для нового проекта официально устанавливается именно dspy.
Основная версия для статьи и production-экспериментов.
Опубликована 11 сентября 2026 года, но PyPI прямо помечает её как pre-release.
В 3.4 уже меняется LM-интерфейс и добавляются новые ReActV2/MCP возможности. Для обычного проекта разумнее сначала использовать stable 3.3.1.
Вместо длинного prompt — короткая signature
import dspy
lm = dspy.LM("openai/gpt-4o-mini")
dspy.configure(lm=lm)
qa = dspy.ChainOfThought(
"question -> answer"
)
result = qa(
question="Почему автомат может отключаться при коротком замыкании?"
)
print(result.answer)
Здесь "question -> answer" — compact signature.
DSPy сам формирует interaction с LM через adapter.
Но пока это ещё не «самообучение»: мы просто описали программу.
Без evaluation optimizer не знает, что именно означает «лучше».
Сложную задачу лучше описывать typed-классом, а не строкой
import dspy
class ClassifyTicket(dspy.Signature):
"""Classify a support request."""
message: str = dspy.InputField()
category: str = dspy.OutputField(
desc="One of: network, power, camera, other"
)
urgency: int = dspy.OutputField(
desc="Integer from 1 to 5"
)
classifier = dspy.Predict(ClassifyTicket)
Signature задаёт контракт между Python program и LM: какие поля входят, какие должны выйти и что они означают. Конкретная prompt-formulation остаётся внутренней частью adapter/optimizer.
Текст, история, image и другие supported field types.
Можно задавать descriptions и typed structured values.
Короткое описание вместо огромной system-инструкции.
Signature отвечает «что», Module — «как выполнять LM-step»
dspy.Predict
Прямое предсказание
Самый простой module вокруг signature.
dspy.ChainOfThought
Добавляет reasoning field
Подходит для задач, где модели полезен промежуточный reasoning step.
dspy.ReAct
Reason + Act + tools
Agent loop для задач с функциями/инструментами.
dspy.RLM
Новый code/reasoning-oriented path
В 3.3.1 разработчики рекомендуют его вместо deprecated CodeAct/ProgramOfThought для нового кода.
CodeAct и ProgramOfThought уже deprecated в 3.3.1.
Release notes указывают их планируемое удаление в DSPy 3.5. Новую архитектуру лучше на них не строить.
Metric определяет, чему DSPy на самом деле будет учиться
def metric(example, prediction, trace=None):
expected = example.category.strip().lower()
actual = prediction.category.strip().lower()
return 1.0 if expected == actual else 0.0
Если metric считает только exact match, optimizer будет искать prompts, которые повышают exact match. Если нужен более сложный критерий — например, правильность ответа плюс обязательная ссылка на источник — metric должна проверять именно это.
Подходит для категорий, enum и коротких structured outputs.
Правильность + формат + наличие обязательных полей.
Гибче, но дороже и сам может ошибаться.
GEPA использует feedback, чтобы понимать причину провала кандидата.
DSPy очень хорошо может улучшить именно тот показатель, который вы задали, даже если он плохо отражает реальную полезность продукта.
Какой optimizer выбрать для первого эксперимента
Автоматически собирает demonstrations, которые проходят metric.
Ищет более удачные combinations few-shot examples.
Предлагает instructions и few-shot examples, затем ищет комбинацию через Bayesian Optimization.
Использует execution feedback и reflection LM для эволюции instructions.
Текущая официальная документация предлагает начинать примерно так:
при очень малом наборе примеров — BootstrapFewShot;
при большем наборе — random-search вариант;
для более дорогой instruction optimization — MIPROv2 или GEPA.
Чем больше candidates, trials и evaluation examples, тем выше стоимость облачного provider или время локального inference.
DSPy может одновременно искать инструкцию и few-shot demonstrations
import dspy
optimizer = dspy.MIPROv2(
metric=metric,
auto="light",
)
optimized = optimizer.compile(
classifier,
trainset=trainset,
)
optimized.save(
"classifier_optimized.json"
)
MIPROv2 сначала генерирует candidate demonstrations и instructions,
затем использует Bayesian Optimization для поиска удачной комбинации.
Для быстрого старта есть presets light, medium и heavy.
Few-shot demos можно отключить, если prompt должен оставаться zero-shot.
Это один из основных сценариев MIPROv2.
Trainset и dev/test set нужно разделять, иначе optimizer легко переобучить на примеры, по которым вы его оцениваете.
Reflection optimizer использует не только score, но и объяснение ошибки
GEPA поддерживает population of candidate programs, оценивает их на validation set и просит reflection LM предложить изменения на основе execution traces и текстового feedback от metric.
def feedback_metric(example, prediction, trace=None):
score = 1.0 if prediction.category == example.category else 0.0
if score:
feedback = "Classification is correct."
else:
feedback = (
f"Expected {example.category}, "
f"but received {prediction.category}."
)
return dspy.Prediction(
score=score,
feedback=feedback,
)
optimizer = dspy.GEPA(
metric=feedback_metric,
auto="light",
)
optimized = optimizer.compile(
classifier,
trainset=trainset,
)
В документации DSPy подчёркивается: GEPA умеет работать и с обычным числовым score, но конкретный natural-language feedback даёт reflection-модели больше информации о причинах ошибки.
Вы по-прежнему задаёте dataset, metric, evaluation budget и LM. Автоматизирована именно часть поиска более удачных instructions/program variants.
DSPy официально показывает Ollama как local laptop backend
import dspy
lm = dspy.LM(
"ollama_chat/qwen3",
api_base="http://localhost:11434",
api_key="",
)
dspy.configure(lm=lm)
predict = dspy.ChainOfThought(
"question -> answer"
)
result = predict(
question="Что такое автоматическая оптимизация промптов?"
)
print(result.answer)
Для другого OpenAI-compatible local server можно использовать
openai/... model prefix и свой api_base.
В официальных docs пример с SGLang указывает endpoint вида http://localhost:7501/v1.
Optimizers, особенно reflection/instruction generation, могут требовать более сильной proposer/teacher model, чем конечная дешёвая модель в production.
DSPy умеет строить ReAct-программы, а tool-use тоже можно оценивать и оптимизировать
import dspy
def get_voltage() -> float:
"""Return demo mains voltage."""
return 231.4
agent = dspy.ReAct(
"question -> answer",
tools=[get_voltage],
)
result = agent(
question="Какое сейчас демонстрационное напряжение?"
)
print(result.answer)
DSPy 3.3.x также улучшает MCP compatibility. В beta 3.4.0b1 новый ReActV2 получил расширенную async MCP integration, но это уже pre-release функция и для stable-инструкции её лучше не считать обязательной.
DSPy-program может состоять из нескольких LM steps, retrieval, tools и agent loop. Metric при этом оценивает результат всей программы.
Скомпилированную программу можно сохранить и использовать без повторной оптимизации
optimized.save(
"./dspy_program/program.json",
save_program=False,
)
JSON state — предпочтительный вариант для обычного сохранения оптимизированных
instructions/demonstrations и state.
DSPy также умеет сохранять whole program через cloudpickle.
Безопаснее для переноса state между окружениями.
Нужен для whole-program serialization, но способен выполнять код при загрузке.
DSPy оптимизирует LLM-программы, но вокруг него остаётся обычная Python attack surface
Pickle/cloudpickle способны выполнить arbitrary Python code при deserialize.
Если whole-program serialization не нужна, лучше сохранять обычное состояние.
ReAct tool должен сам проверять permissions и arguments.
Исполняемый model-generated code нельзя приравнивать к простому text generation.
Local DSPy не делает cloud LM локальной — prompts уходят туда, куда указывает backend.
3.4.0b1 — beta. Для production не смешивайте stable и beta API без причины.
В 3.2.1 усилили безопасность cache
Release 3.2.1 отдельно отмечает изменение для dspy.Embedder,
связанное с предотвращением arbitrary code execution через повреждённые
или вредоносные cache files.
Stable 3.3.1 уже включает более новую ветку.
Официальная документация прямо предупреждает: загружать такие программы можно только из доверенного источника. Для обычного оптимизированного state предпочитайте JSON.
DSPy автоматизирует поиск prompt/program configuration, но не отменяет экспериментальную работу
Framework не знает бизнес-цель лучше вас.
Пять искусственных примеров могут оптимизировать совсем не production behavior.
MIPROv2 и GEPA делают много дополнительных model evaluations.
Train/dev/test нужно разделять так же, как в ML.
Оптимизированная программа для одной модели не гарантированно лучшая для другой.
3.4 уже содержит переходные изменения, а 3.5 планирует удаление deprecated API.
Если вы ещё не можете написать 20–50 реальных test cases и объяснить, что считается хорошим ответом, возможно, рано автоматизировать prompt optimization.
Где DSPy может дать больше пользы, чем очередной ручной rewrite prompt
Есть labelled cases и чёткая accuracy metric.
Можно оптимизировать query generation, reasoning и answer stage по одной общей metric.
Метрика проверяет полноту и правильность извлечённых полей.
Можно оценивать конечный результат, а не вручную тюнинговать каждый agent prompt.
Сильная teacher/proposer model помогает подобрать instructions для более дешёвой model.
Оптимизация идёт вместе с dataset/evaluation вместо случайных ручных экспериментов.
DSPy: stable version, optimizers, Ollama и безопасное сохранение
Stable package — dspy 3.3.1 от 21 августа 2026 года.
3.4.0b1 от 11 сентября — pre-release и сознательно не используется как baseline статьи.
DSPy нужен тогда, когда prompt перестал быть текстом и стал оптимизируемой частью программы
Для одного разового вопроса DSPy избыточен. Но если есть repeatable task, реальные examples и измеримая metric, framework позволяет заменить ручное «покрутим system prompt» на воспроизводимый optimization loop.
Особенно интересна связка: локальная или облачная LLM как backend, DSPy — для signatures/modules и optimization, отдельный evaluation set — для контроля regression, а Langfuse или другой OTel-инструмент — для production observability.
Частые вопросы про DSPy
Что такое DSPy простыми словами?
Python framework, в котором LLM-pipeline описывается как программа, а prompts и few-shot examples можно автоматически оптимизировать по metric и набору примеров.
DSPy сам обучает модель?
Не обязательно. Основной сценарий — оптимизация prompts/demonstrations без изменения weights. Есть также optimizers для fine-tuning, но это отдельный режим.
Можно ли использовать Ollama?
Да. Официальные docs показывают dspy.LM("ollama_chat/...", api_base="http://localhost:11434").
Что выбрать: MIPROv2 или GEPA?
MIPROv2 ищет instructions и demonstrations через proposal/search. GEPA использует reflection и особенно выигрывает от metric с текстовым feedback. Выбор нужно проверять на своём dev set.
Нужны ли сотни примеров?
Нет для первого эксперимента. Официальная документация предлагает BootstrapFewShot даже при примерно десяти examples. Более дорогие optimizers требуют больше данных, чтобы снизить риск overfitting.
DSPy заменяет Pydantic AI?
Нет. DSPy сфокусирован на программировании и optimization LM behavior. Pydantic AI больше про production agent runtime: typed outputs, tools, dependencies, MCP и durability.
Можно ли сохранить оптимизированную программу?
Да. Для обычного state предпочтителен JSON. Whole-program saving использует cloudpickle и должен загружаться только из доверенного источника.
Что актуально: dspy или dspy-ai?
Для нового проекта устанавливайте dspy. dspy-ai сейчас является compatibility alias.
Какая версия актуальна?
На 21 сентября 2026 года stable — DSPy 3.3.1. 3.4.0b1 существует, но это beta/pre-release.
Prompt уже меняли десятки раз и непонятно, действительно ли стало лучше?
Следующий шаг — собрать реальный evaluation set, формализовать metric и только после этого сравнивать ручной prompt, DSPy optimization и fine-tuning.