CNN Türkİstanbul’da FETÖ operasyonu: 19 şüpheli gözaltına alındıBollywood HungamaBigg Boss 20: Qazi Touqeer recalls being labelled “arrogant” after turning down Ekta Kapoor’s TV offer in 2005: “Main chhota tha, 20 saal ka…”PunchWorld Anaesthesia Day: Doctors call for better equipment, fundingDaily MaverickWORLD FOOD DAY EDITORIAL: Hungry by design: hunger must be on the ballot on 4 NovemberRTP DesportoLiga Europa. Benfica goleia Celtic por 4-1The Jerusalem Post'We'll knock it out fast': Trump threatens Iran's Pickaxe Mountain nuclear site with strikesInquirer3 dead, 1 wounded in Negros Oriental town shootingESPNTransfer rumors, news: Arsenal eye January move for Bayern Munich defenderInquirer EntertainmentAl Pacino to get lifetime achievement award from the Screen Actors GuildZDF heuteSo haben sich die Mieten in Ihrer Region entwickeltUOLEm sabatina, Lula dá guinada sobre redução da maioridade penalSky TG24Elezioni Usa Midterm, Anthropic integra chatbot Claude contro le fake news
The Daily Newsstand · Free, Always
Friday, October 16, 2026

Выручка за сентябрь: как AI‑агент получает три разных ответа

Translate

Всем привет, меня зовут Сергей Прощаев, я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech & E‑commerce и преподаю на курсах разработки и архитектуры в ОТУС.

В этой статье расскажу, почему AI‑агент, который блестяще отвечает на вопросы по демо‑базе, начинает путаться на настоящем хранилище данных, и что с этим может сделать аналитик ещё до выбора модели.

Знакомая картина.

На демо вендор открывает чат, пишет «покажи выручку за сентябрь по регионам», и через пять секунд на экране таблица и красивый график. Пилот согласован. Через месяц агента подключают к рабочему хранилищу, финансовый директор задаёт тот же вопрос и получает число, которое не совпадает ни с отчётом бухгалтерии, ни с дашбордом продаж. Переформулирует вопрос — получает третье.

Модель здесь обычно не главная проблема. Она хорошо пишет SQL там, где задача уже формализована.

В корпоративном хранилище часть этой формализации живёт вне схемы: в определениях метрик, в кардинальности связей, в терминах компании и в том, по какой дате принято резать период.

Если этот контекст не дан машине явно, модель восстанавливает его наугад.

Рис. 1. На учебной схеме агент легко находит ответ, а на реальном хранилище может получить несколько правдоподобных вариантов

Рис. 1. На учебной схеме агент легко находит ответ, а на реальном хранилище может получить несколько правдоподобных вариантов

От 91% до нуля: почему цифры бенчмарков не переносятся на ваше хранилище

Задача, о которой пойдёт речь, называется enterprise text‑to‑SQL — генерация SQL по вопросу на естественном языке поверх корпоративного хранилища.

Я посмотрел на неё через три работы разных команд. Сразу оговорюсь: в одну шкалу эти цифры не складываются, у исследований разные данные, модели и протоколы.

Но тенденция одна: переход от открытых учебных данных к закрытым корпоративным резко усложняет задачу.

  • Первая — бенчмарк Spider 2.0. В версии, опубликованной на ICLR 2025, авторы собрали 632 задачи из реальных корпоративных сценариев: базы на BigQuery и Snowflake, нередко больше тысячи колонок, несколько диалектов SQL. Их агент на модели o1-preview решил 21,3% задач, тогда как на учебном Spider 1.0 — 91,2%, на BIRD — 73,0%. На 69,9 процентного пункта ниже, примерно в 4,3 раза.

Честности ради: исходный вариант бенчмарка с тех пор убрали, а на новом Spider 2.0-Snow (547 задач на Snowflake) лучшие агентные системы уже выше 90%. Так что 21,3% — не потолок, а снимок конца 2024 года.

  • Вторая — бенчмарк BEAVER. Его авторы взяли запросы не у студентов, а из логов закрытых корпоративных хранилищ: 9 128 пар «вопрос — SQL», 812 таблиц, 19 предметных областей. В среднем запрос затрагивает 4 таблицы и содержит 5,7 соединения, а заодно CTE, вложенные запросы и аналитические функции. Базовый агентный фреймворк ReFoRCE на GPT-5.2 показывает здесь 10,8%, на Claude 4.5 Sonnet — 11,4%.

Самое интересное в BEAVER — опыт с подсказками. Авторы делят задачу на пять подзадач: найти нужные таблицы, определить ключи соединения, сопоставить колонки, извлечь знание предметной области и разложить вопрос на шаги.

В среднем по моделям точность без подсказок — 9,5%. Подсказки по трём подзадачам схемы (таблицы, ключи, колонки) поднимают её до 18,9%, все пять — до 25,9%.

Цифра 30,1% из аннотации авторов получена в другом разрезе, в одну цепочку с этими её ставить не стоит.

И даже с полным набором подсказок ошибки остаются: 46,8% из них структурные (группировки, сортировки, сложные функции), 35,2% — снова выбор элементов схемы, 18,0% — фильтры.

  • Третья — статья Майкла Стоунбрейкера и Питера Чена в Communications of the ACM от 23 сентября 2026 года. Стоунбрейкер руководил проектом POSTGRES и получил премию Тьюринга, так что в нелюбви к базам данных его не заподозришь.

    По их наблюдению, «чистая» LLM на BEAVER набрала ноль, RAG, промпт‑инжиниринг и агенты подняли результат примерно до 10%, а передача модели нужных таблиц и условий соединения — примерно до 30%. По словам авторов, это разница между «у технологии есть потенциал» и «технология не работает».

Меня в этих цифрах зацепила пропорция.

Подсказки о схеме и связях дают заметный прирост, хотя и не закрывают задачу целиком. Значит, один из главных дефицитов здесь — не столько умение писать SQL, сколько умение связать вопрос с конкретными данными, бизнес‑правилами и структурой запроса.

А это и есть работа аналитика.

История из первоисточника: хранилище, которое знает про J‑Term

В той же статье есть история, которую я бы показывал на каждом пилоте AI‑аналитики.

Команда Стоунбрейкера два года пробовала text‑to‑SQL на настоящих хранилищах. Начали с административного хранилища MIT: Oracle, больше 1 400 таблиц, к которому ходят многие подразделения университета.

Исследователи взяли реальные запросы из лога Oracle и вместе с пользователями восстановили, какой вопрос стоял за каждым.

Авторы называют четыре проблемы, которых почти нет в учебных бенчмарках:

  1. Учебные данные лежат в открытом доступе, и модели могли их видеть при обучении. Корпоративные хранилища закрыты.

  2. Схема «гниёт». Бизнес меняется, компания покупает и продаёт подразделения, приходят требования регулятора. Стоунбрейкер приводит пример: в разных таблицах оказывается шесть колонок «salary», и одна означает сумму на руки, а другая — до вычетов.

  3. У каждого хранилища свой словарь. В данных MIT встречается J‑Term — месячный учебный период в январе, а здания там не названы, а пронумерованы. Из схемы этого не вывести.

  4. Реальные запросы сложнее учебных: по наблюдению авторов, им обычно нужны два‑три соединения, а в BEAVER в среднем уже 5,7.

Помню, как на одном из проектов у меня была похожая ситуация, только без всякого AI. Три отчёта о выручке за один месяц расходились, и каждый автор был уверен в своей цифре.

Ушло несколько дней, чтобы выяснить: один считал по дате заказа, второй — по дате оплаты, третий забыл про возвраты.

Ни одна из команд не ошибалась в SQL. Они по‑разному понимали слово «выручка».

Эксперимент: три запроса на один вопрос

Чтобы не рассуждать вокруг темы, я собрал учебную схему интернет‑магазина в SQLite 3 и сгенерировал данные с фиксированным seed: 1 000 заказов с конца августа по конец сентября.

Типы намеренно упрощены: суммы — целые рубли, даты — строки вида ГГГГ‑ММ‑ДД. Часть заказов отменена, часть ждёт оплаты, 165 заказов оплачены двумя платежами, по 42 есть возвраты.

Всё, что ниже, можно повторить у себя: схема, данные, запросы и разбор ошибок лежат в репозитории text‑to‑sql‑dwh‑demo на GitHub, ссылка в конце статьи.

Команда ./run.sh собирает базу с нуля, печатает результаты и сверяет их с эталоном, а CI на каждый push проверяет, что данные воспроизводятся байт в байт. Нужен только sqlite3.

CREATE TABLE orders (
  order_id    INTEGER PRIMARY KEY,
  customer_id INTEGER,
  created_at  TEXT,      -- дата создания заказа
  status      TEXT,      -- completed / pending / cancelled
  amount      INTEGER    -- сумма заказа, рубли
);

CREATE TABLE payments (
  payment_id INTEGER PRIMARY KEY,
  order_id   INTEGER,    -- связь с заказом не объявлена внешним ключом
  paid_at    TEXT,
  amount     INTEGER
);

CREATE TABLE refunds (
  refund_id   INTEGER PRIMARY KEY,
  order_id    INTEGER,
  refunded_at TEXT,
  amount      INTEGER
);

Вопрос бизнеса: «Какая выручка за сентябрь?». Ниже три запроса. Каждый из них я видел в живых отчётах, и каждый правдоподобно мог бы сгенерировать агент, глядя только на схему.

Запрос A — «самый очевидный»: сумма заказов, созданных в сентябре. Зерно — заказ.

SELECT SUM(amount)
FROM orders
WHERE created_at >= '2026-09-01'
  AND created_at <  '2026-10-01';

Запрос B — «аккуратный». Агент решает: раз показатель связан с оплатой, нужно присоединить payments, а отменённые заказы отбросить.

SELECT SUM(o.amount)
FROM orders o
JOIN payments p ON p.order_id = o.order_id
WHERE o.status = 'completed'
  AND o.created_at >= '2026-09-01'
  AND o.created_at <  '2026-10-01';

Запрос C — другая бизнес‑договорённость: чистые поступления денег. Деньги, пришедшие в сентябре, минус деньги, возвращённые в сентябре.

Я специально не называю это универсальной «выручкой»: в другой компании под выручкой может пониматься сумма отгрузок без НДС — в зависимости от принятой методологии учёта.

SELECT
  COALESCE((SELECT SUM(amount) FROM payments
            WHERE paid_at >= '2026-09-01' AND paid_at < '2026-10-01'), 0)
  -
  COALESCE((SELECT SUM(amount) FROM refunds
            WHERE refunded_at >= '2026-09-01' AND refunded_at < '2026-10-01'), 0)
  AS net_cash_collected;

Результаты на одних и тех же данных:

Запрос

Что считает

Результат

Отклонение от C

A

все заказы сентября по дате создания

4 465 500

+23,6%

B

завершённые заказы, соединённые с платежами

4 623 500

+28,0%

C

чистые поступления по дате движения денег

3 613 500

—

Самое показательное — запрос B.

Он выглядит строже A: отменённые заказы отфильтрованы, а результат получился больше. Проблем у него две, и обе независимы.

  • Первая — соединение. У payments другое зерно: одна строка — один платёж. Само размножение строк ещё не ошибка, ошибка в том, что после него суммируется o.amount — мера уровня заказа. Заказ на 20 000, оплаченный двумя платежами по 10 000, после join становится двумя строками, и SUM(o.amount) даёт 40 000. В моих данных так задвоились 138 сентябрьских заказов.

  • Вторая — время. Запрос задуман «про оплаты», а фильтр стоит по дате заказа: 44 заказа, созданные в сентябре, оплачены уже в октябре и всё равно попали в сумму.

Оба счётчика считает diagnostics.sql в репозитории.

Все три запроса синтаксически корректны и выполняются без ошибок. Различаются они не SQL, а семантикой: какое событие считается основанием для показателя, какое зерно допустимо и какие операции входят в расчёт. Ничего этого в схеме нет.

Пять наблюдений

  1. Первое: модель промахивается не в синтаксисе, а в смысле. Проверкой «запрос отработал» такую ошибку не поймать, её видно только при сверке с эталоном.

  2. Второе: самые дорогие ошибки сидят в соединениях. Неявная связь один‑ко‑многим тихо размножает строки. Внешних ключей в хранилищах часто нет, и модели приходится угадывать связь по совпадению названий колонок.

  3. Третье: словарь компании не выводится из схемы. «Сентябрь» может быть календарным или фискальным, «Москва» — городом доставки, складом или юрлицом. Модель может узнать это из документации, каталога или логов запросов, если этот источник доступен системе и попадает в её контекст.

  4. Четвёртое: учебные бенчмарки завышают ожидания. Данные из них могли попасть в обучение, и даже современные публичные бенчмарки не воспроизводят целиком сочетание закрытых данных, корпоративного словаря и сложности рабочих запросов. Цифра из презентации вендора ничего не говорит о точности на вашем хранилище.

  5. Пятое: контекст о данных даёт заметный прирост, но не всё. В BEAVER подсказки по схеме почти удваивают точность. Ещё в 2023 году Секеда и коллеги из data.world получили похожую картину: GPT-4 отвечала на вопросы к корпоративной SQL‑базе с точностью 16%, а через граф знаний с онтологией и маппингами — 54%. При этом структурные ошибки остаются и с подсказками.

Что помогает: вынести часть смысла в машинно‑читаемую модель

Из пятого наблюдения следует подход, который сейчас обсуждают почти все, кто строит AI‑аналитику, — семантический слой.

Это описание данных на уровне бизнеса: сущности, связи и их кардинальность, зерно таблиц, определение каждой метрики.

В такой архитектуре агент выбирает из описанных метрик и измерений, а SQL строит движок слоя по записанным правилам.

Документация dbt прямо говорит, что MetricFlow знает типы ключей сущностей и поэтому избегает fan‑out и chasm join — ровно той ошибки, на которой споткнулся запрос B.

Отдельный рыночный сигнал дают опросы.

В исследовании Futurum Research среди более чем 800 руководителей по данным 44,5% планируют увеличить расходы на семантический слой в ближайшие 24 месяца, ещё 14,4% собираются его внедрить впервые.

Вот как выглядит метрика из запроса C в актуальной спецификации dbt Semantic Layer:

models:
  - name: fct_payments
    description: "Одна строка — один платёж. На один заказ бывает несколько платежей."
    semantic_model:
      enabled: true
    agg_time_dimension: paid_at
    columns:
      - name: payment_id
        entity: {type: primary, name: payment}
      - name: order_id
        entity: {type: foreign, name: order}
      - name: paid_at
        granularity: day
        dimension: {type: time}
    metrics:
      - name: paid
        label: Поступило денег
        type: simple
        agg: sum
        expr: amount

  - name: fct_refunds
    description: "Одна строка — один возврат."
    semantic_model:
      enabled: true
    agg_time_dimension: refunded_at
    columns:
      - name: refund_id
        entity: {type: primary, name: refund}
      - name: order_id
        entity: {type: foreign, name: order}
      - name: refunded_at
        granularity: day
        dimension: {type: time}
    metrics:
      - name: refunded
        label: Возвращено денег
        type: simple
        agg: sum
        expr: amount

metrics:
  - name: net_cash_collected
    label: Чистые поступления
    description: >
      Деньги, поступившие за период, минус возвраты за тот же период.
      Дата — дата движения денег, а не дата заказа.
    type: derived
    expr: paid - refunded
    input_metrics:
      - name: paid
      - name: refunded

Обратите внимание на время. У каждой простой метрики своя дата агрегации: paid считается по paid_at, refunded — по refunded_at.

При запросе за сентябрь слой режет каждую по её собственной дате, и именно это решение в запросе B никто не принимал.

В description задокументированы зерно таблицы и определение показателя, для человека и для агента, а машинная часть кардинальности задаётся через entities.

Для простоты показан расчёт общей метрики по времени: чтобы группировать её по клиенту или региону, нужные сущности и пути соединения тоже придётся описать.

Не менее важно, что должен делать агент, если термина в слое нет. Если термин не определён или допускает несколько толкований, правильное поведение агента — не угадывать, а уточнить: «Считать по поступлению денег или по отгрузке?».

Для финансовой аналитики это важнее любой точности.

На рисунке 2 показаны пути вопроса к хранилищу: напрямую через схему и через описанный слой.

Рис. 2. Без описанного смысла агент угадывает, с ним — выбирает из записанного или переспрашивает

Рис. 2. Без описанного смысла агент угадывает, с ним — выбирает из записанного или переспрашивает

Главная мысль схемы: семантический слой не делает модель умнее. Он переносит знание о кардинальности, допустимых соединениях и определениях метрик из догадки модели в описание, которое можно проверить. А там, где описания нет, честнее спросить, чем выдать число.

Ограничения: где это не сработает

Семантический слой — не серебряная пуля.

  • Во‑первых, он не заменяет моделирование данных. dbt строит его поверх подготовленных моделей: если исходный слой запутан, сначала придётся собрать аналитические витрины, а уже на них фиксировать смысл. И кто‑то должен поддерживать описания: без этого слой гниёт так же, как хранилище, только незаметнее.

  • Во‑вторых, слой закрывает повторяющиеся вопросы про описанные метрики. Если нужной метрики в слое нет, системе нужен другой источник контекста: каталог, документация, примеры запросов. Без него агент снова восстанавливает смысл наугад.

И наконец, мой эксперимент демонстрирует механику ошибки, а не оценивает её вероятность в продакшене.

Плюс 23,6% и 28,0% — свойство моих синтетических данных, а не типичная погрешность. YAML выше — иллюстрация подхода: он лежит в репозитории рядом с запросами, но компиляция через dbt там не проверяется.

Что проверить у себя за вечер

Если вы планируете пилот AI‑аналитики или уже его ведёте, я бы начал не с выбора модели, а с такой проверки:

  1. Выпишите 10–15 вопросов, которые бизнес задаёт чаще всего, и для каждого — эталонный SQL, согласованный с владельцем метрики.

  2. Прогоните вопросы через агента и сравните результат, затем SQL и объяснение: какие метрики, таблицы, фильтры и даты он взял. Совпадение числа — необходимый сигнал, но не доказательство: две разные ошибки могут случайно дать одно число.

  3. Для каждой таблицы, которая участвует в ответах, запишите зерно: одна строка — это заказ, платёж или позиция заказа.

  4. Составьте словарь терминов компании: что такое выручка, активный клиент, регион, месяц.

  5. Опишите пять самых спрашиваемых метрик в семантическом слое и повторите шаг 2.

  6. Задайте агенту вопрос с термином, которого нет в словаре, и посмотрите: он переспросит или уверенно ответит.

Для разминки подойдёт и мой репозиторий: три таблицы и три вопроса, на которых видно, ошибётся ли ваш агент на соединении и на дате.

Мой вариант, который я обычно советую: шаги 1 и 2 сделать до разговора с вендором. Тогда на демо вы проверяете не красивый график, а свои пятнадцать вопросов.

Вывод

AI‑агенты сделали SQL дешёвым. Дорогим осталось другое — договориться о том, что значат данные, и записать это так, чтобы прочитала машина. Enterprise text‑to‑SQL — не один шаг генерации SQL, а цепочка разрешения контекста: какие данные нужны, как они связаны, что значат термины, по какой дате считать и какую структуру запроса построить. Часть этого контекста традиционно живёт в голове аналитика.

Поэтому, как мне кажется, роль аналитика с приходом агентов не уменьшается, а смещается: от написания каждого запроса к формализации смысла, на котором эти запросы строятся.

А как у вас: пробовали подключать AI‑агента к рабочему хранилищу? На чём он ошибался чаще всего — на соединениях, на терминах или на датах? Буду рад обсудить в комментариях.

Ссылка на мой репозиторий с экспериментом.

ИСТОЧНИКИ

Как интегрировать ИИ‑агентов с корпоративными системами и оценивать качество их работы?

Эти вопросы разберём на бесплатных демо-уроках OTUS:

Больше тем об искусственном интеллекте, разработке и работе с данными — в октябьском дайджесте.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.