DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

Chain-of-Table: make the table itself the chain of thought — one op at a time, eight rows collapse to a single cell

Ask a language model a question about a table — "which North-region rep brought in the most revenue?" — and plain chain-of-thought answers it by reasoning over the rows in prose, holding every filtered row, every product and every running sum in its head at once. On more than a handful of rows that hidden scratchpad drops a row, mis-multiplies, or forgets a match, and the mistake is invisible in the final sentence. Chain-of-Table (Wang et al., 2024) fixes this by making the table itself the reasoning state: the model emits one tabular operation at a time, code executes it, and the table visibly shrinks toward the answer. I built a live demo that runs the real ops on real data. Here's the idea.

The reasoning lives in the data structure, not the prose

Free-text CoT carries a growing mental scratchpad — which rows survived the filter, each product, a running sum per group — and on a big table that mental state overflows. Chain-of-Table externalises it: each step is a small, deterministic table → table function, so the intermediate state is always a concrete, inspectable table — not an unverifiable claim in a paragraph.

The vocabulary is five table operations

The model doesn't write arbitrary code. It picks from a small, safe menu — f_add_column, f_select_row, f_select_column, f_group_by, f_sort_by — and each is a pure function.

const addColumn = (t, name, fn) =>
  ({ columns:[...t.columns, name], rows:t.rows.map(r => ({ ...r, [name]:fn(r) })) });
const selectRow = (t, pred) =>
  ({ columns:t.columns, rows:t.rows.filter(pred) });
Enter fullscreen mode Exit fullscreen mode

The arithmetic — sums, sorts — is done by trusted code, never by the model's mental maths. It only had to decide to group, not to add.

Plan one op at a time — dynamically, not upfront

The crucial detail: the model does not emit the whole chain in advance. It sees the current table and question, emits only the next operation, code runs it and hands back the new table, then it re-asks. Each decision is small and local. This lets the plan adapt — a group-by might reveal you now need a sort. It halts when the table already shows the answer (the paper's [E] end step; the demo calls it STOP), and the final answer is read off the surviving row rather than generated.

for (let i = 0; i < MAX_OPS; i++) {
  const next = await llm(planPrompt(table, question));  // pick the NEXT op
  if (/^\s*STOP/i.test(next)) break;                    // the table answers it
  table = applyOp(table, parseOp(next));                // execute + evolve
}
Enter fullscreen mode Exit fullscreen mode

Watch eight rows collapse to one

The demo's table has 8 deals across regions. The chain runs five ops: add a Revenue column (Units × Unit Price) → filter to Region = 'North' (8 rows → 5) → group by Rep summing revenue (5 → 3) → sort descending → keep the top row. What's left is a single cell: Alice, $450, just ahead of Carol at $440. That near-tie is exactly the case a prose sum fumbles — here it's decided by an exact, visible ordering.

Why it beats reasoning in prose

Three things fall out. There's far less to track, because the current table is the entire state. Every intermediate is a real table you can check, so a mistake surfaces at the step that made it instead of silently poisoning the answer. And the exact work is offloaded to a deterministic executor, so the totals are correct by construction. It shines precisely where CoT struggles — multi-condition filters, aggregations, comparisons over many rows — and it's prompt-only: no fine-tune, just a small op vocabulary and a plan-one-op-at-a-time loop. It's a cousin of PAL, but instead of free-form Python it uses a small table-op menu and shows a legible table at every step.

The takeaway I now carry: when the question is about a table, don't ask the model to reason over the rows in its head — hand it a few operations and let it transform the table until the answer is the only cell left.

Step through the chain and watch the eight rows collapse to Alice, $450:
https://dev48v.infy.uk/prompt/day48-chain-of-table.html

Top comments (0)