TL;DR
Multi-step reasoning в работе с данными — подход, при котором LLM разбивает сложный запрос на этапы: изучает структуру данных, генерирует запрос, проверяет результат, переформулирует при ошибке и выбирает подходящую визуализацию. Вместо одного прямого обращения к данным модель работает итеративно через цикл "план → действие → проверка результата".
Прямая генерация запросов проваливается на трёх типах проблем: семантическое несоответствие (пользователь говорит "прачечные", в данных — "Laundry Service"), сложное временнóе рассуждение (выходные vs будни, праздники, пересечение полуночи) и пространственная семантика (районы и ориентиры отсутствуют в данных). Без механизма адаптации система не может согласовать намерение с реальной структурой данных. При ошибках нет возможности переформулировать или попробовать альтернативный подход.
Multi-step подход добавляет шесть инструментов: изучение схемы данных (структура таблиц и примеры значений), генерация запроса, выполнение и проверка, чтение больших результатов, построение графиков и создание карт. Модель может переформулировать вопрос, используя реальные значения из данных ("ночная жизнь" → Bar + Nightclub + Music Venue), разбить сложный запрос на подзапросы, восстановиться после ошибки и выбрать подходящий формат визуализации. Это цикл: если результат пустой или неверный — модель пробует иначе.
Схема метода
Цикл выполняется до получения корректного результата:
ШАГ 1: Изучить структуру данных
→ Получить названия таблиц, столбцов, примеры значений
ШАГ 2: Спланировать подзадачи
→ Разбить вопрос на этапы, определить какие данные нужны
ШАГ 3: Переформулировать запрос
→ Заменить абстрактные термины на конкретные значения из схемы
ШАГ 4: Сгенерировать запрос
→ Создать SQL/код на основе переформулированного вопроса
ШАГ 5: Выполнить и проверить
→ Запустить запрос, посмотреть на первые строки результата
ШАГ 6 (если ошибка): Адаптировать
→ Расширить поиск (синонимы), добавить внешние данные (границы районов),
попробовать альтернативный подход
ШАГ 7: Визуализировать
→ Выбрать формат (график/карта/таблица) и создать визуализацию
ШАГ 8: Создать текстовое резюме
→ Описать находки структурированным текстом
Все шаги выполняются в одной сессии с сохранением контекста между итерациями.
Пример применения
Задача: Аналитик маркетплейса хочет понять в каких районах Москвы больше всего заказов доставки еды по вечерам, чтобы скорректировать зоны покрытия курьеров.
Промпт:
У меня есть данные о заказах доставки:
- order_id, user_id, restaurant_category, lat, lon, order_time
Вопрос: "Где вечером заказывают больше всего еды?"
Действуй пошагово:
1. Изучи какие категории ресторанов есть в данных
2. Определи что значит "вечером" (18:00-23:00)
3. Определи районы через координаты (я дам границы ЦАО, ЮЗАО, САО если нужно)
4. Посчитай заказы по районам и категориям
5. Построй тепловую карту
6. Дай резюме: какой район лидирует, какие категории популярны
Если данных мало или что-то не найдёшь — расширяй поиск или проси уточнений.
Результат: Модель покажет процесс работы с данными: сначала изучит уникальные значения категорий (найдёт "Пицца", "Суши", "Бургеры" вместо абстрактной "еды"), отфильтрует по времени 18:00-23:00, использует предоставленные границы районов для группировки. Выдаст тепловую карту с концентрацией заказов и текстовое резюме: "ЮЗАО лидирует с 3,247 заказами вечером, пицца составляет 42% всех вечерних заказов в этом районе."
Почему это работает
LLM плохо справляется с данными "в лоб" из-за семантического разрыва. Пользователь спрашивает про "фастфуд", а в данных могут быть категории "Burger Joint", "Quick Service", "Fast Food Chain". Прямой запрос провалится, потому что модель не знает какие именно значения есть в столбце category_name. Добавьте сюда временные нюансы (что делать если вечерний интервал 20:00-02:00 пересекает полночь?) и пространственные (районы не указаны явно) — прямая генерация даёт 28.6% точности.
LLM отлично работает с циклом "действие → наблюдение". Она может посмотреть в данные, увидеть реальные значения, адаптировать запрос. Получила пустой результат по "laundromat"? Посмотрела какие категории содержат "laundry", нашла "Laundry Service", повторила запрос — успех. Это паттерн ReAct (Reasoning + Acting): модель рассуждает над планом, действует через инструменты, наблюдает результат, корректирует.
Многошаговое рассуждение использует сильную сторону (структурирование) для обхода слабости (незнание данных). Вместо угадывания модель узнаёт: "Вот 3 примера строк из таблицы → теперь я вижу формат дат, названия категорий, диапазон координат". Затем генерирует запрос не вслепую, а на основе конкретных примеров. При ошибке — возвращается к изучению данных и пробует иначе. Результат: 91.4% точности.
Рычаги управления:
- Число итераций — для простых задач можно ограничить одним проходом (быстрее, дешевле), для сложных разрешить до 3-5 попыток
- Глубина изучения схемы — показывать только названия столбцов или включить примеры значений и их статистику (больше контекста = точнее, но дороже)
- Условия остановки — определить когда результат "достаточно хорош" (например, >10 найденных записей) или когда прекратить попытки
- Источники внешних данных — добавить справочники (праздничные даты, границы районов, координаты ориентиров) или работать только с тем что есть в таблице
Шаблон промпта
У меня есть данные: {описание_структуры_данных}
Вопрос: "{вопрос_пользователя}"
Работай пошагово:
1. Изучи структуру данных (названия столбцов, примеры значений)
2. Определи какие конкретные значения соответствуют терминам из вопроса
3. Спланируй: нужна одна операция или несколько подзадач?
4. Сформулируй запрос используя КОНКРЕТНЫЕ значения из данных
5. Выполни и проверь результат
6. Если результат пустой/неверный — попробуй:
- Синонимы и похожие значения
- Расширить фильтры (убрать часть условий)
- Добавить внешнюю информацию если доступна
7. Выбери формат визуализации (график для временных рядов, карта для координат, таблица для категорий)
8. Дай краткое резюме с ключевыми находками
При ошибках — объясни что пошло не так и как адаптируешь подход.
Что подставлять:
{описание_структуры_данных}— названия таблиц/файлов, столбцов, примеры значений (2-3 строки){вопрос_пользователя}— вопрос на естественном языке
Для данных в формате CSV/Excel добавь:
Данные загружены в формате CSV. Первые 3 строки:
[вставь примеры строк]
Столбцы: {список_столбцов}
Ограничения
⚠️ Требует доступ к данным: Метод работает когда LLM может читать и выполнять запросы к данным. В ChatGPT это Data Analysis mode / Code Interpreter, в Claude — загруженные файлы или Code Execution. Без доступа к данным остаётся только теоретическое планирование.
⚠️ Больше запросов = выше стоимость: Агентский подход делает в среднем 1.5 запроса вместо одного у прямой генерации. Для больших датасетов или частых итераций это увеличивает время и расход токенов на 50%.
⚠️ Сложные пространственные запросы: Проваливается на задачах с точными геометрическими расчётами (расстояние от точки, пересечение полигонов) без специальных библиотек. Пример: "найти все точки в радиусе 5 км от Красной площади" не сработает если модель пытается вычислить расстояние арифметически вместо использования географических функций.
⚠️ Галлюцинации при многотабличном синтезе: На сложных запросах типа "сравни выходные в Москве vs Питере" модель может предложить логически неверную комбинацию двух таблиц, несмотря на доступ к схеме. Частично решается явным указанием как объединять датасеты.
Как исследовали
Исследователи взяли 227,428 чекинов в Нью-Йорке и 573,703 в Токио из публичного датасета локационных соцсетей. Каждая запись содержит: user_id, место, координаты, категорию заведения, время. Данные загрузили в PostgreSQL без геопространственных расширений (без PostGIS) — чистая табличная БД с координатами как числами.
Придумали 35 вопросов на естественном языке, покрывающих разные типы сложности: простая фильтрация ("покажи чекины на вокзалах"), агрегация ("топ-10 мест"), временной анализ ("пики активности по часам дня"), многошаговое рассуждение ("для топ-5 категорий построй тренд по месяцам"), пространственные запросы ("сравни активность в Бруклине vs Квинсе"), инъекция внешних данных ("чекины в День благодарения"), сравнение городов ("Нью-Йорк vs Токио по ночной активности").
Тестировали два подхода с одной и той же моделью генерации SQL (llama-3-sqlcoder-8b):
- Naive pipeline: Вопрос → одна генерация SQL → выполнение → таблица результата
- Agent pipeline: ReAct-агент (Mistral Large) с инструментами: изучение схемы, генерация SQL (тот же sqlcoder), выполнение, чтение файлов, построение графиков, создание карт
Почему получились такие результаты: Naive подход завалил почти всё кроме простейших фильтров. Причина — модель генерирует SQL вслепую, без знания какие категории реально есть в данных. Спросили про "laundromats" (прачечные) — модель написала WHERE category = 'laundromat', а в данных это называется "Laundry Service". Результат: пустая выборка, ошибка. Агент же сначала посмотрел в данные, нашёл что категории записаны как "Laundry Service", переформулировал запрос — успех.
Что удивило: Разница оказалась драматической. При том что обе системы используют одну модель SQL-генерации, агентский подход выдал 91.4% vs 28.6% точности. Это показывает что оркестрация важнее мощности модели. Улучшение пришло не от более сильной модели, а от возможности планировать, проверять и адаптироваться.
Инсайт для практики: Naive pipeline полностью провалился (0%) на всех запросах требующих: пространственного рассуждения (районы, ориентиры), внешних знаний (праздники, границы районов), многотабличного синтеза. Агент справился с ними в 80-100% случаев. Вывод: для реальных аналитических задач недостаточно просто "спросить SQL у LLM". Нужна итеративная работа с обратной связью — именно это дают инструменты и планирование.
Адаптации и экстраполяции
💡 Адаптация для анализа продаж маркетплейса
Те же принципы работают для анализа коммерческих данных. Вместо чекинов в заведениях — заказы на маркетплейсе.
У меня данные о заказах: order_id, user_id, product_category, region, order_time, price
Вопрос: "В каких регионах люди чаще покупают технику в предновогоднюю неделю?"
Пошагово:
1. Изучи уникальные значения product_category — найди что относится к "технике"
2. Определи "предновогоднюю неделю" (24-31 декабря)
3. Посчитай заказы по регионам для этих категорий в этот период
4. Построй столбчатую диаграмму
5. Дай топ-3 региона с процентным вкладом
Если категории размыты — группируй похожие (например, "Смартфоны", "Ноутбуки", "Наушники" → все "техника").
Отличие от оригинала: вместо географических координат — регионы как категория, вместо мест — товары. Логика та же: изучить данные → переформулировать → запросить → визуализировать.
💡 Адаптация для анализа кликов по сайту
Применимо для веб-аналитики с данными событий (event tracking).
Логи событий: user_id, event_type, page_url, timestamp, device_type
Вопрос: "Когда пользователи чаще всего кликают на кнопку оформления заказа?"
План:
1. Найди все event_type содержащие "checkout" или "order" (точное название узнаю из данных)
2. Извлеки час дня из timestamp
3. Посчитай события по часам
4. Построй линейный график
5. Выдели пиковые часы (топ-3) и минимумы активности
Если данных мало в какие-то часы — покажи это явно, не скрывай.
🔧 Техника: добавить промежуточные результаты → видеть процесс мышления
Оригинальный агент работает "под капотом", показывая только итог. Можно модифицировать чтобы видеть ход рассуждений:
На каждом шаге выводи:
- Что делаю сейчас
- Что нашёл в данных
- Какое решение принял
- Почему выбрал этот подход
Пример формата:
[ШАГ 1] Изучаю структуру → Нашёл столбцы: category_name с 47 уникальными значениями
[ШАГ 2] "Ночная жизнь" не точный термин → Ищу похожие категории → Нашёл: Bar (12%), Nightclub (8%), Music Venue (3%)
[ШАГ 3] Генерирую запрос с WHERE category_name IN ('Bar', 'Nightclub', 'Music Venue')
[ШАГ 4] Результат: 4,523 записи → Успешно → Строю график
Это особенно полезно для обучения — видишь КАК модель приходит к решению, не только ЧТО получилось.
🔧 Техника: кэширование схемы → снижение стоимости
Если работаете с одним датасетом многократно:
[ОДИН РАЗ в начале сессии]
Изучи структуру данных и сохрани:
- Названия всех столбцов с типами данных
- Примеры уникальных значений для категориальных полей
- Диапазоны для числовых полей (min/max)
- Формат дат
[ПОТОМ для каждого вопроса]
Используй сохранённую схему, не изучай заново.
Обращайся к данным только для выполнения запроса.
Это сокращает число обращений к данным с 1.5 до ~1.1 на запрос (изучение схемы делается один раз, не при каждом вопросе).
🔧 Техника: явные условия остановки → контроль качества
Добавьте критерии "достаточно хорошо":
Критерии успешного результата:
- Найдено минимум 10 записей (если меньше — расширь поиск)
- Результат покрывает >80% запрошенного периода (если меньше — проверь фильтры по времени)
- Нет пустых/NULL значений в ключевых полях (если есть — исключи или обработай)
Если за 3 попытки не достиг критериев — объясни почему и что можешь предложить вместо этого.
Это предотвращает ситуацию когда модель возвращает технически корректный, но практически бесполезный результат (например, 2 записи из миллионов).
Ресурсы
From Queries to Insights: Agentic LLM Pipelines for Spatio-Temporal Text-to-SQL
Manu Redd, Tao Zhe, Dongjie Wang
University of Kansas
GeoGenAgent Workshop 2025
Датасет: NYC and Tokyo LBSN Check-in Dataset (Yang et al., 2015)
Ключевые технологии: ReAct framework (Yao et al., 2023), LangGraph, SQLCoder (Defog AI)
Бенчмарк: Spider dataset (Yu et al., 2018) — стандарт для text-to-SQL задач
