Почему Text-to-SQL ломается на ваших данных
Вы берете готовую модель для генерации SQL. GPT-5 Turbo, Claude 3.7, даже специальные CodeLLaMA. Даете ей описание вашей базы данных - схемы таблиц, связи. Просите: "покажи заказы за последнюю неделю". И она выдает идеальный SQL. Для PostgreSQL. А у вас - кастомный диалект на старом Oracle, с самописными функциями, которые не описаны ни в одной документации. Или унаследованная СУБД, где JOIN пишется не так. Модель генерирует красивый, синтаксически правильный код, который не работает. Вообще.
COMPANY_LEGACY_CALC_REVENUE() или странных правил наследования прав. Модель просто не знает, что так можно.Классическое решение - fine-tuning. Берем большую модель, загружаем тысячи примеров наших запросов и правильного SQL, обучаем несколько эпох. Результат отличный, но счет за обучение заставляет плакать. А инференс? Каждый запрос к 70B модели стоит как маленький кофе. Если запросов 100 в день - кофе превращается в ежедневный кейтеринг для отдела.
Amazon Nova Micro: зачем платить за слона, если нужна мышь
В апреле 2025 Amazon анонсировал серию "Nova Micro" - компактные модели на 3B и 7B параметров, оптимизированные для конкретных задач. Nova Micro-SQL (7B) - специально для генерации и понимания SQL. Она не умеет писать поэзию, плохо поддерживает диалог, зато в синтаксисе SQL разбирается лучше 70B монстров. Потому что обучена на терабайтах кода и документации к СУБД.
На 19.04.2026 актуальная версия - Nova Micro-SQL v2.1. Основное изменение - улучшенная поддержка window functions и лучшее понимание контекста длиной до 8K токенов. Если вы используете более старую версию (v1.x), смотрите инструкцию по миграции.
Цена инференса Nova Micro в Bedrock: $0.0004 за 1K токенов output. Для сравнения, Nova Pro (70B) - $0.008. Разница в 20 раз. Латентность? 120-180 мс против 600-800 мс. Но модель не знает ваших кастомных правил. Значит, нужно ее дообучить. И здесь в игру вступает LoRA.
Подготовка датасета: от сырых логов до чистых примеров
Самый сложный этап. Вам нужны пары "естественный язык -> SQL". Где их взять?
- Логи приложений: если у вас есть интерфейс, где пользователи вводят запросы через форму, а бэкенд генерирует SQL - это золотая жила. Но такие системы редкость.
- История запросов в BI-инструментах: Tableau, Power BI, Superset хранят логи, какие фильтры выбирали пользователи и какие SQL генерировались.
- Ручная разметка: попросите 3-5 аналитиков неделю писать запросы и правильный SQL. Скучно, дорого, но эффективно.
- Синтетическая генерация: используйте детерминированную модель для создания примеров на основе схемы БД.
Вам нужно 500-1000 качественных примеров. Меньше - модель недообучится. Больше - потратите время на чистку. Формат - JSONL, каждая строка:
{
"instruction": "Покажи топ-10 клиентов по сумме заказов за 2025 год, исключив тестовые аккаунты",
"input": "Таблицы: customers (id, name, is_test), orders (id, customer_id, amount, created_at). Связь: orders.customer_id = customers.id",
"output": "SELECT c.id, c.name, SUM(o.amount) as total FROM customers c JOIN orders o ON c.id = o.customer_id WHERE c.is_test = 0 AND EXTRACT(YEAR FROM o.created_at) = 2025 GROUP BY c.id, c.name ORDER BY total DESC LIMIT 10;"
}
Ключевой момент - в поле `input` вы должны включать схему БД, которую модель будет использовать для генерации. Не надейтесь, что модель запомнит схему после обучения - давайте ее в контексте каждого запроса.
1Запуск тонкой настройки с LoRA в SageMaker
Полный fine-tuning 7B модели потребует GPU с 40+ GB памяти. LoRA (Low-Rank Adaptation) меняет правила игры - обучаются только небольшие адаптеры, встраиваемые в модель. Памяти нужно в 4 раза меньше.
AWS предлагает Managed Training в SageMaker. Создаем конфигурационный файл:
# training-config.yaml
model_id: amazon/nova-micro-sql-v2-1
lora:
r: 16 # ранг адаптера
lora_alpha: 32 # scaling параметр
target_modules: ["q_proj", "v_proj", "k_proj", "o_proj"]
bias: "none"
dataset_path: s3://your-bucket/training-data.jsonl
output_dir: s3://your-bucket/lora-adapters/
num_train_epochs: 5
per_device_train_batch_size: 4
learning_rate: 2e-4
warmup_steps: 100
logging_steps: 50
Запускаем тренировку через SDK SageMaker:
from sagemaker.huggingface import HuggingFace
estimator = HuggingFace(
entry_point='train.py',
instance_type='ml.g5.2xlarge', # 24GB памяти, достаточно для LoRA
instance_count=1,
base_job_name='nova-micro-lora-tuning',
role=iam_role,
transformers_version='4.36.0',
pytorch_version='2.1.0',
hyperparameters={
'model_id': 'amazon/nova-micro-sql-v2-1',
'dataset_path': '/opt/ml/input/data/train',
'num_train_epochs': 5
}
)
estimator.fit({
'train': 's3://your-bucket/training-data.jsonl'
})
2Упаковка модели с адаптерами для Bedrock
Bedrock не принимает голые адаптеры LoRA. Нужно создать кастомную модель, объединив базовую Nova Micro с обученными адаптерами. AWS предоставляет контейнер для упаковки.
# Скачиваем базовую модель и адаптеры
aws s3 cp s3://your-bucket/lora-adapters/ ./adapters --recursive
# Используем официальный скрипт объединения
python -m amazon_bedrock_model_merger \
--base-model-id amazon/nova-micro-sql-v2-1 \
--adapter-path ./adapters \
--output-dir ./merged-model \
--model-version 1.0.0
# Упаковываем в tar.gz для загрузки в S3
tar czvf nova-micro-custom-sql.tar.gz -C ./merged-model .
aws s3 cp nova-micro-custom-sql.tar.gz s3://your-bucket/custom-models/
Теперь в консоли Bedrock создаем кастомную модель, указывая S3-путь к архиву. Важный нюанс - выбираем инстанс `ml.g5.xlarge` для инференса. Bedrock будет масштабировать его автоматически при нагрузке, но базовая емкость - 1 инстанс.
3Настройка serverless inference с оплатой по запросу
В Bedrock теперь есть два варианта: Provisioned Throughput (фиксированная плата за час) и On-Demand (оплата по запросу). Для Text-to-SQL с неравномерной нагрузкой выбираем On-Demand.
Стоимость: $0.0006 за 1K токенов output для кастомной модели (на 50% дороже базовой Nova Micro, потому что используется кастомный инстанс). Входные токены - $0.0002 за 1K.
Вызываем модель через API:
import boto3
from botocore.config import Config
bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')
# Используем географическую маршрутизацию для снижения латентности
# Подробнее: https://example.com/article/amazon-bedrock-v-oklende-kak-geograficheskaya-marshrutizatsiya-menyaet-pravila-igryi/
# (Внутренняя ссылка: Amazon Bedrock в Окленде)
response = bedrock.invoke_model(
modelId='your-custom-model-id',
contentType='application/json',
accept='application/json',
body=json.dumps({
'prompt': f"Схема БД: {schema}. Запрос: {user_query}",
'max_tokens': 500,
'temperature': 0.1, # Низкая температура для детерминированного SQL
'stop_sequences': [';'] # Останавливаемся на точке с запятой
})
)
result = json.loads(response['body'].read())
generated_sql = result['generations'][0]['text']
Цифры: сколько вы сэкономите (и что потеряете)
Давайте посчитаем на примере реального кейса. У вас 1000 запросов в день. Средний SQL - 150 токенов output, промпт с схемой - 300 токенов input.
| Сценарий | Модель | Стоимость инференса в месяц | Латентность (p95) | Точность на кастомных SQL |
|---|---|---|---|---|
| Без fine-tuning | Nova Pro (70B) | ~$48.00 | 720 мс | 45% |
| Без fine-tuning | Nova Micro (7B) | ~$2.40 | 160 мс | 60% |
| Наше решение | Nova Micro + LoRA | ~$1.60 | 180 мс | 92% |
Экономия против Nova Pro: $46.40 в месяц. Против базовой Nova Micro: $0.80. Кажется, мелочь? Но точность выросла с 60% до 92%. Каждый ошибочный SQL - это либо падение сервиса, либо тикет в поддержку, либо неправильные данные для бизнеса.
Частые ошибки: как не убить модель за 5 минут
- Переобучение на маленьком датасете: 100 примеров и 20 эпох - модель запомнит примеры, но не научится обобщать. Рецепт: 500+ примеров, 3-5 эпох, ранняя остановка.
- Забыть про валидацию: выделите 10-15% данных для теста. Если после обучения модель на них падает, значит, она просто зазубрила тренировочные данные.
- Игнорировать токенизацию SQL: SQL токенизируется иначе, чем английский текст. Используйте специальные токенайзеры для кода или добавьте функции вознаграждения за правильный синтаксис.
- Подавать неполную схему: если в промпте нет актуальной схемы БД (типы полей, связи), модель будет гадать. И ошибаться.
- Температура выше 0.3: для SQL нужна детерминированность. Температура 0.1-0.2. Иначе получите 5 разных вариантов запроса, и все неправильные.
А что насчет сложных JOIN и вложенных запросов?
Nova Micro-SQL v2.1 хорошо справляется с 2-3 уровнями вложенности. Если ваши аналитики пишут монстров на 100 строк с CTE и window functions - модель может сломаться. Решение: разбить запрос на части. Сначала генерируем высокоуровневую логику, потом детализируем. Или использовать техники из кейса New Relic, где сложные запросы собираются по шагам.
Главный секрет не в модели, а в данных. 500 чистых примеров с вашими кастомными функциями дадут больший прирост точности, чем переход с 7B на 70B модель. Инвестируйте время в датасет. Один день работы двух аналитиков сэкономит тысячи долларов на инференсе.
Следующий шаг - добавить семантический поиск по схемам. Когда пользователь спрашивает "сколько у нас активных пользователей", а в БД есть 5 разных определений "активности", модель должна найти нужное. Здесь помогут Nova Embeddings. Но это тема для отдельного гайда.