TL;DR
Semantic Atoms — это два «кирпичика» для анализа таблиц с текстом: разметка (Tagging) и выделение категорий (Categorization). Разметка получает N текстов и возвращает N значений, то есть новую колонку. Выделение категорий получает N текстов и возвращает M категорий, то есть справочник тем. Всё «смысловое» делает LLM, а сортировку, фильтры, средние и регрессию делает обычный код по готовой колонке.
Типичная боль: просишь агента «отсортируй жалобы по раздражению клиента и найди главную тему каждой». Он делает это отдельными вызовами, и каждый возвращает только итог. Сортировка выдаёт порядок, но без самих оценок. Когда следующему шагу нужна колонка «раздражение», модель оценивает всё заново. Оценки получаются другими, порядок и регрессия расходятся, а токены тратятся дважды. Причина в том, что промежуточный результат нигде не сохранили: модель его «держала в голове» и не записала.
Метод простой: каждый смысловой шаг записывает результат в явное место. Оценка раздражения 1–10 по каждой строке становится колонкой, и сортировка с регрессией берут именно её. Для тем действуют два шага: сначала categorize находит общий список тем, потом tag присваивает каждой строке тему из этого списка. Если строк тысячи, нарезка на пачки и сборка идут внутри инструмента, а агент ничего про это не знает.
Схема метода
ШАГ 1 (разметка): tag(тексты, "оцени раздражение 1–10") → колонка из N значений
ШАГ 2 (категории): categorize(тексты, "главные темы жалоб, до 8") → таблица из M категорий
ШАГ 3 (назначение): tag(тексты, "выбери тему из списка {темы}") → колонка из N значений
ШАГ 4 (точный счёт): сортировка / группировка / регрессия — кодом, по готовым колонкам
Правило: каждый смысловой вызов → результат сохранён и доступен следующим шагам.
Шаги 1–3 — разные запросы к модели, шаг 4 — Python/SQL/Excel-формулы.
Пример применения
Задача: Вы руководите качеством сервиса пунктов выдачи Wildberries в трёх городах. В выгрузке 3 000 отзывов: текст, оценка, город, срок ожидания заказа. Нужно понять, от чего люди злятся и где хуже всего, а ещё проверить, растёт ли раздражение с ожиданием.
Промпт (агенту с анализом данных: Claude Code, ChatGPT с Data Analysis, Cursor):
У меня файл reviews.xlsx: колонки «текст», «город», «дней_ожидания», «оценка».
Работай по правилам «семантических атомов»:
1. Смысловую работу над текстом делай только через два типа шагов:
- TAG: на вход N отзывов, на выходе ровно N значений (по одному на отзыв, в том же порядке). Сохраняй результат НОВОЙ КОЛОНКОЙ в таблице.
- CATEGORIZE: на вход N отзывов, на выходе список из M категорий (название + короткое описание). Сохраняй как ОТДЕЛЬНУЮ ТАБЛИЦУ.
2. Сортировку, группировку, средние и регрессию делай кодом по готовым колонкам. Не проси модель «отсортировать» или «посчитать».
3. Не пересчитывай уже размеченное: если колонка есть, используй её.
План:
- TAG «раздражение»: оцени от 1 до 10, где 1 — спокоен, 10 — крайне раздражён.
- CATEGORIZE: выдели до 8 главных тем жалоб.
- TAG «тема»: для каждого отзыва выбери ровно одну тему из полученного списка (или «другое»).
- Затем кодом: среднее раздражение по городам и темам, регрессия раздражения на дни ожидания и тему.
Если отзывов много — разбей на пачки по 100 с идентификатором строки и собери результат по идентификатору. Покажи мне итоговые таблицы и по 3 примера отзывов на тему.
Результат: Агент сначала добавит в таблицу колонки «раздражение» и «тема». Он покажет справочник из 6–8 тем с описаниями. Затем выдаст сводные таблицы по городам и темам и результат регрессии, посчитанные кодом. Все цифры можно проверить: оценки лежат в файле, а не растворились в ответе модели. Если спросить «а что будет, если взять только Казань», расчёт пойдёт по тем же колонкам без нового прогона по тексту.
Почему это работает
Слабость LLM: модель плохо держит промежуточное состояние. Она нестабильна в точном счёте (сортировка 3 000 строк «на глаз», среднее, регрессия). Если один и тот же смысл («раздражение») нужно получить дважды, оценки разойдутся, потому что каждый вызов даёт свой ответ.
Сильная сторона: модель отлично понимает смысл одного текста с понятным заданием: оценить тон, выделить тему, выбрать из списка. Код, наоборот, идеально считает, но не понимает смысл.
Как метод это использует: граница проходит по результату смысловой работы. Модель делает локальную работу над каждой строкой и записывает её в колонку. Дальше всё считает код и повторно читает эту колонку, так что оценка получается одна на все шаги. Для тем действует тот же принцип: общий словарь категорий делается один раз, и все строки назначаются в него, поэтому темы у разных строк сопоставимы.
Рычаги управления: - Шкала в запросе («1–10», «да/нет», «одна из: …») → чем жёстче формат, тем легче считать кодом. Свободный текст в колонке неудобен для агрегации. - Число категорий («до 8») → больше даёт детальнее, но дробит статистику. Начинайте с 5–8. - Размер пачки (100 строк) → меньше пачки устойчивее оценки, но больше вызовов. - Список категорий в запросе назначения → добавьте «другое», чтобы редкие темы не затирались. - Серия вызовов под колонку: для нескольких признаков (город, индекс, тон) делайте по одному вызову на каждый, а не один на всё.
Шаблон промпта
У меня таблица {файл} с колонками: {список_колонок}. Текстовая колонка: {текстовая_колонка}.
Работай по правилам «семантических атомов»:
1. Смысловую работу над текстом делай только двумя типами шагов:
- TAG: на вход N текстов, на выходе ровно N значений, по одному на текст, в том же порядке. Результат сохраняй НОВОЙ КОЛОНКОЙ с идентификатором строки.
- CATEGORIZE: на вход N текстов, на выходе список из M категорий (название + описание). Результат сохраняй ОТДЕЛЬНОЙ ТАБЛИЦЕЙ.
2. Точные операции (фильтр, сортировка, группировка, среднее, регрессия) делай кодом по готовым колонкам. Не поручай их модели.
3. Один смысл — один расчёт. Если колонка уже есть, не пересчитывай, а используй её.
4. Для открытой группировки: сначала CATEGORIZE, затем TAG «выбери одну категорию из списка {категории} или "другое"».
5. Несколько признаков = несколько TAG-вызовов, по одному на признак.
Мой запрос: {что_нужно_узнать}
Предложи план из шагов TAG / CATEGORIZE / код. Затем выполни его. Если строк больше {порог_пачки}, разбей на пачки с идентификаторами и собери результат по ним. В конце покажи итоговые таблицы и 3 примера строк на каждую категорию для проверки.
Что подставлять: {файл} и колонки — вашу выгрузку. {что_нужно_узнать} — цель на человеческом языке, например «понять, от чего зависит срок решения обращения». {порог_пачки} — обычно 100–200 строк.
🚀 Быстрый старт — вставь в чат:
Вот шаблон «семантических атомов» (разметка колонкой + справочник категорий + точный счёт кодом).
Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, какие колонки есть в таблице, какой признак нужен из текста (шкала или категории) и что вы хотите посчитать в итоге. Эти ответы определяют, какие вызовы TAG и CATEGORIZE нужны и что останется на долю кода. Она возьмёт паттерн из шаблона и соберёт готовый промпт под вашу выгрузку.
Ограничения
⚠️ Нет нового качества: авторы прямо пишут, что атомы не добавляют возможностей. Это просто разумный дефолт: «разметь в колонку, потом считай». Качество разметки в среднем сопоставимо с готовыми семантическими операторами, а не лучше.
⚠️ Агент с кодом без атомов тоже справляется: обычный агент для программирования без этого интерфейса показал похожую сохранность результата в трёх из пяти классов задач. Выигрыш не гарантирован, а выводы сделаны относительно эталонного прогона, интервалы перекрываются.
⚠️ Абсолютные шкалы хуже: операторы точнее воспроизводили абсолютные значения оценок. Атомы лучше сохраняли порядок. Оценка «7 из 10» не стабильна от прогона к прогону. Для порядка и сравнений годится, для пороговых решений («всё выше 7 — эскалировать») проверяйте на выборке.
⚠️ Экономия запросов — свойство реализации: «в 41,8 раза меньше вызовов» относится к конкретной системе авторов. Для вас это значит скорее «экономия токенов», а не рост качества.
⚠️ Масштаб требует кода: автоматическая нарезка на пачки, сборка и повторные попытки встроены в систему авторов. В чате или агенте вы делаете это руками или через скрипт. Редкие, но важные темы могут потеряться при нарезке: если категорий почти поровну, нужен запас кандидатов.
⚠️ Только текст: метод проверяли на таблицах с текстовыми колонками. Это не про картинки, аудио и PDF с вёрсткой.
Как исследовали
Идея была в том, чтобы поставить границу между «смыслом» и «точным счётом» в агентной системе. Авторы сделали агента TADA-Agent: сильная модель планирует анализ и пишет Python, а лёгкие модели выполняют вызовы tag и categorize внутри кода. Для проверки собрали TABench — 40 полных аналитических запросов на таблицах, например «найди темы, оцени тон, посчитай регрессию». Сравнивали с системой готовых семантических операторов, где такие вызовы упакованы в единые действия вроде «сортировка по смыслу», и с агентом без атомов.
Так как у многих запросов нет единственного правильного ответа, эталоном служил отложенный прогон самой системы, а судил LLM-судья. Поэтому авторы честно пишут, что измеряют согласие с эталоном, а не абсолютное качество. Итог: качество на уровне строки сопоставимо, сохранность итоговых файлов выше во всех пяти классах задач, запросов к модели не менее чем в 41,8 раза меньше. Отдельно проверили большие объёмы (разметка за пределами одного контекстного окна) и открытые юридические и биомедицинские бенчмарки с теми же вызовами. Вывод для практики: главное преимущество в повторном использовании и экономии, а не в «умности». Это важная поправка на фоне громких заявлений в этой области.
Анализ основан на доступной части статьи: введение, обзор литературы и раздел 3.2. Подробные таблицы результатов и приложения в тексте не вошли.
Адаптации и экстраполяции
🔧 Техника: добавить «справочник кодов» → стабильные метки в колонке
Если нужны не оценки, а ярлыки, зафиксируйте их заранее:
TAG «тип обращения»: выбери ровно один код из списка:
BILL — оплата, DELIV — доставка, QUAL — качество, SUPP — поддержка, OTH — другое.
Верни только код, без пояснений.
Эффект: колонку легко группировать и сравнивать между выгрузками разных месяцев.
Экстраполяция: чат без кода, на небольшой выборке. Если у вас нет агента с кодом, а строк до 200:
Вот 100 отзывов, каждый с номером. Шаг 1: верни таблицу «номер | раздражение 1–10».
Больше ничего не делай. Я посчитаю в Excel.
Затем в следующем сообщении: «Теперь выдели 6 тем жалоб», а после этого: «Присвой каждому номеру одну тему из списка». Сортировку и средние делайте в Excel. Это перенос принципа в ручной режим. Авторы такой вариант не проверяли.
Ресурсы
- Semantic Atoms for Scalable Text Analysis in Data Analytics in the Era of LLM-Based Agents — Jinxiang Xie (Nanjing University), Zihao Li (Tsinghua University), Rui Ding, Bartuer Zhou, Shi Han, Dongmei Zhang (Microsoft Research).
- Бенчмарк TABench (40 аналитических запросов); агент TADA-Agent; предшествующая работа CAST (Xie et al., 2026) о стабильности разметки и суммаризации.
- Связанные системы: LOTUS, DocETL, Palimpzest; Programmatic Tool Calling (Anthropic, 2025).
