Result Analysis
Data retrieval alone is often insufficient. Users need to see patterns, comparisons, and trends to draw conclusions. Language Models can be helpful in interpreting results if utilised correctly.
Retrieving data from a database is only the first step. A database query returns rows and columns, but the user asked a question. The gap between raw tabular data and an actionable answer is where analysis and visualisation come in.
Consider a query that returns 250 rows of weekly energy consumption across 10 buildings. The raw result answers "what is the data?" but not the questions the user likely cares about: Which building consumes the most? Is consumption trending up or down? How does this week compare to the previous one? Are there outliers?
The Problem with LLMs and Numbers
A natural instinct is to pass query results directly to a language model and ask it to analyze them. This approach fails for several reasons.
Tokenization and Numerical Reasoning
Language models process text as tokens, not as numbers. The number "1,247.83" is not represented internally as a floating-point value but as a sequence of tokens (e.g. "1", ",", "24", "7.8", "3") . This representation is fundamentally unsuited for precise arithmetic.
LLMs are able to do calculations but should be generally be treated as unreliable for tasks like:
Summing columns of numbers
Computing averages, medians, or percentages
Comparing values across rows with precision
Detecting small but meaningful differences
The error rate increases with the number of values involved and the precision required. For analytical tasks where numerical accuracy matters, LLM-generated calculations are not trustworthy.
Context Window Saturation
Passing large result sets into an LLM's context window creates additional problems:
Attention dilution: as the context fills with hundreds of data rows, the model's ability to reason about any individual row or pattern degrades.
Context limits: large result sets can exceed the available context window entirely, or consume so much of it that the model cannot generate a useful response alongside the data.
Cost and latency: processing thousands of tokens of tabular data is slow and expensive, especially when the model then produces an unreliable analysis of that data.
The conclusion is clear: LLMs should not perform numerical computation on raw data. They should decide what to compute, and delegate the actual computation to deterministic tools.
Deterministic Result Inspection
The principle behind deterministic result inspection is a clean separation of concerns:
The LLM decides which analytical operation to apply and on which part of the data (e.g. "compute the top 3 buildings by total energy consumption and compare each to the group average").
A deterministic tool executes the operation with exact arithmetic on the full result set and returns the computed values.
The LLM interprets the tool's output and incorporates it into the response.
The LLM never sees all raw rows. It sees a small preview (enough to understand the data structure) and then works with the deterministically computed results from the inspection tool.
Result Set Inspection / Analysis:
letting a LLM analyze raw data is seldomely a good idea (concept of tokens and numbers!!)
dumping hundreds of rowas of raw data will fill up the available context very quickly and lead to accuracy degradations
it should be avoided to let it do numerical computations wherever possible
instead give it a handy set of tools and functions that it can apply deterministically on result sets (these do the actual computations) the llm just decides which function to use and on what part of the data and only sees the result computed by the function
Example Operations:
Aggregation
Sum, mean, median, min, max, count
"What is the average temperature across all rooms?"
Ranking
Top N, bottom N, row with max/min
"Which building consumes the most energy?"
Comparison
Compare to group mean/median, cross-column delta,period-over-period change, baseline deviation
"How does Building A compare to the portfolio average?"
Contribution
Percentage share of total, contribution by group
"What share of total energy does each building account for?"
Profiling
Null report, schema inspection, value distribution
"Are there sensors with missing data?"
Temporal
Period-over-period diff, percent change, rolling stats
"How did energy consumption change month over month?"
Derived Result Sets
Some inspection operations produce not just scalar values but new tabular result sets. For example, computing the month-over-month percentage change per building produces a new table with the original grouping columns plus computed delta columns.
These derived result sets can be:
Used as input for further inspection operations (chaining)
Passed to a visualisation subagent for charting
This chaining capability means complex multi-step analyses can be built from simple, reliable primitives - without ever asking the LLM to do arithmetic.
Visualisation
The Mapping Problem
Generating a useful chart from a SQL result requires solving a multi-dimensional mapping problem:
What does the user want to understand? (comparison, trend, distribution, composition)
What is the structure of the data? (time series, categorical, matrix, single metric)
Which chart type best represents this combination? (line, bar, pie, heatmap, scatter)
How should data columns map to visuals? (x-axis, y-axis, series grouping)
How much data is needed? (are 10 preview rows sufficient, or does chart quality require the full result set?)
A rule-based chart generator can handle simple cases (one time column + one metric column -> line chart). But real-world data analysis produces diverse result shapes:
Multiple metrics with different units on the same time axis
Grouped categories where series should be split by a column value
Matrix-shaped data that could be a heatmap or a set of grouped bars
Results where only a subset of columns are meaningful for charting
A visualisation subagent handles this diversity by receiving:
The result set structure (columns, types, row count)
A high-level visualisation intent from the orchestrator (e.g. "compare buildings over time", "show distribution of temperatures")
Optional baselines or display preferences
It then independently decides:
How many charts to generate
Which chart type(s) to use
How to map columns to charts (axes, series, categories)
Display options (stacking, orientation, sorting, null handling)
The output is a structured visualisation plan, a declarative specification that can be compiled into a larger chart configuration. Instead of writing the full chart configuration code or generating an image it produces a mapping configuration that translates the data's structure into a visual structure.
Users can override these decisions, but the default behavior is designed to produce useful visuals without requiring manual chart configuration. A visualisation subagent operates on the same principle as other agentic integrations: the user states what they want to understand, and the system handles the technical translation.
Last updated