English translation is not available yet. Showing Russian content.

Что такое 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 / LlamaIndexDSPy
Основная задачаОркестрация (цепочки, агенты, 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

КритерийLangChainDSPy
ФилософияОркестрация компонентовОптимизация промптов
ПромптыРучные шаблоны (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 примеров).

Шаги:

  1. Загрузить датасет (например, datasets.load_dataset("imdb", split="train[:50]")).
  2. Разделить на train (30) и dev (20).
  3. Определить сигнатуру review -> sentiment.
  4. Создать модуль dspy.ChainOfThought("review -> sentiment").
  5. Написать метрику точности.
  6. Оптимизировать с BootstrapFewShot.
  7. Оценить на dev-сете.
  8. Сравнить с ручным промптом (просто 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. Навигация


Навигация