vegman.dev
Все статьи

Таблицы - это не RAG

2026-02-05кейс

Вы выгружаете из системы техобслуживания таблицу: судно, узел, статус, критичность. Отдаете ее ИИ-ассистенту и просите разобраться, что чинить первым. Он отвечает абзацем: «Рекомендуется обратить внимание на узлы с высокой критичностью и приоритизировать их обслуживание». Формально не поспоришь. Отправить механику - нельзя.

Дальше почти все идут одной дорогой: «значит, нужен RAG». RAG (retrieval-augmented generation) - это схема, в которой модель перед ответом ищет в вашей базе подходящие куски текста и отвечает уже с ними на руках. На регламентах, инструкциях и переписке она работает прекрасно. На таблице - не работает, и дело не в настройках.

Эта статья про то, как за минуту отличить задачу «найди по смыслу» от задачи «посчитай и сгруппируй», и что строить во втором случае. К концу вы перестанете городить векторный поиск там, где нужны фильтр и группировка.

Быстрый тест: агент работает или красиво разговаривает

У меня есть личный тест на зрелость агента. Агент здесь - это модель, у которой есть инструменты: она может прочитать файл, выполнить код, записать новый файл. Больше, чем окно чата.

Тест такой: дать ему не базу знаний, а таблицу. И попросить не поговорить про данные, а сделать документ, который можно отправить в работу.

Домен я беру учебный, но жизненный: флот, оборудование, техобслуживание. Обычная выгрузка, четыре колонки: судно, узел, статус, критичность. Ничего экзотического - такая таблица есть в любой сервисной службе, просто называется по-разному.

Сценарий укладывается в 15 минут:

  • взять исходный файл только на чтение
  • найти все со статусами «отказ» и «требует обслуживания»
  • сгруппировать по судну
  • собрать таблицу в отдельный файл-отчет
  • в конце дать короткий вывод: что горит первым по критичности.

Дальше просто смотрите, что получилось. Если на выходе текст «рекомендуется обратить внимание» - перед вами собеседник. Если на выходе файл, который можно открыть и раздать людям, - исполнитель. Разница не в красноречии модели, а в том, что она вообще делает с данными.

Задание агенту (15 минут):

Файл «выгрузка.csv» - открывать ТОЛЬКО на чтение.

1. Отобрать строки, где статус = «отказ» или «требует обслуживания».
2. Сгруппировать результат по колонке «судно».
3. Внутри каждой группы отсортировать по критичности.
4. Записать таблицу в НОВЫЙ файл «отчет.csv». Исходник не изменять.
5. В конце - короткий вывод: что горит первым по критичности
   и по какому правилу это решено.

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

Что происходит, когда на входе таблица

Чтобы понять, почему RAG тут мимо, посмотрим на его механику. В основе - векторный поиск: каждый кусочек текста заранее превращают в набор чисел («вектор»), и близкие по смыслу куски оказываются близко друг к другу. Вы спрашиваете - система находит самые похожие фрагменты и отдает их модели.

Главное слово здесь - похожие. Векторный поиск отвечает ровно на один вопрос: «что похоже на мой запрос». К документам это правильный вопрос.

А к таблице задают совсем другие вопросы:

  • сколько
  • у кого больше
  • покажи все за период
  • сгруппируй вот по этой колонке.

Похожие строки не складываются в правильную сумму. «Все узлы в отказе» - это не «десять строк, наиболее похожих на слово отказ», это точное совпадение по колонке, все до единой. Поиск по смыслу вернет вам правдоподобную выборку, и вы даже не заметите, чего в ней нет: пропущенная строка не оставляет следа. В документах неполнота - неприятность. В плане работ неполнота - это узел, который никто не поехал чинить.

Отсюда главный вывод, ради которого все затевалось: когда вход - таблица, агент работает не поисковиком по текстам, а исполнителем маленьких операций над данными. Фильтр. Группировка. Приоритизация. Это не магия и не «понимание» - это отбор и сортировка, которые кто-то должен честно выполнить до последней строки.

flowchart LR
  A["Исходная выгрузка: судно, узел, статус, критичность"] -->|только чтение| B["Фильтр: отказ и требует обслуживания"]
  B --> C["Группировка по судну"]
  C --> D["Сортировка по критичности"]
  D --> E["Новый файл-отчет"]
  E --> F["Короткий вывод: что горит первым"]
Путь данных в таком отчете: чтение, фильтр, группировка, сортировка, новый файл. Векторному поиску тут негде встать

Как выглядит правильное решение

Когда тест проходит, я вижу три вещи - и они важнее любых слов в ответе.

Первое: агент не отвечает, а делает выборку. Он не пересказывает таблицу словами - он ее обрабатывает и упаковывает результат в отчет. Текст в конце есть, но он вторичен: это подпись под таблицей, а не замена ей.

Второе: исходные данные остаются нетронутыми. Исходник открывается только на чтение, результат пишется в новый файл. Это не формальность и не паранойя. Инструмент, который может молча переписать вашу рабочую выгрузку, не получит доверия никогда - и правильно сделает. Один испорченный исходник закрывает тему автоматизации в отделе надолго.

Третье: на выходе план работ, а не список советов. Разница проверяется одним движением: можно ли переслать этот файл человеку, который будет чинить, и он поймет, что делать. «Рекомендуется усилить контроль» переслать нельзя. Отфильтрованную и отсортированную таблицу «судно - узел - статус - критичность» - можно.

Куда это масштабируется дальше

Хорошая новость: от такого прототипа до чего-то серьезного нет пропасти. Все расширение - те же самые операции над данными, просто их становится больше.

  • Правила приоритета. Критично плюс отказ равно красная зона. Правило формулируется одной строкой и дальше применяется ко всем строкам одинаково, без «на мой взгляд».
  • История и тренды. Когда отчетов накопилось несколько, появляется новый вопрос: что ломается чаще. Это снова группировка, только теперь еще и по времени.
  • Регулярный запуск и уведомления. Отчет собирается по расписанию, а ответственный получает не общий дайджест, а свой кусок: вот что горит у вас.

Обратите внимание, чего в этом списке нет. Ни один пункт не требует векторного поиска. Ни один.

Применить у себя

Что проверить на практике

Возьмите час и сделайте это на своих данных - на своих, там вся правда.

  • Выгрузите настоящую таблицу из своей системы и оставьте несколько колонок: объект, элемент, статус, важность. Названия ваши, смысл тот же.
  • Сформулируйте задание как работу с файлами, а не как вопрос. Что прочитать, что отобрать, как сгруппировать, куда записать.
  • Явно напишите два условия: исходный файл - только на чтение, результат - в новый файл.
  • Попросите короткий вывод в конце и обязательно спросите, по какому правилу он получен.
  • Засеките время. Если за 15 минут нет файла, значит, задача сформулирована как беседа, а не как операция над данными.
  • Проверьте руками одну-две группы: откройте исходник, отфильтруйте сами, сравните со строками в отчете. Это скучно и это единственный способ узнать правду.

Как понять, что получилось

Критерий один и он бинарный: получившийся файл можно отправить в работу без переписывания. Не «содержит полезные соображения», а - открыть, прочитать, раздать людям.

Проверяется тремя вопросами:

  • Исходный файл не изменился?
  • Ваша ручная выборка совпала с выборкой агента - ни одной лишней строки, ни одной пропущенной?
  • Вывод в конце опирается на правило, которое вы можете произнести вслух?

Если на все три «да» - у вас не чат-бот, а маленький работающий инструмент. И заметьте, чего вы для этого не собрали: ни векторной базы, ни индекса, ни RAG. Просто потому, что таблица - это не про поиск по смыслу. Это про данные.