Как вы делаете synthetic data для сложного рассуждения (math, code)?

Краткий тезис

Синтетические данные для сложного рассуждения (math, code) создаются через генерацию Chain-of-Thought (пошаговых рассуждений) с последующей валидацией: другой LLM проверяет логику, для кода — запуск в песочнице, а также через backward generation (ответ → вопрос) и self-consistency (множественные траектории с голосованием). Эти методы позволяют получать большие размеченные датасеты без ручной аннотации, что критически важно для обучения агентов, способных к многошаговому рассуждению в Agentic RAG.


1. Термин: Synthetic data для reasoning

Synthetic data — это искусственно сгенерированные данные, имитирующие реальные. В контексте сложного рассуждения (math, code) это пары (вопрос, пошаговое решение + ответ), созданные LLM без участия человека.

Зачем нужны синтетические данные

  • Ручная разметка сложных рассуждений (например, доказательств теорем или многошаговых алгоритмов) крайне дорога и трудоёмка.
  • Для обучения Agentic RAG (агентов, которые используют инструменты и делают несколько шагов) требуются тысячи примеров с цепочками действий.
  • Синтетические данные позволяют масштабировать датасеты и покрывать редкие сценарии.

Основные подходы (из черновика):


2. Chain-of-Thought (CoT) генерация

Chain-of-Thought — это методика, при которой LLM генерирует не только ответ, но и промежуточные шаги рассуждения. Для синтетических данных мы используем CoT-промпты, чтобы получить размеченные примеры.

Пример промпта для математики

Ты — репетитор по математике. Реши задачу пошагово, объясняя каждый шаг.
Задача: {question}
Решение:

Пример генерации

Задача: Если x + 2 = 5, чему равно x?
Решение:
1. Исходное уравнение: x + 2 = 5.
2. Вычтем 2 из обеих частей: x + 2 - 2 = 5 - 2.
3. Получаем: x = 3.
Ответ: 3.

Для кода промпт может требовать генерации кода с комментариями и выводом.

Проблема LLM может генерировать правдоподобные, но неверные рассуждения. Поэтому нужна валидация.


3. Проверка (Check) другим LLM

Используется второй LLM (или та же модель с другим промптом) для верификации корректности рассуждения.

Методы проверки

  • Проверка ответа совпадает ли финальный ответ с правильным (если известен).
  • Проверка шагов логически ли каждый шаг следует из предыдущего, нет ли ошибок в арифметике или синтаксисе кода.
  • Критерии для math — численная проверка, для code — запуск и сравнение вывода с ожидаемым.

Пример промпта для проверки

Проверь решение математической задачи. Укажи, верен ли каждый шаг, и есть ли ошибка в ответе.
Задача: {question}
Решение: {solution}
Вердикт (верно/неверно):

Таблица: плюсы и минусы проверки LLM

ПлюсыМинусы
Не требует внешних инструментовLLM может пропустить ошибки (hallucination)
Быстро и дешевоЗависит от качества модели-верификатора
МасштабируетсяТрудно проверить сложные логические цепочки

4. Симуляция для кода

Для задач, связанных с программированием, лучший способ валидации — запустить сгенерированный код в изолированной среде (песочнице) и проверить результат.

Процесс

  1. LLM генерирует код по описанию задачи.
  2. Код выполняется в контейнере (Docker, subprocess с ограничениями).
  3. Сравнивается вывод с ожидаемым (если есть тесты) или проверяется отсутствие ошибок.
  4. Если код не работает или выдаёт неверный результат — пример отбрасывается или модифицируется.

Пример на Python

import subprocess
import tempfile

def validate_code(code, test_input, expected_output):
    with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
        f.write(code)
        f.flush()
        try:
            result = subprocess.run(
                ['python', f.name],
                input=test_input,
                capture_output=True,
                text=True,
                timeout=5
            )
            return result.stdout.strip() == expected_output.strip()
        except Exception:
            return False

Преимущество объективная проверка, не зависит от LLM. Недостаток нужно готовить тесты, что тоже может быть автоматизировано (LLM генерирует тесты).


5. Backward generation

Backward generation (обратная генерация) — метод, при котором сначала создаётся ответ или решение, а затем по нему генерируется вопрос. Это гарантирует, что вопрос имеет корректный ответ.

Алгоритм

  1. Выбираем тему (например, "линейные уравнения").
  2. LLM генерирует случайное корректное решение (например, x = 3).
  3. На основе решения LLM генерирует вопрос: "Придумай задачу, ответом на которую будет x = 3".
  4. Проверяем, что при решении сгенерированного вопроса получается исходный ответ (можно через CoT + проверку).

Пример:

  • Шаг 1: Решение: x = 3.
  • Шаг 2: Сгенерированный вопрос: "Решите уравнение: 2x + 1 = 7".
  • Шаг 3: Проверка: решаем уравнение — получаем x = 3. Совпало → пример корректен.

Преимущество гарантируется, что ответ правильный (если проверка пройдена). Недостаток вопросы могут быть однотипными или слишком простыми.


6. Self-consistency

Self-consistency — метод, при котором для одного вопроса генерируется несколько независимых цепочек рассуждений (CoT), а затем выбирается наиболее частый ответ (majority vote). Если ответы совпадают, пример считается надёжным.

Процесс

  1. Для вопроса Q LLM генерирует N рассуждений (например, 5).
  2. Из каждого извлекается финальный ответ.
  3. Выбирается ответ, который встречается чаще всего.
  4. Если все ответы разные — пример отбрасывается.

Пример для math

  • Вопрос: "Сколько будет 12 * 15?"
  • Рассуждение 1: "1210=120, 125=60, 120+60=180" → ответ 180.
  • Рассуждение 2: "1510=150, 152=30, 150+30=180" → ответ 180.
  • Рассуждение 3: "12*15=180" → ответ 180.
  • Majority vote: 180 → пример принимается.

Self-consistency повышает качество датасета, отсеивая случайные ошибки. Используется как финальный фильтр.


7. Комбинированные методы

На практике подходы комбинируют. Пример пайплайна для создания датасета по математике:

  1. Backward generation → получаем вопрос и гарантированный ответ.
  2. CoT генерация → LLM строит пошаговое решение.
  3. Проверка другим LLM → верификация шагов.
  4. Self-consistency → генерация 3 траекторий, majority vote.
  5. Фильтрация → оставляем только примеры, где все проверки пройдены.

Для кода дополнительно добавляется симуляция (запуск кода с тестами).

Таблица сравнения методов

МетодТип валидацииНадёжностьСтоимость
CoT + проверка LLMЛогическаяСредняяНизкая
Симуляция кодаИсполнениеВысокаяСредняя
Backward generationОбратная связьВысокая (при проверке)Средняя
Self-consistencyСтатистическаяВысокаяВысокая (много вызовов)

8. Инструменты и фреймворки

  • DSPy — фреймворк для программирования LLM, позволяет строить пайплайны генерации и валидации синтетических данных. Есть модули ChainOfThought, ReAct, Assertions.
  • LangChain — с помощью LLMChain и SequentialChain можно организовать многошаговую генерацию и проверку.
  • OpenAI / Anthropic API — прямые вызовы с кастомными промптами.
  • Собственные скрипты на Python с использованием asyncio для параллельной генерации.

Пример на DSPy (упрощённо):

import dspy

class GenerateCoT(dspy.Signature):
    question = dspy.InputField()
    reasoning = dspy.OutputField()
    answer = dspy.OutputField()

class VerifySolution(dspy.Signature):
    question = dspy.InputField()
    reasoning = dspy.InputField()
    answer = dspy.InputField()
    is_correct = dspy.OutputField(desc="True/False")

pipeline = dspy.Pipeline(GenerateCoT(), VerifySolution())

9. Связь с Agentic RAG

В Agentic RAG агент должен выполнять многошаговые рассуждения, использовать инструменты (поиск, калькулятор, код). Синтетические данные, созданные описанными методами, используются для:

  • Fine-tuning базовой LLM на рассуждения с инструментами.
  • Обучения политики агента (какой инструмент выбрать на каждом шаге).
  • Создания датасетов для оценки (benchmark) агентных систем.

Например, можно сгенерировать синтетические траектории, где агент сначала пишет код для вычисления, затем проверяет результат через калькулятор, а потом формулирует ответ. Такие данные улучшают способность агента к tool use и multi-step reasoning.


10. Проблемы и ограничения

  • Качество генерации LLM может генерировать правдоподобные, но неверные рассуждения (hallucination). Требуется многоуровневая фильтрация.
  • Перекос (bias): синтетические данные могут наследовать bias базовой модели, например, предпочтение определённых типов задач.
  • Стоимость генерация большого датасета с self-consistency и проверками требует много API-вызовов.
  • Разнообразие: backward generation может порождать однотипные вопросы. Нужны техники для увеличения разнообразия (например, случайные параметры, комбинирование тем).

Пет-проект для закрепления

Задача Создать датасет из 1000 примеров для решения квадратных уравнений с пошаговым рассуждением.

Инструменты Python, OpenAI API (или локальная модель), библиотека sympy для проверки решений.

Шаги:

  1. Backward generation: сгенерировать 1200 случайных квадратных уравнений с помощью sympy (гарантированно корректные корни).
  2. CoT генерация для каждого уравнения попросить LLM (например, GPT-4) написать пошаговое решение через дискриминант.
  3. Проверка другой LLM проверяет каждый шаг. Отбрасываем примеры, где шаги нелогичны.
  4. Self-consistency для каждого уравнения генерируем 3 решения, оставляем только те, где ответы совпадают.
  5. Симуляция (опционально): для уравнений с комплексными корнями — проверка через sympy.
  6. Форматирование сохраняем в JSON (question, reasoning, answer).

Ожидаемый результат чистый датасет из 1000 примеров, готовый для fine-tuning модели на математические рассуждения.


Связь с другими вопросами

ВопросТема
697Как обучать агента для Agentic RAG?
699Как оценивать качество рассуждений агента?
700Как интегрировать инструменты (код, калькулятор) в агента?
701Как реализовать multi-step reasoning в агенте?
702Как обеспечить consistency в ответах агента?
703Какие метрики использовать для оценки агентных систем?

Навигация