Содержание
Коротко
Команда задаёт вопрос на естественном языке, 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, чтобы отвечать прямо в чате.
Автор выделяет три явные стадии:
- Context loading — при старте читается файл, выводятся типы, собирается metadata block для каждого промпта.
- Query generation — вопрос + metadata → LLM → SQL-строка. Без выполнения: сначала валидация — только существующие колонки, без write/delete, синтаксис корректен.
- 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:
- Validation layer первым — не подключайте LLM output напрямую к DuckDB; проверяйте column refs по metadata до execution.
- Генерируйте metadata block в runtime из актуального файла, не хардкодьте в prompt.
- Добавьте toggle «показать SQL» — non-technical users смогут аудировать интерпретацию вопроса.
- Свяжите с 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 без очереди к единственному аналитику.