Letting business users ask questions of company data, without the AI making things up
Let the language model interpret the question and explain the answer, and let deterministic code do everything that has to be right: the query, the validation, the lookup. That one split is the difference between a demo that impresses and a system a finance team will trust.
Why does natural-language access to data go wrong?
Almost never because the model cannot reason. It goes wrong because the model is asked to do three jobs at once: understand the question, find the right data, and produce the exact query or fact. The first job is what language models are good at. The other two need to be right every time, and a model that is right 95% of the time is wrong in front of a client every week.
We have built this pattern over four very different kinds of data, and the failure always arrives the same way: a confident answer built on a column the model guessed, a table it read as prose, or a code it half-remembered.
| Data | What users ask | Where it breaks without guardrails |
|---|---|---|
| Long PDF reports with charts and tables | “Summarise the 2024 risk-framework updates as a table” | Tables split mid-row, charts never indexed, sources lost |
| A wide deal database (100+ columns) | “Industrials in the southwest with LTV under 70%” | Invented columns, wrong synonyms, free-form SQL |
| EDI transactions (X12) | “What are the net terms on invoice 4471?” | Segment positions misread, codes guessed |
| An internal wiki | “How do we onboard a new school?” | Web results blended in unlabeled, gaps filled with guesses |
What should the model do, and what should code do?
Draw the line before writing a prompt. The split we use:
| The language model | Deterministic code |
|---|---|
| Understands the question and its business vocabulary | Builds and runs the query |
| Breaks a multi-part request into sub-questions | Validates fields, operators, ranges and codes |
| Chooses which tool or source to use | Matches records across systems (PO to invoice, EDI to ERP) |
| Writes the answer in plain English, with sources | Blocks anything that writes, logs every query |
On a deal-search build this meant the model never wrote SQL at all. It produced a filter plan such as {"primary_asset_type": "Industrial", "proposed_loan_to_value__lt": 70}, a schema rejected any field that does not exist, and version-controlled code turned the plan into a read-only query. Same question, same SQL, same rows, every time.
How do you close the vocabulary gap?
Before the system answers a single question, profile the data and describe it. For a database that means every column: type, null rate, cardinality, value ranges, top values. A model then writes a one-line description and a handful of synonyms per column at temperature zero, so “loan amount”, “LTV” and “southwest” resolve to real fields and real values.
Retrieval works from that profile, not from the raw schema: an entity index for exact names, vector search over the descriptions, and fuzzy matching for values (“york” finds New York). The output is a short summary of which tables, columns and values the question needs, and it is handed to the step that plans the query.
For EDI, the vocabulary gap is between teams: the business side says “invoice 4471”, the EDI side says “810”. Mapping business terms to transaction types is the first step, and a model fine-tuned on EDI vocabulary does the translating back into English.
How should documents with tables and charts be parsed?
By layout, before anything reaches a vector store. Detect the regions on each page: text, table, figure, caption. Crop each table and chart with its caption, read it with a vision model, and index the result alongside the image path, page number and file name. Text is chunked by meaning rather than by character count.
Two things follow. A question about a chart can be answered at all, and every answer can point to the page it came from. On a compliance library this was the whole point: an answer an auditor cannot cite is a liability, not an answer.
Retrieval then blends keyword and semantic search (we weight roughly 30/70), because names, codes and rule numbers are exactly what pure embeddings miss.
What if users ask vague questions?
They will, and retrieval suffers more than the model does. For an asset manager’s research assistant we benchmarked three rewriting strategies, each measured on what it retrieved against the unrewritten question:
| Question type | Strategy | How it helps |
|---|---|---|
| Vague, no keywords | Hypothetical answer (HyDE) | Drafts a plausible answer whose vocabulary matches the documents, then searches with it |
| Several questions in one | Rewrite, retrieve, read | Splits the request into separate queries before searching |
| Exploratory | Perspective follow-ups (STORM) | Proposes the follow-up questions the user would ask next |
No single strategy wins. Route by question type, and measure at retrieval rather than at the final answer.
How do you handle multi-part questions?
Real questions arrive as instructions: “summarise the risk updates, then put them in a table with Updated, Who is affected and Date.” A breakdown step splits these into sub-questions, and each sub-question is checked for relevance to the original before it runs, so the chain does not wander. An agent picks the tool for each part (retrieve, format as a table, search the wiki, calculate), and a final check asks whether the combined answer covers every part of what was asked.
For a table answer we score both the table and the plain retrieval answer for relevance and keep the better one, or refine the table from the retrieved text. The user sees one answer; the system has quietly picked between two.
How do you keep it trustworthy in production?
- Screen before retrieval. A safety check runs on every message before any data is touched.
- Label every source. Internal documents, the web and reference sources are tagged in the context and cited in the answer, never blended silently.
- Refuse well. When the data does not cover the question, say so. On an internal wiki bot, those refusals became the list of pages the team needed to write.
- Benchmark each component, not the whole. We test models side by side per step. On one build the larger model kept column descriptions, where quality drives matching, and a model about 90% cheaper took entity grouping, where it did as well or better.
- Log the plan, not just the answer. Parameters, the query that ran, the sources used. When an answer is questioned, you can show your working.
Frequently asked questions
Is text-to-SQL safe to put in front of business users?
Not as free-form SQL. Have the model produce a structured filter plan that a schema validates, then build a read-only query from it in code. Unknown fields are rejected and the same question always gives the same result.
Can RAG answer questions about charts and tables in PDFs?
Yes, if documents are parsed by layout first: tables and figures are cropped with their captions, read by a vision model and indexed with the page and file they came from. Treated as plain text, they are silently lost.
Do we need to fine-tune a model?
Usually not. Profiling and describing the data closes most of the vocabulary gap. Fine-tuning earns its cost on specialist formats such as EDI, where the vocabulary is unlike anything in general training data.
How do you stop the AI making things up?
Give it less to decide. The model interprets and explains; deterministic code queries, validates and matches; every answer carries its source; and “the data does not say” is an allowed answer.
The builds behind this guide, step by step.
When a platform is enough.
Before it gets tool access.
Citation-first retrieval, built and run.

About the author
Cat Yung is the founder of Super Cat Technology, an AI agent engineering team in Hong Kong and London, and works as an AI expert, data scientist and fractional CTO. Over a decade in production AI, NLP and machine learning; Expert-Vetted top 1% on Upwork with a 100% Job Success Score (source: Upwork profile, October 2026).