AI Engineer World's Fair 2026
Semantic Blindness: 500,000 Sensors Confused an LLM - Raahul Singh & Vanč Levstik, Phaidra
Read the talk
Semantic Blindness: Resolving Equipment Queries Without Reading Every Name
Phaidra turns ambiguous infrastructure questions into structured retrieval plans, using compact hierarchy summaries and deterministic set operations to keep model work bounded.
From a talk by Raahul Singh and Vanč Levstik
Before you start: Familiarity with LLM context windows, embeddings, and basic set operations will help.
When equipment names stop fitting in context
Phaidra gave an LLM 500,000 sensor names, and it became confused. The task sounded straightforward: help a data-center operator identify a chiller running hot, analyze temperature distributions across data halls, or investigate GPU problems. But answering those questions starts with resolving exactly which equipment the user means. A question about chiller six targets one item; a question about GPUs in a data hall targets an entire group.
Equipment names do not follow a common industry convention. One customer may encode the data hall, rack, and GPU in a readable name; another may use an opaque identifier whose meaning depends on local knowledge. At demo scale, an LLM can inspect the complete list and infer a match. That approach makes the inventory itself part of every retrieval problem.
In Singh’s one-gigawatt example, a factory has more than 400,000 GPUs, plus power meters, chillers, and other supporting equipment. Passing all those names into a finite context window quickly becomes impractical. The production requirement also changes: finding a plausible match in one demonstration is insufficient when an omitted device can silently invalidate an operational answer.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Similarity does not establish identity
Embedding the equipment names for retrieval appears to remove the context-window bottleneck. But these identifiers carry meaning differently from ordinary prose. Two long names can differ by a single character that changes the physical device: chiller six is not chiller seven. In Phaidra’s experiments, semantic similarity did not preserve those distinctions reliably enough for accurate retrieval. A nearby vector is not necessarily the requested equipment, and finding several nearby vectors does not establish that every required device was found.
Direct enumeration created another failure mode. Consider a request to list roughly a hundred GPUs in aisle seven: the answer contains many almost identical token sequences. Singh reports that the model could stop before completing the list, attributing the behavior to repetition penalties or guardrails interpreting the output as a loop. That explanation is specific to the reported behavior, not a universal rule that repetitive output terminates every LLM. For this system, neither embedding-based name retrieval nor asking the model to produce the full inventory met the production requirement.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Sharding the inventory preserves the wrong task
The next attempt divided the inventory into shards and searched them through parallel LLM calls. This reduced the amount of equipment each call had to inspect, but it retained the underlying task: ask a generative model to identify and enumerate exact members of a large collection. Phaidra observed both phantom equipment that did not exist and silent omissions of equipment that did. Missing a device can hide a developing operational problem, allow it to cascade, and erode the operator’s trust.
Model work needed to grow with the infrastructure’s structure, not its instance count. A data center contains data halls, aisles, rows, racks, and GPUs. Cooling infrastructure has its own groupings, including chiller rooms, pumps, and cooling towers. These arrangements resemble trees whose width grows much faster than their depth. Adding more GPUs usually adds instances of a known equipment type, not a new kind of relationship the model must learn. That difference creates an opportunity for sublinear growth in model work.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Linearize the structure instead of listing the instances
The first architectural change is a linearizer: a compact textual representation of the systems graph that explains where equipment lives and how to reach it. Its purpose is to let the model map a vague request onto an equipment type or group without seeing every equipment node. Singh describes a one-gigawatt factory with more than a million such nodes. The useful context is the set of structural routes through that graph, rather than a separate description of every instance.
The illustrated routes to GPUs, chillers, and switches each traverse four layers. Expanding the inventory along those existing routes need not expand the description proportionally. Phaidra reports roughly equal summary sizes for systems with 64 and 460,000 GPUs. The summary gives the model enough information to understand the plant’s arrangement; the full inventory remains available to the retrieval backend.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Ask for a plan, not a list
The second change separates interpreting a request from executing a search. For a request to find all GPUs running hot in data hall eleven, the model does not need to read GPU names and decide which belong in the answer. It needs to specify how to construct the answer: select GPUs, restrict the scope to the data hall eleven subtree, and apply the relevant hot-running condition.
A compact representation of that plan is:
json
{
"equipmentType": "GPU",
"scope": {
"kind": "subtree",
"location": "data hall 11"
},
"filter": "running_hot"
}
Here, running_hot names a condition for the backend to resolve, not a temperature threshold invented by the model. Its meaning depends on the equipment and operational context. The structured output describes a proposed selection; it does not itself establish which GPUs satisfy it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resolve the plan with indexed sets
The third change moves retrieval into a backend with pre-indexed equipment subsets. These subsets capture locations and relationships between equipment: all GPUs in a data hall, equipment within a rack, or another relevant subtree. For the running example, the backend retrieves the GPU subset for data hall eleven, queries for GPUs that satisfy the hot-running condition, and intersects the two sets.
The intersection itself needs no model judgment. With equipment identifiers represented as strings, the core operation can be written directly:
typescript
function intersectEquipment(
scopedGpuIds: ReadonlySet<string>,
hotGpuIds: ReadonlySet<string>,
): Set<string> {
const result = new Set<string>();
for (const id of scopedGpuIds) {
if (hotGpuIds.has(id)) result.add(id);
}
return result;
}
const dataHall11GpuIds = new Set(["gpu-11-a", "gpu-11-b"]);
const hotGpuIds = new Set(["gpu-11-b", "gpu-12-a"]);
const result = intersectEquipment(dataHall11GpuIds, hotGpuIds);
// result contains only "gpu-11-b".
In this small example, gpu-11-a belongs to the requested hall but is not hot; gpu-12-a is hot but falls outside the requested scope. Exact membership testing excludes both. Singh describes set operations as providing perfect recall and accuracy. The guarantee applies to executing the operation over its supplied sets: correct intent interpretation, accurate indexes, and an appropriate definition of running hot remain separate requirements.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Turn vague references into executable patterns
Some requests are too vague to resolve through an obvious equipment type and location alone. The fourth change gives the model a narrower search responsibility: infer a pattern from the naming convention or the data, then hand that pattern to the backend for execution. The model sees enough naming structure to infer what to look for without receiving the complete name list. The architecture does not depend on a particular pattern language.
This keeps model token exposure relatively stable as equipment instances multiply. Reading every name would make model work grow with inventory size; describing a pattern can remain compact. The distinction concerns the model’s workload and reported operating cost. Index construction and backend pattern execution still have to handle the underlying equipment data.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Bound the query pipeline
The pieces form a short retrieval pipeline:
- Interpret the user query. A planner LLM determines the requested item or group and produces a search plan or pattern.
- Resolve the selection. Deterministic code uses indexes, pattern execution, and set operations to identify the matching equipment.
- Return the result set. The resolved collection becomes the concrete equipment selection for the request.
The boundary between the planner and resolver is the central design decision: the model specifies the search, while code determines membership.
Phaidra describes this as a two- or three-step process instead of an agentic loop that repeatedly searches and reasons. Bounded orchestration complements the compact context: neither the number of equipment names nor an open-ended sequence of model calls needs to determine the model’s total workload.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Test correctness and token cost separately
An elegant retrieval architecture still has to survive customer data, real load, and edge cases. Before exposing the new system to customers, Levstik’s team compared it with the old approaches using the same LLM and the same data, with three runs per case. The reported correctness results were:
| System size | Old approach | New approach |
|---|---|---|
| 64 GPUs | 80% correctness | 100% correctness |
| 460,000 GPUs | About 30% correctness | 100% correctness |
The new approach maintained that correctness across the tested scales, while the baseline degraded as the inventory grew.
Separately, Phaidra reports zero failures across 66 cases drawn from six real production systems. These are outcomes on the reported test cases, not a guarantee of error-free operation on arbitrary future queries.
The token comparison has two different denominators:
| Measurement | Old approach | New approach |
|---|---|---|
| One evaluation pass at one-gigawatt scale | 116 million tokens | 390,000 tokens |
| Per query at both 64 and 460,000 GPUs | Not stated | 9,000 tokens |
The evaluation-pass comparison represents approximately 300 times fewer tokens. The separate per-query result shows why the architecture matters as a customer grows: adding equipment did not increase the reported query token usage at those two scales. These figures describe token consumption, not a measured dollar price or a claim that backend computation is constant.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep judgment in the model and exact work in code
Levstik connects this division of responsibilities to Karpathy’s Software 1.0 and Software 3.0 framing. Software 1.0 is deterministic code: predictable and exact, but less flexible. Software 3.0 is behavior elicited through prompts: adaptable enough to interpret a request about hot GPUs, but fuzzy. In the legacy-software trend he describes, prompts increasingly replace work previously expressed as code. For a new AI-native system, maturation can move in the other direction.
The practical boundary follows the work’s requirements:
- Model judgment: parse ambiguous requests, decide where and what to search, handle unfamiliar phrasing, and synthesize the final human-readable answer.
- Deterministic execution: represent hierarchies, graphs, and schemas; retrieve equipment in bulk; apply exact set logic; count results; and deduplicate near-identical names.
If a structure or rule can be written down, code can execute it reproducibly. A language model scanning a well-structured inventory token by token discards precisely the information that makes conventional retrieval effective. Use the model where interpretation is necessary, and give it exact tools wherever the rules are known.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Productionize by adding reliable tools
Phaidra began with an almost pure Software 3.0 prototype, putting everything into the context window because that was a fast way to discover which behavior was worth building. As the system encountered real scale, the team moved known engineering problems into deterministic code while retaining difficult judgment in the LLM. For the use cases that justify it, AI-native software can therefore start with prompts and mature by adding Software 1.0.
Those functions do not replace model judgment; they give it reliable results and structure to work with. The resolver supplies an equipment set instead of asking the model to guess its members. Each exact tool removes another mechanical uncertainty from the model’s task.
Leave the hard decisions with the LLM. Implement the parts it should not be guessing about, then hand that structure back to it. Levstik’s closing formulation, after correcting himself, is to demo with Software 3.0 and productionize by adding Software 1.0.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
Further reading
Phaidra discusses why physical relationships, large context, and repetitive sensor data complicate industrial AI.
API reference for response fields, termination reasons, and validation of generated function arguments.
Read the complete timestamped transcript
- 0:00
Welcome everyone. My name is Raahul Singh. I'm a staff AI research engineer at Phaidra.
- 0:05
And I'm Vanč Levstik. I'm a senior engineering manager, also at Phaidra.
- 0:09
And today, we want to talk about the time when we gave an LLM five hundred thousand sensor names, and it got confused. We call this problem semantic blindness. At Phaidra, we build AI agents for AI factories.
- 0:22
This includes agents which allow our customers to talk about their data centers and explain to themselves and understand how the data centers are working and what problems they are facing on a day-to-day basis.
- 0:34
User queries can be anything from what chiller is running hot, to analyze the distribution of temperatures across my data halls, to is any of my GPUs facing any problems?
- 0:47
Now, from this variety of, uh, queries, you can see that these include talking about specific equipments, is chiller six all right, to talking about groups of equipments, GPUs in data hall one.
- 1:01
The industry has not really figured out a common naming pattern yet, and every si-single customer can have their own things. From simple names like, uh, racks with GPUs, with data halls, which give you an exact idea of where different things are, to something that is more difficult to comprehend, like CH3 something, something six.
- 1:21
We've seen all kinds of names, uh, in the industry going forward. Now, when you're building a demo system, uh, this works because you're working with at a small scale.
- 1:30
Uh, s-a simple LLM can, uh, look at all the names of your equipment and figure out what the, uh, user is talking about. But this problem really becomes intractable as you go to for scale.
- 1:42
For example, at one gigawatt scale factories, uh, you will see four hundred thousand plus GPUs, and to support those GPUs, you have power meters, you have chillers, you have other equipments.
- 1:53
LLM context windows are finite, and you will very quickly saturate, uh, them, and it just becomes a problem. Like we say, a product is something that works for all scenarios and does not fail silently.
- 2:03
A demo just has to work for one.
- 2:07
In addition to having the LLM figure out these names, uh, we could also have, uh, embedded them in a RAG database, uh, a vector embedding approach. But the problem is oftentimes the names are so similar that semantic search just fails.
- 2:21
Uh, there's very little difference between a vector of, sorry, a string name of twenty characters long, which is differs by, let's say, one character, chiller six instead of chiller seven or, uh, CPU something, uh, versus, well, something else.
- 2:35
It's very small, so you get a lot of, uh, problems with getting accurate, uh, recall. Also, LLM suffer from what we call a frequency, uh, penalty. If you keep on outputting very similar names over and over again, or very similar tokens, uh, more accurately over and over again, there are internal penalties in the LLM which just shut
- 2:55
off their output. So if the user says gi-- list all the names of, uh, let's say GPUs in aisle seven, and th-there are, let's say, a hundred. Just by listing th-through them, the LLMs, uh, guardrails would see, uh, would think that, well, it's spiraling, and it would just shut the system up.
- 3:13
So we can't really have these two approaches. RAG would not work. Just naive LLMs would not work. As we move into production systems, we need something that can scale as the system scales.
- 3:24
Now, there are naive solutions which we shall discuss going forward. A naive approach to solve this problem would be just to, well, divide and conquer. Take your different eq, uh, equipments, branch them in different shards and pass them through LLMs.
- 3:38
Uh, parallel calls should work, right? Well, that's what we thought. The problem is you get horrible recall and hallucinations. You will see LLMs invent phantom equipment that do not exist and also silently drop things that do exist.
- 3:53
Now, this creates a problem for mission, uh, critical systems where the users need to know exactly what is happening with their systems. Any problems there will quickly erode user trust.
- 4:03
At the same time, you will miss on specific problems which can cascade into bigger and bigger problems going forward. Anyhow, something that we realize here is that as the size of these, uh, physical infrastructure grows, LLMs cannot, uh, the LLM-based solutions cannot grow with the size of individual components or instances or nodes.
- 4:25
They-- we have to find something that grows sublinearly with increasing equipment count, and this is what we figured out. So we should not grow with instances, we should grow with tree depth.
- 4:36
Now, what do we mean by tree depth here? We realized that, uh, there's a hierarchical structure in which an AI factory is arranged. You will have data centers, then each data centers will have different data halls.
- 4:45
You will have dif-- Each of them will have different aisles, and you will have different rows and racks, and then GPUs. Similarly, a chiller plant will have, uh, rooms where chillers are arranged.
- 4:55
Then you will have pumps. There will be a separate cooling tower unit. It's kind of like a tree. The depth of the tree grows very slowly. The width grows extremely fast.
- 5:05
In other words, you will have a hierarchy that only adds new equipments very rarely, but it adds a lot of them when it does. You will have a lot of GPUs, but without GPUs, you won't have a lot of things.
- 5:18
Now, we realized that this could be used to solve our problems, and th-there are four insights that really come into the picture for this. One is a linearizer. What I mean by the linearizer is the LLM has to figure out where each of these things are arranged and how to map from a vague user query to specific
- 5:39
equipment or groups of equipments. Here, uh, a summarized representation of our systems graph can be really useful. For example, uh, if your, uh, a one gigawatt scale, uh, factory can have over a million nodes and each node represents a unique, uh, equipment.
- 5:57
But because you want to go from the root to the leaf, all you have to do is describe all the parts, and that's a very f-small finite list. For example, here, uh, you can see that to get to a GPU, you can just-- you just need four different, uh, layers to get to it.
- 6:13
To get to a chiller, similarly, uh, four layers. To get to switches, similarly, four layers.
- 6:19
With this, a sixty-four GPU, uh, layer, uh, s-sorry, a s-sixty-four GPU, uh, system and a four hundred and sixty thousand GPU system produce roughly the same size of summaries.
- 6:32
This consolidated, uh, context gives your LLM, uh, all it needs to know to figure out how the distribute-- h-how a plant is arranged and how different equipment are distributed in that plant.
- 6:44
The second insight that we had was LLMs are good for planning but not good for searching. This is, uh, what we realized when we saw very poor recall with our sharded solutions.
- 6:55
So instead of making the LLM sift through all the different fuzzy names that we can get from our users, we ask the LLM to f- uh, give us exactly how to look for them.
- 7:06
So for example, here the query says, "Give me all the GPUs that are running hot in data hall eleven." The LLM does not need to go through all these names of all our GPUs to figure out which one of those are in data hall eleven and then figure out how they are, uh, running hot.
- 7:20
All it needs to do is structured outputs, which tells us that, well, we need to collect, uh, GPUs. The scope under which we need to collect is a subtree, which is just data hall eleven.
- 7:32
And the filter that we need to apply to finally figure out what exactly we need is GPUs that are running hot. Now, this can be different things depending on the context, and you can implement different filters.
- 7:42
All we need to know is how do we create the set that we want to know, uh, get to. The third thing that we realized is that once you have a structured output to figure out what exactly you need, uh,
- 7:55
building the backend for it is relatively simple and straightforward. Now, all we need to do is create different, uh, subsets of, uh, our equipment or pre-indexed trees, as we like to call them, based on, uh, location and based on how they interact with other, uh, equipment around to get an idea of what you need to look at.
- 8:14
So for example, from the previous, uh, slide, we saw that we wanted to look at GPUs in data hall eleven. We could just get all the GPUs in data hall eleven in one pre-indexed subtree or other data halls, for example, or other racks, for example.
- 8:27
And then to get to the final result, all we need to do is, uh, run a query to find all GPUs that are running hot and take their intersection.
- 8:35
Set operations ensure that we have perfect recall and accuracy irrespective of, uh, how we want to filter, uh, the queries and what, uh, you know, fuzziness the user may have in their query.
- 8:48
Next slide, please. Yes. And finally, uh, what if you have something that is very, very vague? In which case, uh, you have to get the LLMs to, uh, get to searching.
- 9:01
But instead of searching directly with names, we figured out that getting the LLMs to, uh, give us patterns to look for. This could be, uh, patterns in the data, patterns in names, can be much more useful to figure out, uh, what the user is, uh, talking about instead of just passing the entire name list, uh, to the
- 9:18
LLM. The LLM never has to see a very large number of tokens. All it needs to do is, uh, see some patterns in the naming convention, figure out what exactly the user is talking about, create a pattern, and then we can execute it, uh, on the backend on ourselves.
- 9:35
This makes sure that the LLMs has a constant or relatively constant, uh, cost of operation. Whereas if we had to read through everything, we would have been scaling linearly with, uh, increasing equipment count, which itself grows exponentially as the size of the system increases.
- 9:54
Finally, to, uh, process a user query end to end, we go from the user's, uh, query, which could be anything from, uh, one equipment or a group of equipment to a planner LLM, which figures out user's intent and gives us a search pattern.
- 10:10
Uh, based on that search plan, we have a deterministic resolver which indexes, does set operations, figures out exactly what we need to do, and creates the final set that, uh, maps to the user's query, and this is what we call the result set.
- 10:25
All of this is a two or three-step process instead of, uh, a multi-step agentic loop which can keep on running over and over again. And this keeps our total cost also relatively flat and constant.
- 10:40
Cool. Yeah, um, if Rahul's job is to design the architecture, my job is production readiness. So [clears throat] we need to make sure that whatever we designed, the elegant solutions we came up actually hold up under real load, real customer data, and all the messy edge cases you only ever see in production.
- 10:59
So before any of this went near a customer, we put it through some extensive tests and evals. We measured the new system head to head against the old ones with same LLM model, same data, and we did three runs per case just to make sure.
- 11:13
Our goal was simple, prove that Rahul's solutions are ready for production. And they definitely are. If you look at some stats here, the old approach degraded pretty fast with scale.
- 11:24
So we got eighty percent correctness at sixty-four GPUs, and that dropped to about thirty percent when the GPU grew to four hundred-- six-- four hundred and sixty thousand. On the other hand, the-- our new approach has maintained correctness with hundred percent accuracy across all of those, um, tests that we give it.
- 11:42
And this is not just synthetic test, uh, this is also our real data. So we, we had sixty-six cases on six real production systems, and they product-- they produced zero failures as well.
- 11:56
And not just correctness, it's also dramatically lighter. So when we talk about one gigawatt scale, uh, data center, the old approach burned one hundred and sixteen million tokens for just a single evaluation pass while still having a lot of errors.
- 12:11
If you look at the new one, it's three hundred and ninety thousand tokens, which comes to around three hundred less tokens, fewer tokens. But the part that matters the most, the cost is flat.
- 12:22
As, as Rahul was talking about before, the, the system grows In size. But we, the cost of the query was 9,000 tokens a query where the system was 64 GPUs or 460,000.
- 12:35
So instead of getting the cost grow exponentially, w- when the customers grow their systems, it stays the same.
- 12:43
That's the impact. Now, there's something about, uh, what we learned, and the part I want you to take back to your own work. It starts with a lens from Karpathy.
- 12:53
Most of you have probably seen his presentation or his framing about this before. He talks about different kinds of software. Software 1.0 is a deterministic code you write. It's predictable, exact, but a lot less flexible.
- 13:06
On the other hand, we have Software 3.0, which is basically a behavior you prompt out of an LLM. In our case, that might be, "Show me the GPUs in data hall 11 that are running hot."
- 13:17
There, this is very flexible, smart, but it's a bit fuzzy.
- 13:22
Now, his observation was that in legacy software, the 3.0 is steadily eating 1.0. More of what used to be deterministic code becomes a prompt.
- 13:32
Just hold that picture, because the lesson for new-built AI-native sy- systems runs a little bit the other way.
- 13:41
But the real skill is knowing which work is the LLM not best for. And you always want to keep the thing- the L- LLM should be used for the things that it does well.
- 13:52
It's great at parsing on a biggest request, judging where to look for data and what to look for, handling phrasing we've never seen from a new user that has a different query, and at the end, also synthesizing and writing the final human-readable answer.
- 14:08
But, but everything you, you can data model, you should move into code. This is the key one, especially for large systems. If your data has structure, call it a hierarchy, graph, or a schema, a language model scanning it token by token is definitely the wrong tool.
- 14:24
Both retrieval, exact set logic, counting, DDAP across near identical names, which happens a lot in the data center land. Anything that, that must be 100% reproducible, it should be a deterministic code.
- 14:38
The simple heuristic that usually works, if you can write down the structure or, or the rules, it's a 1.0 job, and pure LLM is weakest exactly when the system is large and well-structured, which is precisely where we operate and our customers.
- 14:55
So in a sense, we ran Karpathy's trend backwards. We started almost pure 3.0. We threw everything in a context window because that is the fastest way to find out what's even worth building.
- 15:06
And as we said, it worked pretty well on a simple demo to start. Then, as it met real scale, we moved the parts that can be treated as known engineering problems into 1.0, and we still kept the hard judgment in the LLM.
- 15:21
So that's the inversion. Legacy software drifts from 1.0 towards 3.0, and new AI-native software starts at 3.0 and matures towards 1.0 for the use cases that earn it, of course.
- 15:34
We are not here to replace model judgment. We wanna feed it with the 1.0 tools as we call it. So every 1.0 function you add is more reliable ground for the LLM to stand on.
- 15:48
So to finish up, let the LLM keep the hard decisions. Everything it shouldn't be guessing on, add, add it in as code, and hand that structure back to the model to work with.
- 16:00
So demo with Software 3.0, productionize by adding in Software 3.0... 1.0.
- 16:08
Thanks for watching, everyone. Uh, any follow-up questions at all, you can reach us by email, Raahul, [REDACTED:email_address], [REDACTED:email_address], or you can drop them in the video comments below.
- 16:20
Thank you for watching.
- 16:22
Thanks.