← Back to blog

Open source · Release

mnemiq: text-to-SQL you can tune to your database

/NEM-ik/ — the "m" is silent, as in mnemonic

mnemiq: text-to-SQL you can tune to your database

/NEM-ik/ — the “m” is silent, as in mnemonic

TL;DR

Before you trust AI on your company’s data, you should be able to test it on your own database, see where it fails, and improve it.

Text-to-SQL vendors publish accuracy numbers, but those numbers do not transfer across databases. They tell you little about how a system will perform on your data — and when it underperforms, the black box gives you little ability to understand why or fix it.

We built mnemiq, an open-source text-to-SQL engine that opens up that black box. You can change the model, retrieval, semantic layer, verifier, and other parts of the pipeline, then benchmark those choices on your own database.

We tested mnemiq on BIRD mini-dev, Spider 1.0, and Spider 2.0-lite, ranging from relatively clean benchmark schemas to much larger, messier ones. Using the same external grader, mnemiq scored higher than Snowflake Cortex Analyst and Databricks Genie on all three:

Text-to-SQL accuracy

got-facts on three public benchmarks · one external grader · three-run means where available
0%25%50%75%mnemiq · BIRD mini-dev: 64.9% got-facts64.9%Databricks Genie · BIRD mini-dev: 53.1% got-facts53.1%Snowflake Cortex Analyst · BIRD mini-dev: 48.9% got-facts48.9%BIRD mini-devmnemiq · Spider 1.0: 79.5% got-facts79.5%Databricks Genie · Spider 1.0: 77.5% got-facts77.5%Snowflake Cortex Analyst · Spider 1.0: 77.1% got-facts77.1%Spider 1.0mnemiq · Spider 2.0-lite: 59.8% got-facts59.8%Databricks Genie · Spider 2.0-lite: 45.5% got-facts45.5%Snowflake Cortex Analyst · Spider 2.0-lite: 24.2% got-facts24.2%Spider 2.0-lite
mnemiq Databricks Genie Snowflake Cortex Analyst
Full methodology, the stricter exact-match pairs, and per-question results are published below.

mnemiq was also more stable across identical runs: its case-flip rate was 2.2–4.1%, compared with 9.4–17.3% for Genie and 10.6–12.8% for Cortex Analyst.

The comparison is useful, but it raised a better question: why did performance move so much when we changed the model, the context, and the data?

The more useful results came from underneath that comparison. Across 28 configurations, fixing a SQL dialect bug helped more than most model-level techniques, spending more compute often made answers worse, and semantic enrichment was decisive on one dataset and worth almost nothing on another.

Our point is simple: no text-to-SQL accuracy number applies to your database until you run it on your database.

mnemiq is the engine and the evaluation harness for doing that.


Why we built mnemiq

Every text-to-SQL product has an accuracy number. Almost none of them were measured on a database that looks like yours.

A system can perform well on a benchmark and then struggle on your warehouse because the schema is larger, the naming is different, the business definitions are different, or the configuration that worked on the benchmark simply does not work as well on your data.

That makes the question we actually care about:

How well will this work on my database — and what can I change if it doesn’t?

We built mnemiq to make both parts measurable. It is Apache-2.0, can run inside your own environment on models you choose, and exposes the major parts of the text-to-SQL pipeline as settings.

The outcome is not just another accuracy score. You can figure out which model works best on your data, whether semantic enrichment is worth maintaining, how much retrieval context you need, how aggressively the system should refuse uncertain answers, and whether paying for more model or more compute actually improves anything.

This post is the experiment log behind those decisions. We tested models, retrieval depths, semantic-layer settings, fine-tunes, verifiers, and decoding strategies, then compared mnemiq with Snowflake Cortex Analyst and Databricks Genie using the same public benchmarks and the same external grader. Across the experiments here, beacon graded more than 25,000 answers.


How mnemiq works

At a high level, mnemiq separates SQL generation from the decision to actually run it. The model proposes SQL, then a deterministic layer checks it before anything touches the database.

The query has to:

  1. Be read-only
  2. Only reference objects the user is allowed to access
  3. Compile in the source database’s own SQL dialect
  4. Be able to pass an EXPLAIN

If any of those checks fail, mnemiq will refuse the query and tell you why.

Permissions are applied before schema retrieval, so the model is never shown tables the user isn’t allowed to see. Every answer also carries a trace showing what SQL ran, what tables it touched, and what enrichment version it used.

The semantic layer is configurable too

Before questions are asked, mnemiq can inspect the database and build more context around the schema. There are 3 levels to this:

Tier 0: tables and columns only
Tier 1: adds structural information like primary keys, foreign keys, and profiling
Tier 2: adds semantic information generated by an LLM — including table descriptions, column descriptions, grain, glossary terms, and coded-value meanings.

For production use, semantic definitions can also be reviewed and certified by a human owner.

We tested the different tiers separately so we could figure out: How much does a semantic layer actually help?

It turns out that the answer to that depends strongly on the database.

Cost is configurable too

mnemiq also lets you choose how much compute you want to spend on each question. The fast mode answers in one shot. The default mode gives a corrector up to three attempts to repair SQL if something fails. Deep mode generates five candidates and uses a judge and verifier to decide which answer to return, at roughly 6× the cost.

One of the more important things we found was that spending more compute did not always mean getting a better answer. In some cases it helped, and in others it actually made things worse. The verifier was the main exception: it was the only lever we tested that consistently reduced the wrong-answer rate.

That tradeoff is exposed as a setting because different applications have different risk tolerances. Some teams will want to answer as many questions as possible. Others would rather refuse more often if it means returning fewer wrong answers.


One engine, 28 configurations

Before comparing mnemiq against Snowflake or Databricks, we wanted to see how much performance changed just by changing the engine itself.

So we ran 28 configurations on BIRD mini-dev, varying the model, retrieval depth, decoding strategy, fine-tuning, semantic layer, self-consistency, and verifier.

The result was more interesting than we expected: a local 14B model on a single RTX 4090 matched the hosted frontier model, while several techniques that sounded like obvious improvements actually made performance worse.

The chart below shows the tradeoff between accuracy and latency across all 28 configurations.

Accuracy against latency

BIRD mini-dev · exact match · mean wall-clock per question
0%10%20%30%40%50%0s5s10s15s20s25s30s35sLatency per questionExact match frontier bestbest overallfrontier SC N=5no semantic layer14B guidedlowest wrong rate7B guideddefers 73.9%Frontier guided JSON: 47.7% exact, 10037 msFrontier retrieval k=12: 50.7% exact, 8427 msFrontier dialect fix, single-shot: 47.7% exact, 7410 msFrontier facts-only enrichment: 44.9% exact, 8686 msFrontier facts + examples: 40.3% exact, 8682 msQwen-14B guided + self-consistency N=5: 52.3% exact, 18228 msFrontier pre-retrieval single-shot: 40.5% exact, 8084 msFrontier self-consistency N=5: 43.7% exact, 34173 msFrontier pre-dialect baseline: 40.7% exact, 8004 msQwen-14B guided, no semantic layer: 52.2% exact, 6037 msQwen-32B guided JSON: 50.3% exact, 8482 msQwen-14B guided JSON: 50.9% exact, 3719 msQwen-14B QLoRA guided JSON: 50.7% exact, 8710 msQwen-14B QLoRA-800 baseline: 51.5% exact, 9023 msQwen-14B QLoRA baseline: 51.1% exact, 8937 msQwen-14B verifier on: 48.5% exact, 7120 msQwen-14B QLoRA-800 guided JSON: 49.7% exact, 8889 msQwen-32B verifier on: 46.1% exact, 10403 msQwen-14B assertive prompt (fixed): 44.8% exact, 3433 msQwen-32B baseline: 43.7% exact, 7152 msDeepSeek-V2-Lite baseline: 37.6% exact, 9842 msQwen-14B guided JSON (pre-fix): 35.9% exact, 4821 msQwen-14B assertive prompt: 33.9% exact, 3620 msQwen-7B guided JSON: 33.9% exact, 3277 msQwen-7B QLoRA guided JSON: 19.7% exact, 4355 msQwen-7B QLoRA baseline: 19.3% exact, 3217 msQwen-14B baseline: 17.0% exact, 5578 msQwen-7B baseline: 6.4% exact, 1367 ms
Local, open weights Hosted frontier Efficient frontier
The dashed line is the efficient frontier: the configurations where no other setup was both faster and more accurate.

Most of the best speed/accuracy tradeoffs came from local open-weight models. In other words, for many points on the chart, there was no hosted configuration that was both faster and more accurate.

The most obvious outlier is the hosted model using five-sample self-consistency at around 34 seconds per question. It used roughly four times as much compute as asking the same model once, but scored about seven points worse.

That became a recurring theme: more model, more context, or more compute did not automatically mean better text-to-SQL.

One thing to keep in mind: this grid was part of the search process, not the final shipped configuration. Most rows change one setting at a time so we could isolate its effect. The configuration used later in the vendor comparison combines several of the settings that worked best, which is why its final BIRD score is higher than any individual row here.

We also publish the configurations that did not work. If we only showed the winners, you would not be able to tell which changes actually helped and which ones were dead ends.

Four things we did not expect

A 14B local model matched the hosted frontier model. Qwen2.5-Coder 14B scored 50.9% exact match on BIRD in a single-shot run. The hosted frontier model’s best comparable grid result was 50.7%. The 14B model ran locally on a single RTX 4090 and answered in about 3.7 seconds per question. With five-sample voting, it reached 52.3%. We are not saying a 14B model is generally better than a frontier model. It obviously is not. What this showed us is that model size and model reputation alone are not enough to predict text-to-SQL performance. The rest of the system matters a lot.

The 32B model did not improve accuracy. Going from 7B to 14B helped a lot. Going from 14B to 32B did not. Qwen2.5-Coder 32B scored 50.3% with guided decoding, slightly below the 14B model at 50.9%, while requiring an A100 instead of a 24 GB consumer GPU. The 32B model did have one advantage: with the verifier turned on, it reached the lowest wrong-answer rate in the entire grid at 25.7%. But it got there by refusing about a quarter of the questions. That is why we think right, wrong, and refused need to be reported separately. A single accuracy number hides a lot of how the system actually behaves.

One of our biggest improvements came from fixing the SQL dialect. Around 35 logically correct queries were failing because the engine was generating SQL in one dialect and executing it against another. Fixing that improved the hosted frontier model by about seven exact-match points — a larger gain than most of the model-level techniques we tested. That was a useful reminder that a lot of text-to-SQL performance comes from things that look like plumbing until you measure them. It is also why mnemiq exposes those parts of the pipeline instead of hiding them behind one API call.

Accuracy and wrong-answer rate are not the same thing. Two systems can have the same exact-match score and still behave very differently. At exactly 33.9% exact match, the 7B model was wrong on 39.4% of questions. The 14B model, at the same exact-match score, was wrong on only 19.5%. The hosted frontier model’s best grid cell was wrong 48.2% of the time and refused only 1% of questions. In other words, it almost always attempted an answer, even when that answer was wrong. The verifier was the only setting we tested that consistently pushed the wrong-answer rate down. On the 14B model, it reduced wrong answers from 38.8% to 32.4%. On the 32B model, it got the wrong-answer rate down to 25.7%, but with much lower coverage. There is no universally correct point on that tradeoff. It depends on what you are building and how costly a wrong answer is.

The full matrix · 28 configurations

Exact partitions with deferred and wrong to 100% · got-facts overlaps it · all cells read live from the tracker’s current grading
ModelConfigurationnExactDeferWrongGot-factsms
Qwen-14Bguided + self-consistency N=548652.3%7.8%39.9%57.0%18,228
Qwen-14Bguided, no semantic layer48752.2%9.4%38.4%55.2%6,037
Qwen-14B QLoRA-800baseline48751.5%7.8%40.7%52.2%9,023
Qwen-14B QLoRAbaseline48751.1%10.3%38.6%52.4%8,937
Qwen-14Bguided JSON48750.9%10.3%38.8%54.0%3,719
Frontierretrieval k=1248350.7%1.0%48.2%63.4%8,427
Qwen-14B QLoRAguided JSON48750.7%12.5%36.8%52.4%8,710
Qwen-32Bguided JSON48750.3%9.0%40.7%53.6%8,482
Qwen-14B QLoRA-800guided JSON48749.7%11.9%38.4%50.9%8,889
Qwen-14Bverifier on48748.5%19.1%32.4%52.2%7,120
Frontierguided JSON48647.7%1.0%51.2%63.2%10,037
Frontierdialect fix, single-shot48247.7%5.4%46.9%61.4%7,410
Qwen-32Bverifier on48646.1%28.2%25.7%49.2%10,403
Frontierfacts-only enrichment48344.9%4.6%50.5%61.3%8,686
Qwen-14Bassertive prompt (fixed)48744.8%17.5%37.8%47.8%3,433
Frontierself-consistency N=548343.7%12.6%43.7%54.2%34,173
Qwen-32Bbaseline48743.7%23.4%32.9%46.6%7,152
Frontierpre-dialect baseline48240.7%13.5%45.9%53.5%8,004
Frontierpre-retrieval single-shot48440.5%13.2%46.3%53.7%8,084
Frontierfacts + examples48140.3%4.2%55.5%60.7%8,682
DeepSeek-V2-Litebaseline48737.6%18.1%44.4%41.9%9,842
Qwen-14Bguided JSON (pre-fix)48735.9%41.1%23.0%37.6%4,821
Qwen-14Bassertive prompt48733.9%46.6%19.5%35.5%3,620
Qwen-7Bguided JSON48733.9%26.7%39.4%35.1%3,277
Qwen-7B QLoRAguided JSON48719.7%56.9%23.4%19.9%4,355
Qwen-7B QLoRAbaseline48719.3%62.2%18.5%19.5%3,217
Qwen-14Bbaseline48717.0%73.9%9.0%17.7%5,578
Qwen-7Bbaseline4876.4%92.0%1.6%6.6%1,367

The practical takeaway from this grid is simple: on BIRD, a local 14B model running on one RTX 4090 was competitive with the hosted frontier model through the same engine. But that result did not hold uniformly once we changed the data. That is exactly the point of making these settings measurable.


Where the gap gets bigger: large schemas

Spider 2.0-lite

BIRD and Spider 1.0 are useful benchmarks, but their schemas are relatively clean compared with what most enterprise teams actually deal with.

Spider 2.0 is much closer to the shape of a real warehouse. The schemas are larger, there are many more columns, and the system has to retrieve the right part of the schema before it can even start writing the SQL.

That is also where the gaps between systems became much larger.

EnrichmentBIRD mini-devSpider 1.0Spider 2.0-lite
tier 2 semantic52.2 / 64.968.4 / 79.536.6 / 59.8
tier 1 structural50.8 / 63.869.0 / 80.136.2 / 59.2

The numbers above are exact match / got-facts.

One of the more interesting results here is that the semantic layer did not help equally on every benchmark. On BIRD, it added around a point. On Spider 1.0, it basically did nothing. On Spider 2.0, it helped a little more.

The biggest improvement from semantic enrichment actually came from an in-domain dataset, not a public benchmark. When we gave the system certified business definitions, performance landed around 69–72%. Without those definitions, it was around 51.7–58.6%.

That makes sense when you look at what semantic enrichment is actually doing.

If your schema already contains most of the meaning the model needs, more descriptions may not help much. If you have columns like rev_amt, rev_amt_net, and rev_settled, and different teams casually call all three “revenue,” then the definition matters a lot.

That is why mnemiq does not assume everyone needs the same semantic layer. It gives you the setting and the evaluation harness so you can measure whether the extra work is actually worth it on your database.


Accuracy is not enough if the answer changes every time

A system can have a respectable average accuracy score and still be hard to trust in production if the same question gives you a different answer every time you ask it.

So we measured stability: ask the exact same questions in separate runs and count how often the verdict changes.

Systemcase-flip rate between identical runs
mnemiq2.2–4.1%
Genie9.4–17.3%
Cortex Analyst10.6–12.8%

mnemiq’s case-flip rate was 2.2–4.1%. Genie’s was 9.4–17.3%, and Cortex Analyst’s was 10.6–12.8%.

Put differently, roughly one in eight vendor answers changed between identical runs in some pairings. That matters operationally. A dashboard, analyst, or agent that gives a different answer on Tuesday and Thursday is difficult to trust even if its average benchmark score looks good.

We think mnemiq is more stable partly because most of the pipeline after SQL generation is deterministic. The model’s randomness is concentrated in fewer places.

Neither Snowflake nor Databricks currently publishes a stability number for these products. We think they should. dbt Labs already moves in this direction by repeatedly running questions in its semantic-layer benchmark and reporting which stay consistent.


How mnemiq compared with Snowflake and Databricks

We did not want the vendor comparison to be the main point of this article.

A benchmark run by one of the products being compared deserves skepticism, including ours. So if we were going to publish the comparison, we wanted the setup to be as inspectable as possible.

Each product ran on its own platform with its own semantic tooling. We used the same benchmark questions, the same external grader, and three runs per cell where possible. We also publish the per-question results so you can inspect the SQL and outputs rather than trusting the summary table.

SystemBIRD mini-devSpider 1.0Spider 2.0-lite
mnemiq (tier 2, GPT-5.5)52.2 / 64.968.4 / 79.536.6 / 59.8
Databricks Genie37.4 / 53.163.6 / 77.527.3 / 45.5
Snowflake Cortex Analyst33.3 / 48.956.4 / 77.117.4 / 24.2

Again, these are exact match / got-facts.

mnemiq scored higher on both metrics across all three benchmarks. The largest gap was on Spider 2.0-lite, where got-facts was 59.8% for mnemiq, 45.5% for Genie, and 24.2% for Cortex Analyst.

But we want to be careful about what that result does and does not prove.

The vendor models are undisclosed. Part of the difference may come from model choice. Part may come from the semantic setup. Part may come from architecture. And none of these benchmarks tells you exactly what will happen on your own warehouse.

So we see the vendor comparison as evidence for the larger point, not the point itself.


What we did to make the comparison fair

Cross-vendor benchmarks are easy to get wrong. We found that out several times while running this one.

Instead of quietly fixing problems and publishing the final table, we kept track of the issues we found and how we handled them.

We kept the benchmark queries unchanged
The gold SQL from the benchmarks was never rewritten to make it work better for one platform. For example, Snowflake uppercases unquoted identifiers while some of the source benchmarks were built around SQLite behavior. Instead of changing the benchmark SQL, we changed how we loaded the schema so the original queries would still run. That way the benchmark itself stayed the same.
We restored the declared keys
Some of the benchmark formats lose primary-key and foreign-key information when they are loaded into a warehouse. That matters because Cortex Analyst uses declared relationships to reason about joins. If those keys disappear during loading, the product can refuse questions it should have been able to answer. So we replayed the primary and foreign keys from the benchmark metadata onto both warehouse setups.
We found and fixed a problem that was hurting Genie
Our original Databricks load had a type mismatch that caused around 20 foreign keys to disappear. Once we found it, we fixed the loader, restored the keys, and reran Genie. That improved Genie’s result by about half a point. The table above uses the repaired result. There are another 73 relationships that Unity Catalog cannot represent because of how it handles foreign keys and uniqueness constraints. We disclose those instead of trying to work around them in a way that would make the comparison harder to reproduce.
We handled Genie’s 30-table limit
One Spider 2.0 schema contains 38 tables, but a Genie space can only contain 30. Rather than manually picking whichever 30 tables looked most useful, we kept the largest connected component of the foreign-key graph. That preserved as many real join paths as possible. We also disclose which tables had to be dropped.
We caught a benchmark that was incorrectly giving a vendor 0%
At one point, a dotted namespace in Unity Catalog caused one benchmark to score Genie at exactly 0%. The run looked legitimate until we inspected what had happened. We fixed the harness and regraded the original answers without changing them. The result went from 0% to 66.7%. The vendor was never actually that bad, so we do not publish the zero. This kind of issue is also why we think per-question results matter. A summary score can look completely believable even when the harness underneath it is broken.

A note on Cortex Analyst refusals

Cortex Analyst refused 27 of the 135 Spider 2.0 questions. We manually read all 27 refusal messages. Twenty-four were caused by missing join metadata, two were genuine inability to answer, and none were clarification requests.

We still report the result as the product behaved under that setup, but we think the reason for the refusals matters. The benchmark score alone would not tell you that.

A note on the grader

Every number in this article depends on what we decide counts as correct, so we also spent time testing the grader itself.

Partway through the project, we tightened the exact-match rule so column order became part of the score. Instead of mixing results from the old and new grading rules, we re-executed and regraded every stored prediction from every system. That reduced exact-match scores by between 1.4 and 5.7 points depending on the system. Got-facts barely moved.

That is one reason we put more weight on got-facts in the comparison. It was much less sensitive to changes in the grader.

As a second check, we wrote two separate implementations of the got-facts logic and ran them against 414 constructed examples. They agreed on all 414.

The fine print

There are a few things worth knowing before reading too much into any individual number.

  • The underlying models used by Snowflake and Databricks are undisclosed, while mnemiq’s model is stated. Some part of the difference may simply come from model choice, and this benchmark cannot separate that out.
  • Spider 2.0 also does not define a standard exact-match rule, so the got-facts number uses the benchmark’s own containment metric while exact match uses our stricter rule for consistency with the other tables.
  • The Genie numbers are from the repaired setup after we fixed our own foreign-key loading issue. We intentionally use the better result.
  • The grader shown here is beacon v7, and the numbers in the article come directly from that tracker. There is no extra post-processing step between the tracker and the published table.
  • mnemiq also uses more model calls per question than the vendor APIs. With repair enabled, it averages around 2.3 LLM calls per question, while we call each vendor API once. That is part of the architecture and should be considered when comparing cost.
  • Finally, the graded denominator varies slightly between runs because errors and unmapped benchmark items are excluded instead of being counted as wrong. The case IDs are published so anyone who wants to compare on the exact same intersection can do that.

What each setting actually does

The full matrix compresses a lot of the experiment into short configuration names, so below is what each major setting actually changes and what happened when we tested it

Generation

Guided JSON
We constrain the decoder to return a JSON object with a non-null SQL field. We added this because the untuned 14B model was refusing 73.9% of BIRD questions. With constrained decoding, exact match went from 17.0% to 50.9%. The tradeoff is that many of those refusals turned into attempts, and some of those attempts were wrong. The wrong-answer rate went from 9.0% to 38.8%. So guided decoding increased coverage dramatically, but it did not magically make the model more correct.
Assertive prompt
This was the softer version of the same idea. Instead of forcing an output shape, we told the model to make a best effort rather than refuse. Exact match improved from 17.0% to 33.9%, but again the wrong-answer rate also went up. We eventually preferred constrained decoding because it moved the system further.
Self-consistency
We generated five queries, executed all five, and voted based on the results. It helped the local 14B by about 1.4 points, but it made the hosted frontier model worse while costing roughly four times as much. The main reason seems to be that text-to-SQL mistakes are often systematic. If the model misunderstands the question in the same way five times, voting does not help. One useful thing did come out of it: agreement between candidates is a reasonable confidence signal.
QLoRA fine-tuning
We fine-tuned Qwen on BIRD’s training split. The tuned models reached around 51.1–51.5%, only slightly above the untuned model with constrained decoding at 50.9%. It also made Spider worse, which is a pretty clear sign of overfitting to BIRD. For us, fine-tuning ended up looking more useful as a serving option than as an accuracy breakthrough.
Model size
Going from 7B to 14B added about 17 points. Going from 14B to 32B slightly reduced accuracy while requiring much more hardware. The takeaway is not that model size never matters. It clearly did from 7B to 14B. It is that the relationship is not monotonic, and bigger is not automatically better for a specific database workload.

The plumbing

SQL dialect handling
This was one of the highest-impact fixes we made. The engine had been generating SQL in the wrong dialect for some sources, which caused around 35 otherwise-correct queries to fail. Fixing it improved the hosted model by around seven exact-match points. It was a bigger gain than most of the model-level techniques we tested.
Retrieval depth
This controls how much schema context enters the prompt. On BIRD, going from k=6 to k=12 improved exact match by about three points and reduced refusals. On larger schemas, the same strategy could make things worse. We saw cases where showing the model more of the correct schema actually increased wrong answers because the prompt became noisier. More context is not always better context.
Context window
Increasing the context window from 8k to 32k eliminated a 17% context-overflow rate in one setup. On a 24 GB card, the 32B model could not fit a large enough usable context window and overflowed on 45% of schemas. Again, this looks like serving infrastructure until it starts changing the benchmark score.

The semantic layer

Enrichment tiers
Tier 1 adds structural information like keys and profiling. Tier 2 adds LLM-generated semantic information like descriptions, glossary terms, and grain. On BIRD, tier 2 added around 1.4 exact-match points. On Spider 1.0, it did essentially nothing. For one weaker model, the richer semantic cards actually hurt slightly because they made the prompt much longer. So we do not think a semantic layer should be treated as free accuracy. It helps when the extra meaning is actually needed.
Certified definitions
This is where semantics made a much larger difference. A human owner can certify a metric definition, for example revenue = sum(amount_settled), along with its grain and rules. When a question uses that concept, the model selects the metric, dimensions, and filters, while a deterministic composer builds the SQL. On an in-domain dataset where those definitions mattered, performance moved from roughly 51.7–58.6% without certification to 69–72% with it. At the same time, a control set of questions that were already answerable from the schema stayed at 100%. That is the behavior we were hoping to see: semantic work helps where semantics are actually missing.
Coded-value grounding
Real databases contain values like CUST_STAT_CD='A'. We do not want the model guessing that A means “active.” mnemiq only attaches a meaning when it has evidence from the database, a lookup table, a dictionary, or another configured source. If two sources disagree, it leaves the value unresolved instead of picking one. This was mostly neutral on BIRD, but it removed a class of hallucinations that matters much more in real databases.
Few-shot examples
We also tried retrieving previously verified question/SQL examples into the prompt. On the hosted frontier model, it reduced exact match by 5.1 points. So we parked it. This is one of several settings that sounded like an obvious improvement and turned out not to be one.

After the SQL is generated

Logic lint and repair
mnemiq checks generated SQL for a small set of patterns that are likely to be wrong. If it finds one, it gives the model a bounded chance to repair the query. The benchmark impact was small, but we kept it because it fixes a real class of failures.
Value grounding
We maintain an offline index of values that actually exist in the database. If the model generates a literal that does not exist, the query can be sent back for repair. In one test of 421 executed queries, there were zero remaining wrong-literal errors after this check. It did not move BIRD much, but it is much more relevant on production data.
Selector judge
We tried generating several candidate queries and asking another model to choose the best one. It improved strict exact match by about three points, but almost all of the gain came from fixing output shape. Got-facts stayed basically flat. We parked it because we do not want to optimize the product around a quirk of one metric.
Selective answering
We can refuse a question when candidate agreement is too low. That improved precision, but roughly five points of extra precision cost around 30% of coverage. We expose that as an option rather than pretending there is one right threshold for everyone.
Difficulty routing
We considered training a classifier that would decide which questions deserve the more expensive deep mode. Before building it, we measured the best-case upside. Even a perfect router would only have added about 4.5 points in our calibration, and the deeper mode’s gains were not concentrated on the hardest questions anyway. So we did not build it. We expose the execution modes directly instead.
The verifier
The verifier runs after generation. It checks for obviously bad results, grounding issues, and then uses a model-based judge for the remaining cases. If an answer looks too risky, mnemiq refuses instead of returning it. This was the only setting that consistently reduced the wrong-answer rate. On the 14B model, wrong answers fell from 38.8% to 32.4%. On the 32B model they fell as low as 25.7%, although with much lower coverage. The verifier helps, but it has a clear ceiling. It sees roughly the same information the generator saw, so it cannot catch every bad interpretation after the fact. You cannot verify your way to perfect accuracy.

How to read the configuration names

baseline means the default mode with no extra settings enabled. guided_json is constrained decoding. assertive is the attempt-rather-than-refuse prompt. SC N=5 is five-sample self-consistency. verify means the verifier is on. k12 and k24 are retrieval depth. qlora and qlora800 are the fine-tuned adapters. dialect fix means source-native SQL generation and execution. single-shot means one candidate and one attempt. The local rows ran quantized open-weight models on an RTX 4090. The larger local setup used an A100.

Six of the fourteen major levers we measured were flat or negative. We left them in because failed experiments are part of the result too.


Run it on your schema

None of the numbers in this article tell you what will happen on your warehouse. That is not a disclaimer around the benchmark. It is the main finding.

We saw the best configuration change when we changed the data. Semantic enrichment mattered a lot in one environment and barely mattered in another. A local 14B model matched a hosted frontier model on BIRD, but that does not mean it will do the same thing on your schema.

So the goal is not to replace Snowflake’s benchmark with ours. The goal is to get your own number — and, more importantly, understand what is behind it.

You do not need a huge evaluation program. Take one meaningful slice of your schema and write 20–30 questions people actually ask. Tag each one as answerable from the schema, requiring a business definition, or something the system should refuse.

Then test a few meaningful choices: enrichment on and off, a local and hosted model, maybe two verifier thresholds. Run each setup at least twice and report right, wrong, and refused separately.

What you end up with is more useful than a vendor accuracy number. You know which setup performs best on your data. You know where it fails. You know whether semantic work is actually helping. You know how often it gives a wrong answer instead of refusing. And you know whether paying for a larger model or more compute is buying you anything.

If definition-heavy questions fail, you have evidence that better semantic documentation is worth the work. If everything works fine without enrichment, you have evidence that you do not need to build and maintain a heavy semantic layer. If a small local model performs just as well as a hosted one, you can make that infrastructure decision with data instead of guessing.

That is what mnemiq is for: not giving you another accuracy number, but giving you the tools to find the text-to-SQL system you can actually trust on your database.


What's next

This is not the end of our work on text-to-SQL. We are still measuring the parts of this system we have not measured yet, and there is more to come on databases, semantics, and the agents that read them.

Keep up with us on LinkedIn, on X, and here on this site for future launches.

We’re Agentic Fabriq (YC W26). If you run mnemiq on your own database, we’d love to see how it performs — especially where it does worse than the benchmarks above. That is the part we cannot learn without your data.