Сбор датасета для дистилляции моделей через OpenRouter API 2026 | AiManual
AiManual Logo Ai / Manual.
23 Мар 2026 Гайд

Кради как художник: как собрать датасет для дистилляции из OpenRouter

Пошаговый гайд по сбору промптов и ответов из SOTA-моделей для тонкой настройки локальных LLM через OpenRouter. Актуально на март 2026.

Почему все собирают датасеты в 2026 году (и вам пора присоединиться)

Забудьте про тонкую настройку на общих датасетах. Результат - очередная посредственная модель, которая повторяет ошибки своих предшественников. Настоящая магия начинается, когда вы дистиллируете знания из топовых моделей прямо в свою маленькую LLM. Представьте: ваш 8-миллиардный параметрный Qwen начинает отвечать как Claude 3.7 Sonnet. Без шуток.

Проблема в одном: где взять эти знания? GPT-5 и Claude 4 недешевы. Аннотировать тысячи примеров вручную - год работы. Агрегаторы вроде OpenRouter дают доступ к десяткам моделей по цене от $0.10 за 1M токенов. Это ваш золотой ключик.

💡
Дистилляция в 2026 - это не просто копирование ответов. Это создание специализированного эксперта в конкретной области: юридические консультации, медицинские аннотации, код-ревью. Собираете датасет в своей нише - получаете монополиста.

OpenRouter в 2026: что изменилось и как этим пользоваться

Если вы до сих пор не знакомы с OpenRouter, у вас огромный пробел. Это агрегатор, который в 2026 году поддерживает все актуальные модели: от свежего GPT-5 и Claude 4 до открытых гигантов вроде Qwen2.5-72B и Llama 4 405B. Главное - единый API и биллинг. Как пишут в нашем гайде про агрегаторы, это спасение для разработчиков вне США.

Важный нюанс марта 2026: многие провайдеры ввели жесткие ограничения на объем данных для дистилляции. OpenAI прямо запрещает сбор более 10к примеров в сутки через их API для этой цели. OpenRouter обходит часть ограничений, но работает в серой зоне. Риски есть.

Почему именно OpenRouter для сбора датасета?

  • Доступ к 40+ моделям через один API ключ
  • Прозрачное ценообразование (видите стоимость каждого запроса)
  • Возможность роутинга: один промпт - ответы от нескольких моделей
  • Нет географических ограничений и проблем с оплатой
  • Поддержка streaming, что ускоряет сбор данных

Пошаговый разбор: от идеи до готового датасета

1Определяем цель и готовим промпты

Собирать все подряд - пустая трата денег. Определитесь: вам нужен код-ассистент, эксперт по финансовым отчетам или творческий писатель? Создайте семплирование промптов. Как это делаю я:

  • Беру реальные вопросы из наших тикетов в Jira
  • Использую техники structured prompting для разнообразия
  • Добавляю edge cases: что-то сломалось, нестандартный запрос, провокационные вопросы
  • Минимум 1000 уникальных промптов. Меньше - шум в данных
# Пример подготовки промптов для код-ассистента
import json
from typing import List

def generate_coding_prompts(count: int = 1000) -> List[str]:
    """Генерация разнообразных промптов для программирования"""
    base_prompts = [
        "Напиши функцию на Python, которая...",
        "Найди ошибку в следующем коде...",
        "Оптимизируй этот SQL запрос...",
        "Объясни концепцию... простыми словами",
        "Сравни два подхода к...",
        "Сгенерируй тесты для..."
    ]
    
    # Добавляем контекст из реальных проектов
    domains = ["веб-разработка", "data science", "DevOps", "мобильные приложения"]
    languages = ["Python", "JavaScript", "Go", "Rust", "SQL"]
    
    prompts = []
    for i in range(count):
        prompt = f"{random.choice(base_prompts)} \n"
        prompt += f"Домен: {random.choice(domains)}. Язык: {random.choice(languages)}.\n"
        prompt += "Давай пошаговое решение с объяснениями."
        prompts.append(prompt)
    
    return prompts

2Выбираем модели-учителя (ошибка здесь стоит дорого)

Не все модели одинаково полезны для дистилляции. GPT-5 дает блестящие, но слишком сложные ответы. Qwen2.5-72B ближе к тому, что сможет воспроизвести ваша маленькая модель. Мой текущий стек (март 2026):

МодельЦельСтоимость / 1M токенов
Claude 3.7 SonnetСложные reasoning задачи$15
GPT-5 PreviewКреатив и многозадачность$12
Qwen2.5-72B-InstructБазовые инструкции (основной источник)$0.80
DeepSeek Coder 33BСпециализированный код (если нужно)$0.40

Совет: начните с Qwen2.5-72B. Его ответы сбалансированы по сложности и качеству. Добавьте 10% промптов к Claude для сложных случаев. GPT-5 оставьте для творческих задач.

💡
В нашей статье про open-weight модели мы подробно разбирали, почему Qwen2.5 догнал проприетарные аналоги. Для дистилляции это идеальный компромисс цена/качество.

3Пишем скрипт сбора (с защитой от обрыва связи)

Главная ошибка новичков - скрипт без retry логики и контроля стоимости. Потратить $500 на битые ответы - неприятно. Вот production-ready версия:

import requests
import json
import time
from typing import Dict, Any, Optional
from tenacity import retry, stop_after_attempt, wait_exponential

class OpenRouterDatasetCollector:
    def __init__(self, api_key: str, model: str = "qwen/qwen-2.5-72b-instruct"):
        self.api_key = api_key
        self.model = model
        self.base_url = "https://openrouter.ai/api/v1/chat/completions"
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
            "HTTP-Referer": "https://yourdomain.com",  # Обязательно для OpenRouter
        }
        
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
    def get_completion(self, prompt: str, temperature: float = 0.7) -> Optional[str]:
        """Получаем ответ от модели с retry логикой"""
        payload = {
            "model": self.model,
            "messages": [
                {"role": "user", "content": prompt}
            ],
            "temperature": temperature,
            "max_tokens": 2000,
        }
        
        try:
            response = requests.post(
                self.base_url,
                headers=self.headers,
                json=payload,
                timeout=30
            )
            response.raise_for_status()
            
            data = response.json()
            
            # Сохраняем метаданные для анализа стоимости
            usage = data.get("usage", {})
            print(f"Токены: {usage.get('total_tokens', 0)} | Стоимость: ~${usage.get('total_tokens', 0) * 0.8 / 1_000_000:.4f}")
            
            return data["choices"][0]["message"]["content"]
            
        except requests.exceptions.RequestException as e:
            print(f"Ошибка запроса: {e}")
            if hasattr(e.response, 'status_code'):
                if e.response.status_code == 429:
                    print("Rate limit. Ждем 60 секунд...")
                    time.sleep(60)
                elif e.response.status_code == 502:
                    print("Bad gateway. Ждем 30 секунд...")
                    time.sleep(30)
            raise
        
    def collect_dataset(self, prompts: list, output_file: str = "dataset.jsonl"):
        """Основной цикл сбора данных"""
        dataset = []
        
        for i, prompt in enumerate(prompts):
            print(f"Обработка промпта {i+1}/{len(prompts)}")
            
            try:
                answer = self.get_completion(prompt)
                
                if answer:
                    entry = {
                        "prompt": prompt,
                        "response": answer,
                        "model": self.model,
                        "timestamp": time.time(),
                        "metadata": {
                            "prompt_length": len(prompt),
                            "response_length": len(answer)
                        }
                    }
                    
                    # Постоянное сохранение на диск
                    with open(output_file, "a", encoding="utf-8") as f:
                        f.write(json.dumps(entry, ensure_ascii=False) + "\n")
                    
                    dataset.append(entry)
                    
                    # Пауза между запросами
                    time.sleep(0.5)
                    
            except Exception as e:
                print(f"Критическая ошибка на промпте {i}: {e}")
                # Сохраняем прогресс
                with open(f"{output_file}.backup", "w", encoding="utf-8") as f:
                    json.dump(dataset, f, ensure_ascii=False, indent=2)
                
        return dataset

4Фильтрация и постобработка (здесь рождается качество)

Собрать ответы - полдела. 30% данных будут мусором: отказы отвечать, политика безопасности, обрывы. Фильтруем агрессивно:

def filter_dataset(input_file: str, output_file: str):
    """Фильтрация собранного датасета"""
    filtered = []
    rejection_patterns = [
        "Я не могу",
        "Извините",
        "как AI",
        "этической",
        "безопасности",
        "[Ответ отклонен]",
        "### Отказ"
    ]
    
    with open(input_file, "r", encoding="utf-8") as f:
        for line in f:
            entry = json.loads(line)
            response = entry["response"].lower()
            
            # Проверка на отказ
            if any(pattern.lower() in response for pattern in rejection_patterns):
                continue
                
            # Проверка длины (слишком короткие ответы - мусор)
            if len(response) < 50:
                continue
                
            # Проверка на повторения (модель зациклилась)
            words = response.split()
            if len(set(words)) / len(words) < 0.5:
                continue
            
            filtered.append(entry)
    
    # Сохраняем отфильтрованный датасет
    with open(output_file, "w", encoding="utf-8") as f:
        for entry in filtered:
            f.write(json.dumps(entry, ensure_ascii=False) + "\n")
    
    print(f"Сохранили {len(filtered)} из {total} записей после фильтрации")
    return filtered

Сколько это стоит и как не разориться

Давайте посчитаем на реальном примере:

  • 1000 промптов, средняя длина 150 токенов
  • Ответы по 500 токенов в среднем
  • Используем Qwen2.5-72B ($0.80 за 1M токенов)

Расчет: (150 + 500) × 1000 = 650,000 токенов. Стоимость: 650,000 × 0.8 / 1,000,000 = $0.52. Да, полдоллара за датасет из 1000 примеров. Добавим 20% на ошибки и повторные запросы - $0.62.

Ловушка: если вы используете GPT-5 или Claude 4, стоимость вырастет в 15-20 раз. Для Qwen2.5-72B качество ответов в 2026 году почти не уступает топовым моделям в большинстве задач. Берите open-weight модели как основной источник.

Где ошибаются 90% разработчиков (список от эксперта)

  1. Слишком высокая температура - ответы становятся творческими, но нестабильными. Для дистилляции используйте temperature 0.3-0.7.
  2. Отсутствие системного промпта - добавьте "Ты - эксперт по... Отвечай подробно и структурированно". Это формирует стиль.
  3. Сбор только текстовых ответов - если ваша модель будет генерировать код, соберите примеры с кодом. Если JSON - добавьте structured output.
  4. Игнорирование токенизации - промпт в 5000 токенов + ответ в 5000 = вы платите за 10к токенов. Следите за длиной.
  5. Нет баланса типов промптов - 80% простых, 15% средних, 5% сложных. Так модель научится и базовому, и сложному.

Что дальше? Тонкая настройка на украденных знаниях

У вас есть датасет. Теперь самое интересное - дистилляция. В 2026 году для этого есть три основных подхода:

  • Полная тонкая настройка - классика. Используйте NTTuner или его аналоги с QLoRA
  • Дистилляция через DPO - если собрали ответы от нескольких моделей, можно обучить модель выбирать лучший ответ
  • Кросс-модельная дистилляция - смешиваете ответы от Qwen, Claude и специализированных моделей

Мой стек на март 2026: Unsloth + QLoRA на 8-bit, 3 эпохи, learning rate 2e-4, группировка по 1024 токена. Обучение 7B модели на 1000 примерах занимает около часа на RTX 4090.

💡
Если вы работаете в корпоративной среде с ограниченным интернетом, посмотрите наш гайд про локальные LLM за бетонной стеной. Там те же принципы, но другие ограничения.

Один неочевидный трюк, который удваивает эффективность

Собирайте не только пары "промпт-ответ", но и промежуточные рассуждения. Попросите модель "думать вслух". Например:

prompt = """
Реши задачу: У Васи было 5 яблок, 2 он отдал Пете. Сколько осталось?

Пожалуйста, покажи пошаговые рассуждения перед ответом.
"""

Ответ модели будет содержать цепочку мыслей. Когда вы обучите на этом свою маленькую модель, она научится не просто выдавать ответ, а рассуждать логически. Это секретная техника, которая превращает 7B модель в 70B по качеству reasoning.

В 2027 году, кстати, ожидаю взрывной рост инструментов для автоматической дистилляции. Уже сейчас появляются сервисы, которые за $100 собирают датасет и настраивают модель под ваши нужды. Но понимание процесса - ваше конкурентное преимущество. Учитесь красть знания у гигантов, пока они не начали защищаться эффективнее.

Подписаться на канал