IАргументы против генерируемого SQL

Модель не должна
писать SQL.

Text-to-SQL — очевидный способ направить агента к базе данных, и демонстрация действительно впечатляет. Но в продакшене картина меняется: один и тот же вопрос компилируется в разный SQL, тихая ошибка в джойне смещает выручку на 15%, а вывод модели становится поверхностью атаки. Есть другой путь.

IIСначала авторство

Text-to-SQL заслужил хайп. В своей нише.

Где это правильный инструмент

  • Прототипы на временных данных
  • Изучение незнакомой схемы под наблюдением
  • Разовые вопросы, которые кто-то проверит вручную
  • Демо — и правда смотрится убедительно

Где это ломается

  • Цифры, на которые будут опираться в решениях
  • Ненадёжный текст где угодно в контексте
  • Боевые учётные данные в строке подключения
  • Ответы, которые должны воспроизводиться или проходить аудит
  • Агенты, работающие без надзора

Паттерн не ошибочен. Ошибочен радиус поражения. Каждая угроза на этой странице восходит к одному архитектурному решению: вывод модели исполняется как код.

IIIДва пути

Один вопрос. Две архитектуры.

Проследите один вопрос по обоим путям — произвольная SQL-строка слева, типизированный план справа. Пронумерованные метки ссылаются на реестр угроз ниже.

вопрос

В каком регионе наибольшая суммарная выручка?

Path A

Модель пишет SQL

  1. модель импровизирует строку 010304

    Всё, что модель прочитала — сообщение пользователя, извлечённую строку — может повлиять на эту строку.

    запуск 1SELECT region, SUM(total) FROM orders GROUP BY region;запуск 2 · тот же вопросSELECT o.region, SUM(i.amount) FROM orders o LEFT JOIN order_items i ON i.order_id = o.id GROUP BY 1;
  2. ваше подключение исполняет запрос 05

    С полными правами подключения. Чтение, объединение — и, если кто-то не вспомнил про флаг, запись.

ответ

run 1 → east · 2130.50

run 2 → east · 2450.08+15% — раздув при объединении 02

Два запуска, два числа. Оба правдоподобны. Никакого сигнала, какое — если вообще какое-либо — верно.

Path B

Модель подаёт типизированный план

  1. типизированное намерение

    Не строка — значение со схемой. Оно может называть только операции, определённые контрактом.

    { "kind": "query", "version": "1", "source": "revenue", "op": "sum", "group_by": "region" }
  2. проверка контракта

    С хэш-привязкой. Неизвестная операция возвращает unsupported_operation с ближайшими совпадениями — никаких догадок.

  3. проверка политики

    Ваш список разрешений на уровне кода. Запрос может сузить поверхность, но никогда не расширить её.

  4. детерминированное исполнение

    float64, один поток, фиксированная среда выполнения. Один план — одни байты — один ответ.

ответ

east · 2130.50

plan_hash f87610d8afeb…

decision_path "exact_spec"

Один ответ с хэшами для воспроизведения — на следующей неделе, в следующем квартале, на любом из языков.

IVРеестр угроз

Пять способов, которыми генерируемый SQL идёт не так

  1. 01

    P2SQLarXiv 2308.01990

    Инъекция перенесена в выходной канал

    Санитизация входных данных проверяет то, что поступает в модель. P2SQL-атаки приходят в том, что выходит из неё: корректный, вредоносный SQL, собранный из инструкций, скрытых в сообщении пользователя или извлечённой строке. Ни один входной фильтр этого не увидит — атака и есть вывод.

  2. 02

    −15%дашборд, который лгал

    Неверные объединения молча дают сбой

    Раздутое объединение дублирует строки, и выручка оказывается занижена на 15%. Никакого исключения, никакого предупреждения — неверный SQL не падает, он отчитывается. Результат всегда число, а правдоподобное число не несёт никакого сигнала о своей ошибочности.

  3. 03

    1 → nодин вопрос, n запросов

    Один вопрос, разный SQL

    Спросите дважды — и модель может скомпилировать вопрос двумя разными способами, иногда получив два разных ответа. Нет канонического запроса для проверки, кэширования или воспроизведения. Вчерашнее число невозможно воспроизвести — даже просто чтобы сверить.

  4. 04

    91.2 → 21.3% верных · бенчмарк → корпоративная схема

    Обрыв точности

    На чистых бенчмарк-схемах передовая модель писала верный SQL в 91,2% случаев. На реальных корпоративных схемах — 21,3%. В той же волне исследований около 40% запусков text-to-SQL-агентов завершились полным провалом или вернули неверные результаты. Бенчмарки аккуратны. Ваша схема — нет.

  5. 05

    1 prod DBудалена агентом — инцидент Replit

    Путь записи был всегда

    Агент Replit удалил производственную базу данных, несмотря на явный запрет её трогать. Вывод прост: инструкция «только чтение» — это просьба. Если соединение допускает запись, путь записи существует, и рано или поздно неудачная генерация его найдёт. Режим только чтения должен быть свойством инструмента, а не строкой в промпте.

Не фильтруйте вывод.
Не генерируйте его.

Нет SQL-строки — нет инъекции · нет догадок, нет дрейфа

VСертификат

Пять измерений рядом

Не генератор LLM-to-SQLREADME движка

Сертификат различий

поверхность созданиягенерируемый SQLпроизвольная SQL-строкатипизированный плантипизированное версионированное намерение
поверхность исполнениягенерируемый SQLвсё, что допускает соединениетипизированный план4 574 возможности только для чтения
путь записигенерируемый SQLприсутствует, если не заблокировантипизированный планотсутствует по конструкции
управление доступомгенерируемый SQLна уровне промпта, по возможноститипизированный плансписки разрешений на уровне кода, недоступные модели для расширения
воспроизводимостьгенерируемый SQLотсутствуеттипизированный планхеш воспроизведения для каждого результата

правая колонка закреплена контрактомsha256:79f1c5a6…924be9a1

Мелкий шрифт выдерживает проверку: единственный запасной выход движка — getUnsafeRuntime — отсутствует на всех поверхностях, доступных модели, поэтому модель не может до него добраться. README формулирует принцип прямо: это не генератор LLM-to-SQL.

VIВопросы

Из реальной эксплуатации

Как заблокировать DELETE и DROP в SQL, генерируемом LLM?

Не фильтруйте SQL — прекратите его генерировать. Чёрные списки анализируют строки, а модели бесконечно изобретательны в создании новых. SQAI устраняет весь класс проблемы: модель подаёт типизированный план против 4 574 возможностей только для чтения, и ни одной возможности записи для плана не существует.

Что такое P2SQL-инъекция?

Prompt-to-SQL injection: вредоносный SQL в выводе модели, собранный из инструкций, скрытых в прочитанном ею контенте — сообщении пользователя, документе, извлечённой строке. Санитизация входных данных его не видит, потому что атака живёт в канале вывода. Задокументировано в arXiv 2308.01990.

Бывают ли случаи, когда text-to-SQL — правильный выбор?

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

Как дать AI-агенту доступ к базе данных только для чтения?

Сделайте режим только чтения структурным, а не настраиваемым. Флаг только чтения на соединении — это параметр, который можно изменить. Поверхность исполнения SQAI содержит исключительно возможности чтения — путь записи отсутствует по конструкции, и даже запасной выход движка недостижим из любого инструмента, доступного модели.

Чем типизированный план отличается от генерируемого SQL?

SQL-строка может выражать всё, что допускает грамматика. Типизированный план — только то, что определяет контракт. Каждый план проверяется против контракта с хеш-привязкой, сверяется с политикой списка разрешений и исполняется на детерминированном движке — с хешем воспроизведения для каждого результата.

Выберите другой путь.

Без аккаунта. Без ключа. Локальные данные остаются локальными.