Объясните концепцию «сигнатуры» (Signature) в DSPy. Чем она отличается от традиционного промпта?
Краткий тезис
Сигнатура в DSPy — это декларативное описание структуры входа и выхода языковой модели (например, question: str -> answer: str), которое не содержит конкретных инструкций на естественном языке. В отличие от традиционного промпта, где разработчик вручную пишет каждое слово инструкции, сигнатура задаёт только типы полей и их семантику, а DSPy автоматически превращает её в оптимизируемый промпт. Это делает разработку более модульной, тестируемой и позволяет применять автоматическую оптимизацию (например, подбор формулировок, few-shot примеров).
1. Термин: Сигнатура (Signature) в DSPy
Сигнатура — это ключевая абстракция фреймворка DSPy (Declarative Self-improving Python). Она определяет что должна сделать модель, а не как это сказать. Сигнатура состоит из:
- Входных полей (input fields) — например,
question: str, context: List[str]. - Выходных полей (output fields) — например, answer: str,
rationale: str. - Необязательного описания (desc) для каждого поля, которое помогает DSPy понять семантику.
Пример минимальной сигнатуры:
class QA(Signature):
question: str = InputField()
answer: str = OutputField()
DSPy трактует эту сигнатуру как «модель должна по вопросу сгенерировать ответ». На основе этой структуры DSPy самостоятельно строит промпт, подбирает стиль, добавляет few-shot примеры и даже может переформулировать описание полей для повышения качества.
2. Термин: Традиционный промпт (Hard‑coded Prompt)
Традиционный промпт — это жёстко заданная текстовая инструкция, которую разработчик пишет вручную. Например:
Ответь на вопрос, используя следующий контекст. Если контекст не содержит ответа, скажи "Я не знаю". Вопрос: {question}
Контекст: {context}
Проблемы такого подхода:
- Хрупкость: небольшое изменение формулировки может сильно повлиять на результат.
- Трудоёмкость: нужно вручную тестировать и переписывать инструкции.
- Сложность оптимизации: нет автоматического подбора примеров или переформулировок.
- Зависимость от конкретной модели: промпт, работающий для GPT‑4, может плохо работать для Llama 3.
3. Сравнение сигнатуры и традиционного промпта
| Критерий | Сигнатура (DSPy) | Традиционный промпт |
|---|---|---|
| Что задаётся | Структура и типы данных (поля) | Текстовая инструкция на естественном языке |
| Степень детализации | Высокоуровневая (декларативная) | Низкоуровневая (императивная) |
| Оптимизация | Автоматическая (DSPy подбирает формулировки, few‑shot, температуру) | Ручная (каждая правка — эксперимент) |
| Переиспользование | Легко: можно наследовать сигнатуры, комбинировать | Ограниченно: промпты обычно уникальны под задачу |
| Тестируемость | Высокая: легко подменять поля, менять типы | Низкая: тесты привязаны к конкретному тексту |
| Зависимость от модели | Слабая: оптимизатор адаптирует промпт под модель | Сильная: промпт пишется под конкретную модель |
| Сложность для простых задач | Избыточна (простой вопрос можно решить промптом) | Интуитивно понятна |
4. Как DSPy использует сигнатуру для построения промпта
Когда вы определяете сигнатуру и передаёте её в модуль DSPy (например, dspy.Predict), происходит следующее:
- Анализ сигнатуры: DSPy извлекает список входных и выходных полей, их типы, описания.
- Генерация шаблона промпта: Создаётся базовый промпт вида:
Complete the following task: Input: {field1}, {field2} → Output: {field3}. - Оптимизация: Оптимизатор (например, BootstrapFewShot, MIPROv2) может:
- Переформулировать описания полей (desc).
- Подобрать несколько примеров (few‑shot) на основе обучающих данных.
- Настроить температуру и другие параметры генерации.
- Выполнение: Модуль запускает модель с финальным промптом, передавая значения полей.
Пример кода:
import dspy
class QA(Signature):
question: str = InputField(desc="Вопрос пользователя на русском")
answer: str = OutputField(desc="Ответ на вопрос")
predict = dspy.Predict(QA)
result = predict(question="Какова столица Франции?")
print(result.answer) # Париж
В этом примере разработчик не писал ни единой инструкции — только описал поля.
5. Роль сигнатуры в оптимизации (DSPy Optimizers)
Оптимизаторы в DSPy — это алгоритмы, которые автоматически улучшают промпт, сгенерированный на основе сигнатуры. Они используют:
- BootstrapFewShot: отбирает лучшие примеры из обучающей выборки и добавляет их в промпт.
- MIPROv2: подбирает не только примеры, но и формулировки описаний полей с помощью байесовской оптимизации.
- SignatureOptimizer: изменяет саму структуру сигнатуры (добавляет/удаляет поля) на основе метрик.
Без сигнатуры такая оптимизация невозможна — у фреймворка нет «точки опоры», чтобы понять, какие части промпта можно менять.
6. Типы сигнатур
| Тип | Пример | Когда использовать |
|---|---|---|
| Встроенные (built‑in) | dspy.ChainOfThought, dspy.ProgramOfThought | Для стандартных рассуждений (CoT, PoT) |
| Простые кастомные | class MyQA(Signature): ... | Любая задача с фиксированными полями |
| Составные (композиция) | Одна сигнатура может содержать другую (через dspy.Module) | Для сложных многошаговых процессов |
DSPy также позволяет задавать сигнатуры без классов — через строковый синтаксис:
signature = "context: List[str], question: str -> answer: str"
7. Преимущества сигнатур перед традиционными промптами
- Декларативность: вы описываете задачу на уровне данных, а не на уровне слов.
- Модульность: сигнатуры можно наследовать (
class NewQA(QA):), добавлять новые поля. - Версионирование: сигнатура — это код, её легко отслеживать в Git.
- Автоматическая оптимизация: DSPy может менять формулировки промпта без участия человека.
- Переносимость: одна и та же сигнатура может использоваться с разными моделями (GPT, Claude, Llama), оптимизатор адаптирует промпт под конкретную модель.
8. Ограничения и когда традиционный промпт всё ещё нужен
- Креативные задачи: если нужно сгенерировать стихотворение в строгом стиле или имитировать конкретного автора, описание полей может не дать нужного качества — лучше написать промпт вручную.
- Высокая чувствительность к формулировке: некоторые задачи (например, извлечение данных в JSON) требуют точных инструкций; сигнатура может сгенерировать слишком вольный промпт.
- Простые одношаговые запросы: для быстрого прототипирования традиционный промпт проще и не требует установки DSPy.
- Совместимость с legacy кодом: если у вас уже есть сотни работающих промптов, переписывать их на сигнатуры неоправданно дорого.
9. Связь с другими концепциями DSPy
- Модули (dspy.Predict, dspy.ChainOfThought) — это обёртки, которые принимают сигнатуру и запускают модель с автоматически сгенерированным промптом.
- Телепромтеры (Teleprompters) — так в DSPy называются оптимизаторы; они работают именно с сигнатурами.
- Примеры (dspy.Example) — размеченные данные, которые оптимизатор использует для few‑shot обучения, опираясь на сигнатуру.
- Метрики — функции оценки, которые оптимизатор максимизирует, меняя промпт в рамках сигнатуры.
Пет-проект для закрепления
Задача: реализовать классификатор отзывов (позитивный/негативный) на русском языке с помощью DSPy, используя сигнатуру и автоматическую оптимизацию.
Инструменты:
- Python 3.10+
- Библиотеки: dspy, datasets (можно взять любой датасет отзывов).
- Модель: через API (OpenAI, Together) или локальная (через transformers).
Шаги:
- Создайте сигнатуру
SentimentSignature:class SentimentSignature(Signature): review: str = InputField(desc="Текст отзыва") sentiment: str = OutputField(desc="Позитивный или негативный") - Загрузите размеченные данные (например, 1000 отзывов с метками).
- Создайте модуль dspy.Predict(SentimentSignature).
- Используйте оптимизатор BootstrapFewShot с обучающей выборкой:
optimizer = dspy.BootstrapFewShot(metric=lambda gold, pred: gold.sentiment == pred.sentiment) optimized_predict = optimizer.compile(predict, trainset=trainset) - Оцените точность на тестовой выборке до и после оптимизации.
- Выведите промпт, который DSPy сгенерировал для первой итерации и после оптимизации.
Ожидаемый результат:
- Вы увидите, что без ручного написания инструкций модель достигает точности >85%.
- Промпт после оптимизации будет содержать тщательно подобранные few‑shot примеры и более чёткие описания полей.
- Вы сможете переключиться на другую модель (например, заменить gpt‑4 на claude‑3), просто изменив настройки в dspy.settings, и точность останется высокой благодаря адаптации промпта.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 101 | Основы DSPy, философия «промпт как код» |
| 103 | Механизмы автоматической оптимизации промптов |
| 104 | Связь сигнатур с модулями Predict, ChainOfThought |
| 105 | Переносимость сигнатур между моделями |
| 106 | Сигнатуры для retrieval и генерации |
| 107 | Конкретный оптимизатор, тесно работающий с сигнатурами |
Навигация
- Предыдущий: 101
- Следующий: 103
- Индекс: 00. Индекс разборов