Apply to my task
arXiv:2610.34860 ★ 72 Oct 26, 2026

Semantic Atoms (Tagging and Categorization): The LLM Labels Text into a Column, the Code Does the Math

Key result

The problem: you ask an agent to "sort the complaints by frustration and find the topic of each." It rates frustration once, then rates it all over again on the next step, and the numbers disagree. The method writes every meaning-related score into a table column, and code does the sorting and regression on that column. It lets you analyze thousands of reviews so that any number can be checked in the file. The model does only tagging (N texts → N values) and categorization (N texts → M topics). One score lives across all steps instead of being recomputed.

01

TL;DR

Semantic Atoms are two "building blocks" for analyzing tables with text: tagging and categorization. Tagging takes N texts and returns N values, i.e. a new column. Categorization takes N texts and returns M categories, i.e. a reference list of topics. The LLM handles everything "meaning-related," while sorting, filters, averages and regression are done by ordinary code on the finished column.

The typical pain: you ask an agent to "sort the complaints by customer frustration and find the main topic of each." It does this in separate calls, and each one returns only the end result. The sort gives you an order, but without the scores themselves. When the next step needs a "frustration" column, the model scores everything all over again. The scores come out different, the ordering and the regression disagree, and you pay for the tokens twice. The reason is that the intermediate result was never saved anywhere: the model "kept it in its head" and didn't write it down.

The method is simple: every meaning-related step writes its result to an explicit place. A 1–10 frustration score for each row becomes a column, and both the sort and the regression read exactly that column. For topics there are two steps: first categorize finds a shared list of topics, then tag assigns each row a topic from that list. If there are thousands of rows, batching and reassembly happen inside the tool, and the agent never knows about it.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

STEP 1 (tagging):      tag(texts, "rate frustration 1–10") → a column of N values
STEP 2 (categories):   categorize(texts, "main complaint topics, up to 8") → a table of M categories
STEP 3 (assignment):   tag(texts, "pick a topic from the list {topics}") → a column of N values
STEP 4 (exact math):   sorting / grouping / regression — in code, on the finished columns

Rule: every meaning-related call → its result is saved and available to later steps.
Steps 1–3 are separate model calls; step 4 is Python/SQL/Excel formulas.
03

Example

Task: You run service quality for Amazon pickup locations in three cities. The export has 3,000 reviews: text, rating, city, days waiting for the order. You need to figure out what makes people angry and where it's worst, and also check whether frustration grows with the wait.

Prompt (for an agent with data analysis: Claude Code, ChatGPT with Data Analysis, Cursor):

I have a file reviews.xlsx with columns "text", "city", "wait_days", "rating".

Work by the "semantic atoms" rules:
1. Do meaning-related work on the text only through two kinds of steps:
   - TAG: N reviews in, exactly N values out (one per review, in the same order). Save the result as a NEW COLUMN in the table.
   - CATEGORIZE: N reviews in, a list of M categories out (name + short description). Save it as a SEPARATE TABLE.
2. Do sorting, grouping, averages and regression in code on the finished columns. Don't ask the model to "sort" or "calculate."
3. Don't recompute what's already tagged: if the column exists, use it.

Plan:
- TAG "frustration": rate from 1 to 10, where 1 is calm and 10 is extremely frustrated.
- CATEGORIZE: identify up to 8 main complaint topics.
- TAG "topic": for each review, pick exactly one topic from the resulting list (or "other").
- Then in code: average frustration by city and topic, a regression of frustration on wait days and topic.

If there are many reviews, split them into batches of 100 with a row ID and reassemble the result by ID. Show me the final tables and 3 sample reviews per topic.

Result: The agent will first add "frustration" and "topic" columns to the table. It will show a reference list of 6–8 topics with descriptions. Then it will output summary tables by city and topic and the regression results, all computed in code. Every number can be checked: the scores live in the file instead of dissolving into the model's reply. If you ask "what if we only take Denver," the calculation runs on the same columns without another pass over the text.

04

Why It Works

The LLM's weakness: the model is bad at holding intermediate state. It's unreliable at exact math (sorting 3,000 rows "by eye," averages, regression). If the same meaning ("frustration") has to be extracted twice, the scores will diverge, because each call gives its own answer.

Strength: the model is excellent at understanding the meaning of a single text with a clear task: rate the tone, identify the topic, pick from a list. Code is the opposite: it calculates perfectly but doesn't understand meaning.

How the method uses this: the boundary runs along the output of the meaning-related work. The model does local work on each row and writes it into a column. From there, code does all the math and rereads that column, so there's one score for every step. Topics follow the same principle: a shared category dictionary is built once and every row is assigned into it, so topics across rows are comparable.

Control knobs: - The scale in the request ("1–10," "yes/no," "one of: …") → the stricter the format, the easier it is to compute in code. Free text in a column is awkward to aggregate. - Number of categories ("up to 8") → more gives more detail but fragments the stats. Start with 5–8. - Batch size (100 rows) → smaller batches give more stable scores, but more calls. - The category list in the assignment request → add "other" so rare topics don't get erased. - One call per column: for several attributes (city, ZIP code, tone), make one call for each instead of one for everything.

05

Prompt Template

I have a table {file} with columns: {column_list}. Text column: {text_column}.

Work by the "semantic atoms" rules:
1. Do meaning-related work on the text only with two kinds of steps:
   - TAG: N texts in, exactly N values out, one per text, in the same order. Save the result as a NEW COLUMN with a row ID.
   - CATEGORIZE: N texts in, a list of M categories out (name + description). Save the result as a SEPARATE TABLE.
2. Do exact operations (filter, sort, group, average, regression) in code on the finished columns. Don't hand them to the model.
3. One meaning, one calculation. If a column already exists, don't recompute it — use it.
4. For open-ended grouping: first CATEGORIZE, then TAG "pick one category from the list {categories} or "other"".
5. Several attributes = several TAG calls, one per attribute.

My question: {what_i_want_to_learn}

Propose a plan of TAG / CATEGORIZE / code steps. Then execute it. If there are more than {batch_threshold} rows, split them into batches with IDs and reassemble the result by ID. At the end, show the final tables and 3 sample rows per category for checking.

What to fill in: {file} and the columns — your export. {what_i_want_to_learn} — the goal in plain language, e.g. "understand what drives ticket resolution time." {batch_threshold} — usually 100–200 rows.

🚀 Quick start — paste into the chat:

Here is the "semantic atoms" template (tagging into a column + a category reference list + exact math in code).
Adapt it to my task: [your task].
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask what columns your table has, what attribute you need from the text (a scale or categories) and what you ultimately want to calculate. Those answers determine which TAG and CATEGORIZE calls are needed and what's left for the code. It will take the pattern from the template and assemble a ready-made prompt for your export.

06

Limitations

⚠️ No new capabilities: the authors say outright that atoms don't add new abilities. It's just a sensible default: "tag into a column, then compute." Tagging quality is on average comparable to off-the-shelf semantic operators, not better.

⚠️ A coding agent without atoms manages too: a regular coding agent without this interface showed similar result preservation in three of five task classes. The gain isn't guaranteed, the conclusions are relative to a reference run, and the intervals overlap.

⚠️ Absolute scales are weaker: the operators reproduced absolute score values more accurately. Atoms preserved the ordering better. A "7 out of 10" isn't stable from run to run. It's fine for ordering and comparisons; for threshold decisions ("escalate everything above 7"), validate on a sample.

⚠️ The call savings are an implementation property: "41.8 times fewer calls" refers to the authors' specific system. For you it means "token savings" more than a quality boost.

⚠️ Scale requires code: automatic batching, reassembly and retries are built into the authors' system. In a chat or an agent, you do this by hand or with a script. Rare but important topics can get lost during batching: if categories are nearly evenly split, you need a buffer of candidates.

⚠️ Text only: the method was tested on tables with text columns. It's not for images, audio or layout-heavy PDFs.

07

How It Was Studied

The idea was to draw a boundary between "meaning" and "exact math" in an agent system. The authors built TADA-Agent: a strong model plans the analysis and writes Python, while lightweight models execute tag and categorize calls inside the code. To test it they assembled TABench — 40 end-to-end analytical queries on tables, e.g. "find the topics, rate the tone, run a regression." They compared against a system of off-the-shelf semantic operators, where such calls are packaged into single actions like "semantic sort," and against an agent without atoms.

Since many queries have no single right answer, a held-out run of the system itself served as the reference, and an LLM judge did the grading. So the authors honestly note that they measure agreement with the reference, not absolute quality. Bottom line: row-level quality is comparable, preservation of the final output files is higher in all five task classes, and there are at least 41.8 times fewer model calls. They separately tested large volumes (tagging beyond a single context window) and open legal and biomedical benchmarks with the same calls. Practical takeaway: the main advantage is reuse and savings, not "smarts." That's an important correction amid the loud claims in this field.

The analysis is based on the available part of the paper: the introduction, literature review and Section 3.2. Detailed result tables and appendices were not included in the text.

08

Adaptations and Extrapolations

🔧 Technique: add a "code book" → stable labels in the column

If you need labels rather than scores, lock them in up front:

TAG "ticket type": pick exactly one code from the list:
BILL — billing, DELIV — delivery, QUAL — quality, SUPP — support, OTH — other.
Return only the code, no explanation.

Effect: the column is easy to group and compare across exports from different months.

Extrapolation: a chat without code, on a small sample. If you don't have a coding agent and you have up to 200 rows:

Here are 100 reviews, each numbered. Step 1: return a table "number | frustration 1–10".
Don't do anything else. I'll do the math in Excel.

Then in the next message: "Now identify 6 complaint topics," and after that: "Assign each number one topic from the list." Do the sorting and averages in Excel. This carries the principle over to manual mode. The authors didn't test this variant.

09

Resources

  • 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).
  • Benchmark TABench (40 analytical queries); agent TADA-Agent; prior work CAST (Xie et al., 2026) on the stability of tagging and summarization.
  • Related systems: LOTUS, DocETL, Palimpzest; Programmatic Tool Calling (Anthropic, 2025).

Research digest

Key result

The problem: you ask an agent to "sort the complaints by frustration and find the topic of each." It rates frustration once, then rates it all over again on the next step, and the numbers disagree. The method writes every meaning-related score into a table column, and code does the sorting and regression on that column. It lets you analyze thousands of reviews so that any number can be checked in the file. The model does only tagging (N texts → N values) and categorization (N texts → M topics). One score lives across all steps instead of being recomputed.

Principle

Two kinds of steps, and nothing else. The first: tagging. The model reads N reviews and returns exactly N values, e.g. frustration from 1 to 10. That's a new column. The second: categories. The model reads N reviews and returns a list of M topics with descriptions. That's a separate table. Topics take two moves: first the topic list, then tagging with "pick one topic from the list." The model writes everything meaning-related to an explicit place, and code computes everything exact. It's like a kitchen: the cook chops and tastes, the scale weighs. Nobody guesses the weight by eye.

Why it works

The model is bad at keeping an intermediate result in its head. It slips up on exact math: sorting 3,000 rows "by eye," averages, regression. Every new call gives its own answer, so asking twice to "rate frustration" yields two different columns. But a single short text with a clear task ("rate the tone," "pick a topic from the list") the model understands perfectly. Code is the reverse: it calculates flawlessly but can't see meaning. The boundary runs along the output of the meaning-related work: it's written once, and every step reads the same column. A single topic list makes topics comparable across rows. The authors' numbers are modest. No new capabilities, tagging quality roughly on par with off-the-shelf tools. A regular coding agent preserved results just as well in 3 of 5 task classes. Atoms preserved row order better and absolute score values worse. The claimed 41.8x reduction in calls applies to the authors' system. For you it's more about token savings.

When to apply

Analyzing tables with text: reviews, support tickets, comments, open-ended survey answers → especially when you need to connect meaning with numbers. For example, finding what makes people angry, where it's worst and whether frustration grows with the wait. Fits when several steps in a row use the same score. NOT a fit for images, audio and layout-heavy PDFs. For threshold decisions ("escalate everything above 7"), validate the scores on a sample first: a "7 out of 10" drifts from run to run.

Mini recipe

1. Describe the table: the file, the columns, which one holds the text. 2. Ban mental math: "do sorting, averages and regression in code, don't ask the model to calculate." 3. Tag into a column: "rate frustration 1–10, save it as a NEW COLUMN, one value per review, in the same order." 4. Build a topic reference list: "identify up to 8 main complaint topics, name and short description, as a separate table." Start with 5–8 topics. 5. Assign topics to rows: "pick exactly one topic from the list or "other"." The word "other" saves rare topics. 6. Batch it: if there are more than 100–200 rows, add a row ID and reassemble the result by it. 7. Don't recompute: if the column already exists, use it. 8. Eyeball it: ask for 3 sample reviews per topic.

Examples

[BAD]: `Here are 3000 reviews. Sort them by frustration, find the main topics and calculate whether frustration grows with the wait` [GOOD]: `reviews.xlsx has columns "text", "city", "wait_days". Step 1: rate frustration from 1 to 10 for each review and save it as a new column. Step 2: identify up to 8 complaint topics in a separate table. Step 3: assign each review one topic from the list or "other". Step 4: in code, calculate average frustration by city and topic and a regression on wait days. Take order and numbers from the columns, don't recompute anything. There are many rows, so split them into batches of 100 with a row number.`

In plain words

Making an LLM do table analytics directly is a total flop. Models are brilliant at reading hidden subtext but completely can't do math. Feed a model a pile of data and ask it to find a correlation, and it will start confidently making things up. The Semantic Atoms method solves the problem radically: it takes the calculator away from the language model and leaves it only the job of recognizing meaning.

It's like hiring a bohemian poet to keep the company's books. He'll write the customer's drama beautifully, but he'll botch the numbers so badly that the IRS shuts you down within the hour. LLMs fumble at holding intermediate state: ask one to rate "frustration" twice and you'll get two different scores, and when sorting thousands of rows it simply drowns in the math.

The fix lies in two basic building blocks: Tagging and Categorization. The model runs through 3,000 reviews and turns raw text into structured labels like "rude courier" or "damaged packaging". Then good old code takes over: filters, averages and regressions are computed by an ordinary script on the finished column, without a single hallucination.

The example uses marketplace reviews, but the principle is universal. The same combo fits support tickets, CRM complaints, employee surveys or medical questionnaires perfectly. Anywhere a business is trying to understand how the human emotions in text hit real metrics: delivery times, churn or revenue.

Bottom line: stop stuffing raw datasets into a prompt and hoping for a miracle. The LLM turns meaning into a column; classic code does the math. Split those jobs, and analytics stops being reading tea leaves.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Semantic Atoms (Tagging and Categorization): The LLM Labels Text into a Column, the Code Does the Math arXiv:2610.34860

Sign in to apply this study New accounts get 50 free credits.