Turning “it’s too hot” into an AC command without an LLM
People complain to a house more than they command it. A small semantic layer turns complaints, comparatives, typos and “everything except” into device actions before a language model is ever asked.
The problem
People say “it’s too hot”, not “turn on the bedroom AC”.
The fix
Pattern tables map complaints, comparatives and aliases to device actions.
- 10
- comfort-complaint patterns
- 12
- comparative words, from “cooler” to “faster”
- 25
- device aliases, typos included
Most of what people say to a smart home isn’t a command. It’s a complaint: “it’s too hot in the bedroom”, “the living room feels dark”, “can you make the kitchen brighter?”. None of those names a device and an action, and that pair is all the hardware understands.
Why not send it all to the LLM
The command engine I built for AHA’s hiring process does have a language model: Llama 3.2, running locally. But a model call takes 1 to 3 seconds, and most complaints come in a handful of shapes. So inside the rule engine sits a semantic layer, a few tables that translate how people talk into what devices do. No model and no network, just lookups that answer in milliseconds.
Step one: fix the words
Before any pattern runs, 25 device aliases are swapped for the names the system uses. Bulb and lamp become light. Blinds and shades become curtains. Aircon and cooler become AC. Lock, door and front door become the door lock. The typo “fna” becomes fan. Five room phrases, like “whole house” and “everywhere”, become “all”.
Fixing the input once is cheaper than teaching every later pattern about every spelling.
Step two: read the complaint
10 comfort patterns map a feeling to a device and an action:
- “too hot”, “boiling” → turn the AC on
- “too cold”, “freezing”, “chilly” → turn the AC off
- “dark”, “can’t see” → turn the lights on
- “too bright”, “blinding” → bring the lights down
- “secure the house”, “lock up” → arm the alarm
“It’s too hot in the bedroom” becomes AC, on, bedroom, at a confidence of 0.95, and the LLM is never called.
Step three: comparatives and capabilities
12 comparative words become relative changes rather than on or off. “Faster” and “slow down” adjust the fan, “brighter” and “darker” the lights, “cooler” and “warmer” the AC. So “make the fan faster in the bedroom” raises the bedroom fan’s speed instead of just switching it on.
Capabilities fill in missing devices. Temperature means the AC, brightness means a light, speed means the fan, and locking means the door lock. “Set the temperature to 18” names no device, but it still lands on the AC, with a value of 18.
Step four: “everything except”
“Turn off everything except the bedroom” is set logic, not language:
rooms = every room - rooms after “except / not / but / excluding”
devices = every device type - locks and alarms # never in “everything”
actions = devices × rooms
That sentence becomes 6 device types across 7 rooms: 42 actions. The bedroom keeps its AC, and the door lock and alarm aren’t touched, because “everything” never includes them unless you name them.
Scenes are the simplest case of all. “Movie time” is a macro: it dims the living-room lights to 30%, and turns on the TV and the AC at 22°C.
Where the rules stop
Patterns are literal, and that’s the trade-off. “It’s too hot in the bedroom” matches; “I’m feeling hot” doesn’t, because “feeling hot” isn’t in the table. It falls through to Llama 3.2, whose prompt includes “I am feeling hot” as a worked example. Anything the tables can’t place, like “turn the lights blue”, goes to the model too, and the model is told to ask rather than guess.
Defaults are the other trade-off. When a command names no room, lights, AC, fans and curtains apply to the whole house. That’s right for “turn off the lights”, and heavy-handed for “it’s too dark in here”, which lights every room.
What I’d keep
- Normalise first, then parse. Aliases and typos belong in one table, not in every pattern.
- Keep the vocabulary in data. Adding “chilly” is one line, and it’s testable.
- Make “everything” mean “everything safe”. Exclusions belong in the set logic, not in the user’s memory.
- Hand over, don’t guess. When no table matches, the model gets the sentence, inside an allow-list.