Listen to this page
Artificial intelligence
The Model Does Not Write the Number
Four plain-language questions put to a company database: a number, a prediction, a forecast, a chart. Every time, the language model writes the query; the database is what answers.
You ask a language model a question about your data. A language model is the program that has learned to read and write text, the one behind chat assistants. It answers with a number. The number is plausible. It is wrong. Hardly anyone signs off on a board decision on the strength of a plausible number. That single fact blocks more enterprise deployments than budget and regulation combined.
Three words are enough to follow the whole article. A database is a set of large tables, cousins of spreadsheets. A table of customers, a table of invoices, thousands of rows each. A query is a question put to those tables. You write it in a language built for the job, the Structured Query Language, shortened to SQL. It is rigid and free of double meanings, saying exactly which rows to take and what to do with them. The language model understands plain language; it can also write SQL. Everything that follows sits in that meeting point.
The answer to the wrong number is not to ask the question better. It is to take away the model's chance of being wrong about the number. It does not write the answer: it writes the query. The database answers, with what it holds. The difference looks like nothing, but it changes the nature of the error. A wrong query can be seen, kept, replayed, fixed. A made-up number cannot be seen, because it looks exactly like a correct one.
This article follows four questions really put to an enterprise deployment. They arrive in the order they come up in a meeting: last month's number, a
row-by-row prediction, a three-month forecast, then a chart. Three stories on one foundation, each named
like an address: txt2sql for the number, txt2sql2ml for the prediction, txt2sql2viz for the figure. The first story is well-trodden industry
ground; the other two are far rarer. Those are the ones I built.
The foundation is the same at all three stories: the question becomes a query, the query is parsed before it runs, the database answers. Only the last link changes.
"How many invoices are overdue?"
The answer lands in two seconds: thirteen. And, unfolded underneath it, the query that produced it.
SELECT COUNT(*) FROM invoices WHERE status = 'overdue' LIMIT 500
Even without ever having read SQL, you can decipher it. It counts (COUNT) the rows of the invoices table (invoices) whose status equals overdue. It never brings back more than five hundred of them (LIMIT 500).
Showing the query is not a flourish. It is the proof. Anyone who knows the database can read it. They can argue with it. They can run it again. The number is not to be believed. It is to be checked.
Writing SQL in general is something a recent language model does very well. The difficulty is elsewhere:
writing the right query for this database. You need the right table names. You need the right joins, that is,
the right way of matching two tables through a shared column, invoices with their customers for instance. Above all
you need the right filter values. Is an unpaid invoice's status written overdue, unpaid or
3? All of that is in the schema, the map of the database: the list of its tables and their columns. A model
that does not know it invents names that look right and are wrong. A tool that turns a question into a query is judged on that. It has to stick to the database in front of you.
There are two ways to go about it. The first, fine-tuning, sends the model back to school: its training is resumed on the customer's data until it knows them by heart. That is expensive, slow, and has to start over whenever the database changes. The second leaves the model as it is. For each question, it slips the model a revision sheet2. On it go the few pieces of information that matter for that one question. It is called retrieval-augmented generation, or RAG. Vanna, the open source reference on this ground, belongs to that second family1.
One point is confusing. It is the most important of all. In Vanna, "train" does not mean what you think. It means filling a knowledge base, which the system will consult when answering. The model itself does not change: none of its internal dials is touched. You file texts away in a kind of library. A question comes in. You look for the texts that talk about the same thing, even in other words. You add them to the question you put to the model3.
Three kinds of content, in the reverse order of intuition
Three kinds of content go into that library. Intuition gets their relative weight wrong.
The table structure comes first. It is each table's CREATE TABLE, its identity card. Its name, its columns, and the type of each. Number, text or date. Then come its keys, the columns that link it to other
tables. It teaches the model what exists and stops it inventing. One table per card, so each comes back separately
when a question touches it.
The business glossary says what the structure does not: how a measure is computed, what the
in-house vocabulary means, what the coded values stand for. One sentence per card, written the way a user would say
it. "Revenue before tax on orders is the sum of orders.total_ht_eur." This is where you gain the most. A model with no context goes wrong exactly there.
The question-query pairs come last in the work and first in the results. A question in plain words, the correct query beside it. Vanna's documentation says it without hedging: it is their quality that decides the result1. Looking at the mechanism shows why. For each question, the system shows the model only the few closest cards; the rest of the library does not exist for it. One good example, close to the question asked, is therefore worth a thousand distant ones. You file things away to cover cases, not to pile up volume. Twenty to a hundred verified pairs are enough to start. They do have to cover the families of question people will ask: counting, crossing two tables, filtering on a coded value, ranking the biggest9. That order of magnitude holds for a database this size; it is not a general rule. It depends on the number of tables, on how ambiguous the vocabulary is, on how many business areas are covered, and above all on the questions people really ask.
Two rules matter more than anything for choosing what enters the library. First, always verified SQL. Actually run, and confirmed correct. A wrong pair teaches the system to produce wrong SQL. Second, never
SELECT *, the query that brings back every column without naming any: it teaches nobody a single column
name.
Two locks between the model and the database
The model produces a query, nothing more. Execution happens elsewhere, under an account allowed only to read the database, never to change it. Before the query runs, guardrails parse it. Parsing means cutting it up the way you diagram a sentence in grammar class, subject, verb, complements; that breakdown is called a syntax tree4. Reading that tree is what lets the chain refuse anything that is not a plain read. The separation is a security measure: the part that talks to the model never has the right to write to the database.
The second lock came out of one precise failure, on 4 September 2026. Until then, the model received the
names and types of the columns, but never the list of values they actually hold. So it wrote
WHERE status = 'confirmed' on the invoices table. The query was correct, the guardrails accepted it, it ran
without error. And it returned zero rows. The real values were paid, overdue and sent;
confirmed existed in the orders table, not in the invoices one. The user saw an empty result, with no
explanation at all.
That flaw is fixed from both ends. To prevent it, the pipeline goes after the columns with few different values. A status, a category. Never an amount. It reads from the database the real list of their values, and hands it to the model along with the rest. It starts with the columns whose exact list of allowed values the database already knows. It continues with the text columns the database statistics flag as low-variety, re-reading their values with a bounded query. A column with no statistics is never probed: no list beats a wrong one.
Then comes the cure. A query can run without error and return no rows, because it filters on a value that does not exist in the column. It no longer hands back a silent blank. The system tries once more, giving the real values to the model. If that fails too, the answer names three things. The column, the invented value, and the values that really exist.
Proving that all this work is worth something
This is the step people skip too often. It is also the only one that proves all that sorting was worth it. You set aside a few question-query pairs that you do not file in the library: they will serve as the exam. The principle is that of any test: you do not grade a student on exercises they have the answers to. If you measure on questions already filed, you are only measuring the system's ability to bring back an example it has learned.
You can score this three ways, from the least to the most reliable. The first is the valid-SQL rate: a mere guardrail, since a query can be valid and wrong. The second compares the two queries character by character. It badly underrates accuracy, because two correct queries are almost always written differently5. The right measure is the third, the simplest too. You run both queries, the generated one and the reference, then compare the results. It is the measure used by the field's benchmarks, Spider6 and BIRD7, those public question sets every team scores itself against. It wins because it judges the answer delivered, the only thing that matters.
On the control set, the business glossary and the worked examples take the share of correct answers from 62.5 % to 87.5 %. Three examples added on the two lagging families, joins and one filter, take it to 100 %. Replayed on three database sizes, the same measurement gives the same result: it is the library of examples that moves the score, not the data volume. One caveat belongs here, without which these figures get over-read. The control set is small. Scores move across it in steps of 12.5 points, which says enough about how fine-grained it is. That 100 % means nothing is missing on those questions. It does not say the pipeline is correct in general; a case study is not a benchmark.
A single overall score hides the family of questions that fails8. So the score is broken down by family: counting, crossing tables, filtering, ranking. That reading tells you what to do next. If the crossings are weak, you need examples of crossings, not a bigger model. That is exactly what happened here. It is the jump from 87.5% to 100% on the figure.
"Which customers are at risk of leaving and how confident are you?"
An exact number answers a question about the past. How much did we invoice last month, which customers went over budget. It does not answer the question the executive asks right afterwards, the one about the future. Until now, that second question meant a project of several months, handed to data specialists, to be redone for every customer and every question.
The idea that changes everything is simple. The query no longer returns a number. It returns a table whose last column is the question. That column is filled for some rows, empty for the ones you want to predict.
| Customer | Segment | Recency | Frequency | Tickets | Left? |
|---|---|---|---|---|---|
| Studio Moreau | SMB | 12 d | 8 | 1 | no |
| Fabrique Horizon | Enterprise | 190 d | 1 | 4 | yes |
| Maison Central | SMB | 45 d | 5 | 0 | ? |
One question, one query: the gaps fill in. SQL cannot predict; it can fetch the right shape of table.
That table holds both the examples and the question. It is exactly what a tabular foundation model knows how to read. A model of this kind was trained once and for all, at its laboratory, on millions of tables made up for the exercise. It does not know your data: it knows how tables behave. It is a grader who, having marked thousands of papers, spots a mistake at first glance on a paper they have never seen. You show it the table, it fills the gaps in one go. Nothing is trained on your data, no internal dial is changed, no model is left to store.
This is called in-context learning, and everyone has already lived it. You give a chat assistant an example inside the conversation itself. It catches on without being retrained10. The comparison has an interesting limit: text reads left to right, whereas a table has no order, neither across rows nor across columns. That is exactly the problem these models had to solve.
The consequence is direct: no training project, nothing to maintain. The day you plug in a new customer, there is no model to retrain. One and the same code covers four uses. Predicting a category, will leave or will stay. Predicting a number, next month's amount. Filling gaps. And ranking the top N.
Two European schools and why I picked the French one, now that Google has joined the dance
Until the autumn of 2026 this ground was held by two teams, both European. The German school, in Freiburg, around Frank Hutter, produced TabPFN, published in Nature in January 202511. Its industrial arm, Prior Labs, was acquired by SAP: announced in May 2026, closed on 17 July, with more than a billion euros committed over four years12. A German vendor putting a billion into an eighteen-month-old German laboratory says how much industrial interest the subject carries. That is a market signal, not a technical proof.
The French school is at Inria Saclay, in the SODA team, around Gaël Varoquaux, co-creator of scikit-learn. Its model is called TabICL. It needs dating, because the ecosystem moves fast. The first version, presented at ICML in 2025, matches TabPFN v2 across two hundred classification datasets. It is consistently faster, by up to ten times. On tables of more than ten thousand rows it overtakes it13. The second, TabICLv2, shipped in February 2026, fits and predicts a table of fifty thousand rows by a hundred features in under ten seconds on an H100 graphics processor14. The comparisons in this article are about the first one; dating them keeps them from reading as a permanent state of affairs.
I picked TabICL, and not out of patriotism. Both models run on the customer's machines, with nothing leaving. Both publish their weights, that is, the billions of dials learned during training. TabICL also publishes the code that trained it14, data generator included. The difference shows the moment you want to check something. With the weights alone, you can run the predictions again. With the training code, you can rebuild the model from scratch. When you tell an executive "this customer is about to leave", being able to show where the answer came from really counts.
On 29 September 2026 a third player walked in. Google Research published TabFM, four hundred million internal dials, trained the same way on tables made up from scratch. On TabArena, the shared test bed of fifty-one datasets, its three variants take the top three places. TabICLv2 lands ninth out of twelve, in classification as in regression23. Those figures come from the TabFM authors' own table rather than from an independent measurement, but they are too clear to leave out.
Those figures change nothing about the choice made here. It all turns on one line of license. TabFM's weights are public, but restricted to non-commercial use. The text rules out client deliverables, paid products or services, and any activity that brings in money. For any of that, Google has to grant a commercial license24. So the model at the top of the leaderboard is the one a company is not allowed to use to answer its own customer. TabICL is BSD licensed, the same as scikit-learn. Two details complete the picture. TabFM's best-ranked variant hands column preparation to Gemini, so the data does leave, which is exactly what this chain is built to avoid. And the technique behind its strength, column grouping, is taken from TabICLv2 and TabPFN-3: the two European schools' work is inside it.
What goes on there is worth a look, because it is open source at its best. Every team reads the others, and says so. TabICL's forecasting code comes from TabPFN-TS, written by the German team; it therefore stays under Prior Labs' license. It is the French team's own license file that says so25. TabFM's column grouping comes from TabICLv2 and TabPFN-3, and Google says as much in its own paper. The leaderboard that ranks them is public, so a newcomer has to put its numbers next to everyone else's, not next to its own. One team publishes, the other two read, improve and publish back. Between the Nature paper of January 2025 and Google's of September 2026, twenty months went by. They were enough for these models to leave the laboratory. They now beat automated pipelines tuned for four hours on the data itself. This is not courtesy between researchers, it is rivalry. Nobody wants to be ninth out of twelve.
Careful not to confuse two kinds of freedom. What circulates freely is the knowledge, not always the right to use it. TabFM publishes its paper and its weights while forbidding commercial use: the idea is there for everyone to read, so everyone benefits. But what you are allowed to install at a customer's site depends on the license alone. Hence two criteria that follow each other without mixing: you read everyone, you install what the law allows.
The row-by-row answer, on the customers whose departure status is not consolidated. Three departures called, none above 69 %: each prediction comes with its confidence and that confidence stays modest.
Let us now say what that 69% means. It is almost always read the wrong way. It does not mean we are 69% sure this customer will leave. It means that among the customers who resemble this one on the columns we can see, about sixty-nine out of a hundred have left. It is an observed frequency, not a prediction about one person.
Two very different things make that figure uncertain, and confusing them is expensive. The first is our own ignorance: there are few comparable customers in the history, so the estimate would move if we added data. The second is the randomness of the world: even with a perfect history, two customers identical on paper do not make the same decision. The first shrinks if you collect more. The second never shrinks. That is why an honest prediction stays cautious.
Hence a rule that holds across all three stories: a figure without its uncertainty is an opinion dressed as a fact. On this data, no prediction goes above 69%. That is a good sign. A tool that had announced 97% would have been lying.
Still, knowing who will leave, without knowing why, is no use. You do not keep a customer with a probability. You keep them with a reason, precise enough to act on.
The problem had a name in commerce long before it had one in statistics. Its most famous phrasing runs like this: "Half the money I spend on advertising is wasted; the trouble is I don't know which half." The line is credited to the American department-store owner John Wanamaker. Sometimes to the British industrialist Lord Leverhulme, occasionally to Henry Ford. The earliest known trace is a 1919 speech already attributing it to Wanamaker. Neither the Wanamaker archives nor Unilever's hold any record of it15. The sentence that states the attribution problem cannot itself be attributed to anyone.
The problem is real enough. It is also ill-posed, in the strict sense. The sale happened once. We will never know what would have happened without the poster in the underground, because that world never existed. Sharing the credit between channels is therefore a convention: you pick a rule for splitting, then you stand by it.
A small experiment shows how much the choice of rule matters. Two advertising channels, billboards and online, bought together and therefore strongly correlated: 0.84 across two hundred simulated weeks. By construction, only the billboards act on sales; online is a passenger. Then each channel is asked what it explains.
The same channel, the same data, two incompatible answers: the only difference is the order in which the question is asked.
The first two bars say everything. Asked on its own, the online channel explains 55.3 % of the variation in sales, which would make a handsome dashboard. Added to billboards, it explains nothing at all: 0.0 %. That is Wanamaker's trouble, in numbers.
The Shapley split averages the two orders and settles it: 52.5% to billboards, 27.7% to online. The two shares come to 80.1%, which is exactly what the two channels explain together. That is no happy accident: Shapley required the shares to add up. That is what makes the result defensible in a meeting. The protocol is spelled out, to be rerun rather than taken on trust: two hundred simulated weeks, seed 20260925, linear regression. The value of a group of channels is measured by the share of the variation in sales it explains.
One limit has to be stated plainly, or the method gets made to say what it does not. Shapley gives 27.7% to a channel that we know, since we built the example, causes nothing. That is not a fault of the method. It answers faithfully the question it was asked, which is: what did the model use. That is not the same question as: what caused the sale. For that one there is no shortcut. You need an experiment: cut one channel's budget in one region, and compare with the others. The split explains the model; only the experiment reaches the cause.
The model returned a single number after looking at a dozen columns at once. We would like to say how much of that 69% comes from the age of the contract, how much from the number of complaints, how much from the last invoiced amount. Cutting a result into shares, one per variable, has a name: attribution. Nothing guarantees in advance that it is possible. The model did not compute its number as a sum. It mixed everything. Attribution rebuilds, after the fact, a split that never existed in the computation.
The naive attempt shows the difficulty. To measure what a variable brings, you can remove it and watch how far the prediction drops. The trouble is that the answer depends on the order in which you remove the others. Removing the age of the contract drops the prediction a long way if nothing has been removed yet. The same removal changes almost nothing once the number of complaints has gone, because the two say partly the same thing. So there is not one contribution, but as many answers as there are orders.
Lloyd Shapley solved this in 1953, for an entirely different purpose. He wanted to share a team's payoff fairly among its members, when each brings something different and the contributions overlap16. His answer is simple: since the order changes the result, look at every possible order and take the average. Think of a restaurant bill. Depending on who arrives first and what gets shared, each person's share changes; averaging over every order of arrival gives a split nobody can dispute. That work earned him the Nobel Memorial Prize in Economic Sciences in 2012. Applied to a prediction rather than a dinner, the same computation says how much each variable weighed, and in which direction17.
The second method starts from a different idea, just as simple. A complicated model stays complicated. But look closely enough, around one single customer. It then behaves almost like a straight line, the way a curve looks straight when you zoom in far enough. So you build a simple model that imitates the big one. It holds in that small neighborhood only. Its coefficients read off directly18.
Both methods are shown side by side. When they agree, the reading is solid. When they disagree, that is already information. The prediction rests on a fragile balance between variables. Better to know that before calling the customer.
"What is the revenue forecast for the next three months?"
Same foundation, same model, different question. This time the query brings back a series through time; the answer is about months that do not exist yet.
Each forecast month carries its range, from the tenth to the ninetieth percentile. A percentile cuts the possible values into a hundred parts: the tenth is the one below which there is only a one-in-ten chance of landing, the ninetieth the one below which there are nine chances in ten. Between the two, eight chances in ten remain and that is what the bar says.
A single number about the future is fortune telling. A number with its range is a decision. And this figure says something uncomfortable that you have to be able to read: the range is wider than the gap between the three months. August looks better than July, but the bars overlap almost entirely. So the gap between the two months means nothing.
The tool is not at fault: the data is bad. The monthly series in this demonstration database is pure noise, jumps with no regularity at all. Over twenty-one months: 293 euros in one month, 72,380 a year later, and three months missing. No method can forecast that. The only honest answer is a wide range. A tool that had returned three neat, tidy numbers would have dressed the situation up. It is the same principle as on the first story: what is promised is not the quality of the answer, but that its uncertainty is shown beside it.
One implementation detail says a lot about the world you work in. The number of months to predict is read from the user's question, which is to say from free text. "In a hundred thousand months" translated into a hundred thousand months to forecast. That gave absurd dates and a computation that tied up the machine, for a result nobody had seriously asked for. That number is now capped. Past that point a forecast has no value anyway, so nothing is lost.
"Show me where revenue is concentrated"
Last question, and the last link that differs. The result is no longer a number or a table. It is a figure. It is chosen automatically, from the shape of the data and what the question asks, then drawn on the spot. So there is no dashboard to maintain. A dashboard is a page of frozen charts prepared in advance: it answers the questions people were asking six months ago, the ones foreseen while building it.
Except that this choice is exactly where a language model can do anything at all. Show it a hundred and twenty-seven chart names. It can invent one. It can misspell one. It can also pick one that does not go with the columns present. A map, for instance, when no column holds a place. So the safety cannot rest on its good will. It has to be in the shape of the program, where the model cannot get past it.
Two deterministic steps (no model involved, so no surprises possible) bracket the two model calls. The third step eliminates every structurally incompatible candidate before the model sees anything at all; the fourth can only reorder and annotate that already-safe list, never extend it.
The model picks a dish from a menu it did not write. This guarantee is not of the same nature as a temperature setting. That dial makes the model more or less adventurous. Nor is it of the nature of an instruction added at the top of the conversation. It does not depend on the model's compliance, but on the shape of the program. And as on the first story, it makes the remaining error visible and fixable: a badly chosen figure is corrected with one click, and never blends in with a correct one.
The answer to the question asked: twelve of the nineteen customers the query returned make 82 % of revenue. The cumulative share is over those nineteen customers. That caveat matters: a Pareto chart ranks the contributions from largest to smallest, then draws above them the curve of what they add up to, so you read at a glance how few customers make up most of the total. Drawn on a ranking already truncated upstream, on the other hand, it announces a share "of the total" that is nothing of the kind, for all its neat curve.
The drawing is done by sprezzature.ai, an open source figure engine21. Its catalog holds one hundred and twenty-seven chart types, from curves to flow diagrams, treemaps, waterfalls and maps. That large number is not collecting for the sake of it. The wider the catalog, the more charts fit the columns you have. So the automatic choice lands right more often.
Every figure also follows rules on accessibility and color. Contrast is checked. The figure stays readable for a color-blind person. Never does a color alone carry information. The reading direction is marked on any axis where up is better than down. None of that is cosmetic. Nobody reads a poorly contrasted chart projected in a room. And a chart that asks you to tell two greens apart excludes one man in twelve. These rules come from graphical semiology, the study of what visual forms can really convey19, and from experiments on perception20. Here they are lines of code, not recommendations.
What production learns and preparation cannot guess
No amount of sorting done in advance can guess how people will phrase their requests. It knows nothing of their turns of phrase, their shortcuts, the special cases of each company. Only production shows the questions people really ask. Every question handled well, and above all every correction, teaches something the initial sorting did not know.
The loop is simple. Someone asks a question. The system writes the query. It runs read-only. A human validates the result, or fixes the query. Once validated, the pair joins the library of examples. The next question that resembles it will find that new example.
One safety rule allows no exception. It is also the easiest to get wrong: never blind learning. Automatically capturing every query produced and feeding it back as an example poisons the library for every similar question to come. Bad SQL teaches the system to produce bad SQL. A pair is therefore only accepted through a dedicated path, which replays the guardrails and re-runs the query before accepting it. No blind trust, not even in what we are told has already been verified.
Four properties separate a mechanism that works on one laptop from a loop that holds in production. Persistence: the library lives in the database already in place22, not in a memory lost on the first restart. Idempotence: a pair's identifier is computed from its content, so submitting it twice creates no duplicate. Traceability: every pair that came from the field is marked as such, apart from the hand-sorted corpus. You can then check what production taught the system, and remove one bad example. And measurement: after each batch of additions, you sit the exam again. You verify the progress instead of assuming it.
What this changes and what it does not
Before, a business question left as a ticket for the data team. It came back three days later. The decision had often been made without it. A question about the future left as a project. Now the question is asked out loud, the number lands in seconds, and so does the follow-up: the meeting keeps its rhythm. What matters is not that the machine does analysis. It is that the delay between the question and a reliable number drops from three days to three seconds, because the number comes from the database.
What this does not change deserves to be said just as plainly. The model can still write a bad query. The architecture guarantees that we will only read the database, within known limits. It does not guarantee that the query matches what the person meant to ask. On that point, it reduces the ways of going wrong and makes them
visible. Removing them would be something else. The real limit is not the volume of data, since the chain queries the
database directly and SQL does the filtering. The real limit is the quality of the schema and the vocabulary. A
database whose columns are called col_17 will not let itself be queried in plain language, and no model will
change that.
The three lines
txt2sql question → SQL → database → the real number
txt2sql2ml question → SQL → table with gaps → the prediction and its range
txt2sql2viz question → SQL → rows → the right chart, live
One foundation, three stories, and everywhere the same discipline: the model proposes the form, the machine checks, the data decides. That is what separates a number you can sign from a number that merely looks right.
Acknowledgments
Special thanks to Marie Sacksick, Edmond Jacoupeau, Bachir Zerroug and Vincent Sammiez for our fruitful discussions on these topics.
Bibliography
None of these titles is here for decoration: each one carries a design decision taken above. The notes say which.
- Vanna AI. Training advice, project documentation. vanna.ai/docs/training-advice States without hedging the hierarchy of the three kinds of content and the safety rule taken up here: the quality of question-to-query pairs is the single largest determinant of the result and bad SQL learned teaches the system to produce bad SQL.
- Lewis, P. et al. (2020). "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks", NeurIPS. arXiv:2005.11401 The paper that named retrieval-augmented generation. It establishes the principle used on the first story: leave the model untouched and supply, for each question, the context that matters, rather than retraining its weights.
- Vanna AI (2023). How Vanna works, how to train it, data security. medium.com/vanna-ai Walks step by step through the retrieval mechanism everything else depends on: the question is embedded, the nearest knowledge is pulled per content type and only that enters the prompt. This is where the rule "coverage beats volume" comes from.
- Mao, T. sqlglot, SQL parser and transpiler in Python, MIT license. github.com/tobymao/sqlglot The parser that turns the generated query into a syntax tree before any execution. It is what makes the guardrails possible: you inspect the structure of the query, not a string and refuse anything that is not a read.
- Pourreza, M. and Rafiei, D. (2023). "Evaluating Cross-Domain Text-to-SQL Models and Benchmarks", EMNLP. arXiv:2310.18538 Shows that benchmark scores underestimate models, because a natural-language question admits several correct queries. Justifies the choice of execution match over textual comparison, made here.
- Yu, T. et al. (2018). "Spider: A Large-Scale Human-Labeled Dataset for Complex and Cross-Domain Semantic Parsing and Text-to-SQL Task", EMNLP. arXiv:1809.08887 The benchmark that set the field's habits, starting with evaluation on databases never seen in training. The held-out control set described here is that idea transposed to the scale of a single customer.
- Li, J. et al. (2023). "Can LLM Already Serve as A Database Interface? A BIg Bench for Large-Scale Database Grounded Text-to-SQLs", NeurIPS. arXiv:2305.03111 The BIRD benchmark, built on real databases, dirty and large. It documents the gap between a syntactically correct query and a correct one, which is exactly the gap the column-domain bug exposed here.
- Zavaleta, G. (2026). "Why 90 % accuracy in text-to-SQL is 100 % useless", Towards Data Science. towardsdatascience.com Argues for per-category reading against the global score: a high average accuracy hides the family of queries that fails, which is the family deciding real-world usefulness. It is the reading that singled out joins and one filter here and made the targeted top-up possible.
- NVIDIA. NeMo Agent Toolkit, text-to-SQL, technical documentation. docs.nvidia.com Independently gives the same order of magnitude for the example corpus and the same requirement of validation on a held-out set. Two sources of very different origin converging on "twenty to a hundred well-chosen pairs".
- Brown, T. et al. (2020). "Language Models are Few-Shot Learners", NeurIPS. arXiv:2005.14165 The paper that established in-context learning: one example given inside the conversation is enough to steer the model, without touching its weights. Tabular foundation models transpose exactly that idea from text to tables.
- Hollmann, N., Müller, S., Purucker, L. et al. (2025). "Accurate predictions on small data with a tabular foundation model", Nature, 637, 319-326. 10.1038/s41586-024-08328-6 TabPFN, the German school. Establishes that a model pre-trained once on synthetic tables beats, in a single pass and with no tuning, methods fitted on the data itself. That is the result that makes this second story possible.
- SAP (2026). SAP Completes Prior Labs Acquisition, press release of 17 July 2026. news.sap.com The acquisition of the Freiburg laboratory, announced in May and closed in July 2026, with more than a billion euros committed over four years. Cited here as a measure of industrial interest in tabular models, not as a technical argument.
- Qu, J., Holzmüller, D., Varoquaux, G. and Le Morvan, M. (2025). "TabICL: A Tabular Foundation Model for In-Context Learning on Large Data", ICML. arXiv:2502.05564 The French school. Column-then-row attention builds a fixed-size representation of each row, which is what lets it hold much larger tables. On a par with TabPFN v2 across two hundred datasets, up to ten times faster and ahead beyond ten thousand rows.
- SODA team, Inria. tabicl, model code and weights. github.com/soda-inria/tabicl The concrete reason for the choice made here: pretraining code, inference code and weights are published, hence auditable and runnable on the customer's own machines, with no data leaving.
- "One-Half the Money I Spend for Advertising Is Wasted, But I Have Never Been Able To Decide Which Half", Quote Investigator, 11 April 2022. quoteinvestigator.com Traces the saying credited to John Wanamaker. The earliest known match is a 1919 speech already attributing it to him; neither the Wanamaker archives nor Unilever's, for the Leverhulme variant, hold any record of it. It is the source for the paragraph on attribution, and the reason this article presents the quotation as apocryphal rather than as a fact.
- Shapley, L. S. (1953). "A Value for n-Person Games", in H. Kuhn and A. Tucker (eds.), Contributions to the Theory of Games II, Princeton University Press, 307-317. The original paper, written to share a team's payoff among its members. It states the axiom that does the work: since the order of arrival changes each share, average over every order. Shapley received the Nobel Memorial Prize in Economic Sciences in 2012, with Alvin Roth. Sixty years separate this text from its use in machine learning.
- Lundberg, S. and Lee, S.-I. (2017). "A Unified Approach to Interpreting Model Predictions", NeurIPS. arXiv:1705.07874 Imports the Shapley value into machine learning, the rule that splits a collective payoff across players by average marginal contribution. Applied to a prediction, it says how much each variable weighed and in which direction.
- Ribeiro, M. T., Singh, S. and Guestrin, C. (2016). "Why Should I Trust You? Explaining the Predictions of Any Classifier", KDD. arXiv:1602.04938 Local surrogate explanation: the model is approximated, in the neighborhood of the single row under examination, by a simple readable one. Shown here beside the previous method, because two methods disagreeing on one row is a signal in itself.
- Bertin, J. (1967). Sémiologie graphique. Les diagrammes, les réseaux, les cartes, Gauthier-Villars. English edition: Semiology of Graphics, University of Wisconsin Press, 1983. The treatise establishing that a graphical form is not decoration but an encoding and that each visual variable has properties of its own. It is the foundation of the deterministic filter: a figure incompatible with the columns present must never be offered.
- Cleveland, W. S. and McGill, R. (1984). "Graphical Perception: Theory, Experimentation and Application to the Development of Graphical Methods", Journal of the American Statistical Association, 79(387), 531-554. 10.1080/01621459.1984.10478080 Ranks visual encodings experimentally by reading precision, position on a common scale ahead of length, itself ahead of angle and area. It is the measurement that justifies the rules applied automatically to this article's figures.
- Harchaoui, W. sprezzature-figures, open source figure engine. github.com/warith-harchaoui/sprezzature-figures The catalog of a hundred and twenty-seven chart kinds used on the last story and the checker that ships with each: contrast, stated polarity, labels that do not collide. The six figures in this article come out of it.
- pgvector, vector search extension for PostgreSQL, PostgreSQL license. github.com/pgvector/pgvector Lets the knowledge base live in the PostgreSQL already in place, so nothing new has to be deployed. That is what gives the improvement loop its persistence: validated examples survive restarts and are shared across every instance of the service.
- Kong, W., Louidor Ilan, E., Nie, S. et al. (2026). "TabFM: A Zero-Shot Foundation Model for Tabular Data", Google Research, 29 September 2026. arXiv:2609.37959 The third model of the kind, four hundred million internal dials, trained on synthetic tables drawn from causal models. Its result tables carry the TabArena ranking quoted here, where its three variants come ahead of TabPFN-3, AutoGluon and TabICLv2. Measurements run by the authors themselves on a public test bed, to be read as such.
- Google (2026). TabFM Non-Commercial License v1.0, license of the published weights. huggingface.co The text that settles the question for professional use. It restricts the model to non-commercial purposes, and its definition of the term rules out client deliverables, paid products or services and any revenue-generating activity by name, unless Google grants a commercial license. Compare with TabICL's BSD license, which imposes none of these conditions.
- SODA team, Inria. tabicl, license file. github.com/soda-inria/tabicl Three-clause BSD for the most part, with one declared exception: the forecasting directory is a derived work from TabPFN-TS and stays under an Apache license in Prior Labs' name. Concrete proof that the two schools read each other, in a document nobody writes for show.
Two books to widen the view. My favorite AI books, for the guided overview. Edward Tufte's The Visual Display of Quantitative Information, for everything the last story automates without being able to replace it: the judgment about which question the figure should ask.