← Все статьи

AI-аналитик без SQL: DuckDB, LLM и трёхэтапный пайплайн

Вопрос на естественном языке → SQL через LLM, DuckDB in-process, три стадии и read-only guardrails для безопасности.

Содержание

Коротко

Команда задаёт вопрос на естественном языке, LLM генерирует SQL, DuckDB выполняет запрос in-process — пользователь видит только ответ. Архитектура из трёх стадий (контекст, генерация, выполнение) и read-only guardrails снимает узкое место «единственный человек, который знает SQL».

Что произошло

Типичная боль: маркетинг и операции ждут дашборд или тикет, хотя данные уже есть в CSV/Parquet из HubSpot, Stripe или ERP. Узкое место — не база, а перевод бизнес-вопроса в запрос.

DuckDB здесь уместен: работает in-process, без отдельного сервера, сразу читает CSV, Parquet и JSON как таблицы. Экспорты, которые команда уже кладёт на диск, становятся queryable без миграции.

Между вопросом и DuckDB стоит reasoning-модель. Ей нужен контекст схемы: имена колонок, типы, несколько sample rows — всё это попадает в system prompt до генерации SQL.

UI — Streamlit (~30 строк Python): поле ввода и таблица результата. Тот же пайплайн можно повесить на Telegram webhook, чтобы отвечать прямо в чате.

Автор выделяет три явные стадии:

  1. Context loading — при старте читается файл, выводятся типы, собирается metadata block для каждого промпта.
  2. Query generation — вопрос + metadata → LLM → SQL-строка. Без выполнения: сначала валидация — только существующие колонки, без write/delete, синтаксис корректен.
  3. Execution and formatting — DuckDB выполняет проверенный запрос, результат форматируется в таблицу или текст (для Telegram — message-safe string).

Разделение стадий позволяет тестировать генерацию и execution независимо — урок из production-пайплайнов, где flat-архитектура ломалась при росте нагрузки.

Почему это важно

Natural language analytics снижает барьер для BI: нетехнические пользователи получают insights без SQL. Но надёжность определяют не Streamlit и не выбор модели, а prompt design, validation и metadata.

Ключевые ограничения:

  • Metadata injection работает до ~50 колонок; дальше контекст давит на token limit — нужен отбор релевантных полей.
  • System prompt должен требовать только SQL, без markdown и комментариев — иначе ломается валидация. One-shot example в prompt сильно снижает malformed output.
  • Telegram round-trip — 3–8 секунд; для простых агрегаций дашборд быстрее, для непредсказуемых вопросов — оправдано.
  • Security: динамический SQL требует read-only connections, allowlisting и лимитов на размер выдачи — иначе риск при exposure вне команды.

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

На практике

Если собираете такой agent поверх flat files:

  1. Validation layer первым — не подключайте LLM output напрямую к DuckDB; проверяйте column refs по metadata до execution.
  2. Генерируйте metadata block в runtime из актуального файла, не хардкодьте в prompt.
  3. Добавьте toggle «показать SQL» — non-technical users смогут аудировать интерпретацию вопроса.
  4. Свяжите с n8n или другим ETL: agent становится read-слоем над тем, что пайплайны уже пишут на диск.

Объём кода скромный (~25 строк UI, ~15 DuckDB, ~30 LLM+validation), но время уходит на prompt engineering и guards — туда и вкладывайтесь.

Итог

AI data analyst без SQL — практичная реализация NL→SQL поверх DuckDB с жёстким разделением стадий и read-only безопасностью. Имеет смысл читать оригинал, если хотите дать команде ad-hoc analytics без очереди к единственному аналитику.