Что такое DSPy и какую проблему он решает, которую не решают LangChain или LlamaIndex?
Краткий тезис
DSPy (Declarative Self-improving Python) — это фреймворк для автоматической оптимизации промптов и few-shot примеров в LLM-пайплайнах. В отличие от LangChain и LlamaIndex, которые решают проблему оркестрации (соединения компонентов), DSPy решает проблему оптимизации — он по вашему датасету и метрике автоматически подбирает наилучший промпт и набор демонстраций, избавляя от ручного промпт-инжиниринга. Это позволяет систематически улучшать качество, а не полагаться на интуицию.
1. Термин: Промпт-инжиниринг и его ограничения
Промпт-инжиниринг — это искусство составления текстовых инструкций для LLM, чтобы получить желаемый ответ. Ручной подход имеет фундаментальные проблемы:
- Нестабильность: малейшее изменение формулировки может сильно изменить ответ.
- Отсутствие гарантий: нет способа доказать, что данный промпт оптимален.
- Затраты времени: на каждый новый датасет или задачу нужно подбирать промпт заново.
- Сложность few-shot: выбор правильных примеров (демонстраций) — отдельная нетривиальная задача.
LangChain и LlamaIndex предлагают абстракции (цепочки, агенты, индексы), но оставляют промпты на усмотрение разработчика. Они не занимаются оптимизацией — поиском наилучшего промпта и набора демонстраций для конкретной задачи.
2. Что такое DSPy?
DSPy — это фреймворк, который превращает построение LLM-пайплайнов из ручного промпт-инжиниринга в программируемую оптимизацию. Основные идеи:
- Signatures (сигнатуры) — декларативное описание входов и выходов модуля (например, question -> answer).
- Modules — строительные блоки, аналогичные слоям в нейросетях (например, dspy.ChainOfThought, dspy.ReAct).
- Optimizers (ранее Teleprompters) — алгоритмы, которые автоматически подбирают промпты и few-shot примеры, используя ваш датасет и метрику.
- Metrics — функции оценки качества (например, точность, F1, faithfulness).
DSPy не привязан к конкретному LLM — можно использовать OpenAI, Anthropic, локальные модели через Hugging Face.
3. Проблема, которую решает DSPy (и не решают LangChain/LlamaIndex)
| Аспект | LangChain / LlamaIndex | DSPy |
|---|---|---|
| Основная задача | Оркестрация (цепочки, агенты, RAG) | Оптимизация промптов и few-shot |
| Промпты | Разработчик пишет вручную или использует шаблоны | Автоматически подбираются под датасет |
| Few-shot примеры | Нужно выбирать вручную | Оптимизатор выбирает лучшие демонстрации |
| Метрика | Не встроена в процесс | Является центральной частью оптимизации |
| Воспроизводимость | Зависит от мастерства инженера | Систематическая, основана на данных |
Ключевое отличие: LangChain даёт инструменты для сборки пайплайна, но не помогает улучшить его качество. DSPy же автоматически настраивает промпты и примеры, чтобы максимизировать заданную метрику.
4. Компоненты DSPy подробнее
4.1 Signatures (Сигнатуры)
Сигнатура — это строка вида "input_field1, input_field2 -> output_field1". Например:
class GenerateAnswer(dspy.Signature):
"""Ответь на вопрос, используя контекст."""
context = dspy.InputField()
question = dspy.InputField()
answer = dspy.OutputField()
DSPy автоматически генерирует промпт на основе этой сигнатуры и описания.
4.2 Modules (Модули)
Встроенные модули реализуют распространённые паттерны:
- dspy.Predict — простой вызов LLM.
- dspy.ChainOfThought — добавляет рассуждения шаг за шагом.
- dspy.ReAct — агент с инструментами.
- dspy.RAG — retrieval-augmented generation.
Модули можно комбинировать, как в PyTorch.
4.3 Optimizers (Оптимизаторы)
Оптимизаторы — сердце DSPy. Они принимают модуль, датасет и метрику, и возвращают оптимизированную версию модуля с лучшими промптами и few-shot примерами.
Основные оптимизаторы:
- BootstrapFewShot — генерирует демонстрации, запуская модуль на обучающих данных и отбирая лучшие.
- BootstrapFewShotWithRandomSearch — перебирает случайные комбинации демонстраций.
- MIPRO (Bayesian Optimization) — более продвинутый, использует байесовскую оптимизацию для подбора инструкций и примеров.
- COPRO — оптимизирует только инструкцию (без few-shot).
4.4 Metrics (Метрики)
Метрика — это функция, которая принимает пример из датасета и предсказание модуля, и возвращает число (чем больше, тем лучше). Пример:
def accuracy(example, pred, trace=None):
return example.answer == pred.answer
5. Пример кода: DSPy пайплайн для ответов на вопросы
import dspy
from dspy.datasets import HotPotQA
# Настройка LLM
lm = dspy.OpenAI(model='gpt-4o-mini', max_tokens=300)
dspy.settings.configure(lm=lm)
# Загрузка датасета
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=1, dev_size=50)
trainset = [x.with_inputs('question') for x in dataset.train]
devset = [x.with_inputs('question') for x in dataset.dev]
# Определение модуля
class RAG(dspy.Module):
def __init__(self, num_passages=3):
super().__init__()
self.retrieve = dspy.Retrieve(k=num_passages)
self.generate_answer = dspy.ChainOfThought("context, question -> answer")
def forward(self, question):
context = self.retrieve(question).passages
prediction = self.generate_answer(context=context, question=question)
return dspy.Prediction(context=context, answer=prediction.answer)
# Метрика
def validate_answer(example, pred, trace=None):
return dspy.evaluate.answer_exact_match(example, pred)
# Оптимизация
optimizer = dspy.BootstrapFewShot(metric=validate_answer, max_bootstrapped_demos=4, max_labeled_demos=4)
compiled_rag = optimizer.compile(RAG(), trainset=trainset)
# Оценка
evaluate = dspy.Evaluate(devset=devset, metric=validate_answer, num_threads=4, display_progress=True)
score = evaluate(compiled_rag)
print(f"Accuracy: {score}")
После компиляции compiled_rag содержит оптимизированный промпт и набор демонстраций, которые можно сохранить и использовать.
6. Сравнение DSPy и LangChain
| Критерий | LangChain | DSPy |
|---|---|---|
| Философия | Оркестрация компонентов | Оптимизация промптов |
| Промпты | Ручные шаблоны (PromptTemplate) | Автоматически генерируются из сигнатур |
| Few-shot | Примеры задаются вручную | Подбираются оптимизатором |
| Метрика | Не является частью пайплайна | Центральная роль |
| Гибкость | Много интеграций (БД, API) | Ограниченный набор модулей |
| Когда использовать | Быстрая сборка сложных цепочек | Когда нужно максимальное качество на конкретном датасете |
DSPy и LangChain не исключают друг друга — их можно комбинировать: LangChain для оркестрации, DSPy для оптимизации промптов внутри шагов.
7. Когда выбирать DSPy, а когда LangChain/LlamaIndex
DSPy выбирают, когда:
- Есть размеченный датасет (хотя бы 10–100 примеров).
- Требуется максимальное качество на конкретной задаче (классификация, извлечение, ответы на вопросы).
- Хочется автоматизировать подбор промптов и few-shot.
- Нужна воспроизводимость и систематическое улучшение.
LangChain/LlamaIndex выбирают, когда:
- Нужно быстро прототипировать RAG или агента.
- Важна интеграция с внешними инструментами (БД, API, файлы).
- Нет размеченного датасета для оптимизации.
- Требуется гибкая оркестрация (ветвления, циклы).
8. Ограничения DSPy
- Требует датасет: без размеченных примеров оптимизация невозможна.
- Вычислительные затраты: оптимизация требует множества вызовов LLM (десятки-сотни).
- Ограниченная экосистема: меньше интеграций, чем у LangChain.
- Сложность отладки: оптимизированный промпт может быть неинтерпретируемым.
- Не для всех задач: для творческих задач (генерация текста) метрику сложно определить.
9. Пет-проект для закрепления
Задача: Создать DSPy-пайплайн для классификации отзывов на позитивные/негативные (sentiment analysis) и сравнить с ручным промптом.
Инструменты: Python, DSPy, OpenAI API (или локальная модель через Hugging Face), датасет IMDb (первые 100 примеров).
Шаги:
- Загрузить датасет (например, datasets.load_dataset("imdb", split="train[:50]")).
- Разделить на train (30) и dev (20).
- Определить сигнатуру
review -> sentiment. - Создать модуль
dspy.ChainOfThought("review -> sentiment"). - Написать метрику точности.
- Оптимизировать с
BootstrapFewShot. - Оценить на dev-сете.
- Сравнить с ручным промптом (просто
dspy.Predictбез оптимизации).
Ожидаемый результат: Оптимизированный модуль покажет точность на 10–20% выше, чем ручной промпт. Вы увидите, как DSPy автоматически подобрал инструкцию и примеры.
10. Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 100 | Что такое программируемые промпты? |
| 102 | Как DSPy оптимизирует few-shot примеры? |
| 103 | Сравнение DSPy и LangChain для RAG |
| 104 | Как написать свою метрику в DSPy? |
| 105 | Когда использовать MIPRO vs BootstrapFewShot? |
| 106 | Интеграция DSPy с Hugging Face |
11. Навигация
- Предыдущий: 100
- Следующий: 102
- Индекс: 00. Индекс разборов
Навигация
- Предыдущий: 100
- Следующий: 102
- Индекс: 00. Индекс разборов