Gazetteer Matcher
An English-language, constraint-driven intent recognizer for Home Assistant voice commands. It complements Home Assistant's built-in sentence grammars by handling home-specific names, fuzzy wording, compound requests, and explicit conversation references while rejecting interpretations that do not fit the upstream intent schema.
Features
- Flexible and fuzzy target matching for entities, areas, floors, domains,
and actions:
turn on the bedrom lampresolves toBedroom Lamp. - Location-aware disambiguation from spoken qualifiers and voice-satellite
context:
bedroom TVselects the TV assigned to the bedroom. - Compound commands with multiple targets, intents, or properties:
turn off the kitchen lights and open the bedroom blinds. - Multiple actions on one target:
turn on the hallway light and set its brightness to 40%. - Explicit conversational follow-ups:
turn on the kitchen lightsfollowed byturn them off, oris the front door locked?followed bylock it. - Conservative, schema-backed validation with structured error categories and concise responses for ambiguous, unsupported, and out-of-range requests.
Install
pip install gazetteer-matcher
Runtime dependencies are home-assistant-intents, unicode-rbnf, and
PyYAML. A source install also attempts to build a self-contained C++17 fuzzy
scorer. Installation still succeeds without a compiler and uses the
behaviorally equivalent Python implementation instead.
For development:
pip install 'gazetteer-matcher[dev]'
pytest
Quick start
from gazetteer_matcher import GazetteerMatcher
matcher = GazetteerMatcher(
home={
"areas": {
"kitchen": {"name": "Kitchen", "floor": "ground"},
},
"floors": {
"ground": {"name": "Ground Floor"},
},
"entities": {},
}
)
result = matcher.interpret("flick on the kichen lights")
assert result.accepted
frame = result.frames[0]
assert frame.intent == "HassTurnOn"
assert frame.slots == {"area": "kitchen", "domain": "light"}
assert frame.response_key == "lights_area"
Pass the voice satellite's location when a command omits it:
result = matcher.interpret("turn off the lights", context_area="Kitchen")
assert result.frames[0].slots == {"domain": "light", "area": "kitchen"}
Interpretations can contain several ordered frames:
result = matcher.interpret(
"turn off the kitchen lights and open the bedroom blinds"
)
assert [frame.intent for frame in result.frames] == [
"HassTurnOff",
"HassTurnOn",
]
Rejected requests carry an integration-facing category, a diagnostic reason, and an optional ready-to-use response:
result = matcher.interpret("set bedroom TV volume to 1000%")
assert not result.accepted
assert result.rejection_code == "invalid_percentage"
assert result.response == (
"Sorry, the volume value must be a whole-number percentage "
"between 0% and 100%."
)
Core API
GazetteerMatcher.interpret() accepts:
- the utterance;
- optional
context_areaandcontext_floorvalues; - optional
previous_targetsexported by a prior accepted interpretation.
An accepted Interpretation exposes ordered frames and reusable targets.
Each frame contains the Home Assistant intent, slot combination, resolved slot
values, response key, and selection diagnostics. Rejected interpretations
expose rejection_code, reason, response, and refusal_target; their
targets collection is always empty.
The matcher itself is stateless. The caller decides whether a prior target is recent enough to pass back:
previous = matcher.interpret("open the bedroom blinds")
result = matcher.interpret(
"close them",
previous_targets=previous.targets,
)
Call matcher.set_home(...) to replace the entity/area/floor gazetteer without
rebuilding the language vocabulary, intent catalog, or shared number trie.
Documentation
- Usage guide — context, compound commands, state questions, follow-ups, response keys, and rejection handling
- Configuration — the home gazetteer, vocabulary, response wording, and runtime updates
- Development — CLI diagnostics, fixture tests, rejection tests, and upstream coverage measurement
- Internals — tagging, intent constraints, number words, fuzzy scoring, coordination, scope, and candidate selection
CLI
gazetteer-match match 'turn on the kitchen and hallway lights' \
--home my-home.yaml
gazetteer-match match 'flick on the kichen lights' \
--home my-home.yaml --debug
gazetteer-match match 'open the bedroom blinds' \
--home my-home.yaml --debug --json
gazetteer-match spans 'flik the bedroom lights on'
gazetteer-match support
match requires either --home PATH or an explicit --empty-home. The latter
is useful for generic timers, date/time, weather, and state questions that need
no home-specific names. spans keeps --home optional, while support does
not use a home gazetteer. Supply --vocabulary or --responses to override the
language data. Location context is available through --context-area and
--context-floor. See the development guide for the
complete debugging and coverage workflow.
Design principle
Fuzzy similarity is evidence, not permission. A close spelling match cannot outweigh incompatible Home Assistant slots, contradictory scope, unexplained semantic content, or an equally good competing interpretation. When the matcher cannot choose one valid meaning, it rejects the request rather than guessing.
Metadata
Release files for gazetteer-matcher 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gazetteer_matcher-1.2.0.tar.gz | 103.5 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| gazetteer_matcher-1.2.0-cp311-abi3-win_arm64.whl | CPython 3.11 | abi3 | Windows ARM64 | Details |
| gazetteer_matcher-1.2.0-cp311-abi3-win_amd64.whl | CPython 3.11 | abi3 | Windows x86-64 | Details |
| gazetteer_matcher-1.2.0-cp311-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 | Details |
| gazetteer_matcher-1.2.0-cp311-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ ARM64, Linux glibc 2.24+ ARM64 | Details |
| gazetteer_matcher-1.2.0-cp311-abi3-macosx_11_0_arm64.whl | CPython 3.11 | abi3 | macOS 11.0+ ARM64 | Details |
| gazetteer_matcher-1.2.0-cp311-abi3-macosx_10_9_x86_64.whl | CPython 3.11 | abi3 | macOS 10.9+ x86-64 | Details |
Total release size: 1.4 MB
Release files / gazetteer_matcher-1.2.0.tar.gz
| Download URL | gazetteer_matcher-1.2.0.tar.gz |
|---|---|
| Size | 103.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a8b47792898cc081d5f29b4548fa82ebdc69294549347ba83f8e12a3e9c3118a
|
|
BLAKE2b-256 checksum How to use checksums |
45868649c665f5dc051b62bbe8e28c9165a0a435b54d7e8055d7c91172d0e3b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / gazetteer_matcher-1.2.0-cp311-abi3-win_arm64.whl
| Download URL | gazetteer_matcher-1.2.0-cp311-abi3-win_arm64.whl |
|---|---|
| Size | 442.2 kB |
| Tags | CPython 3.11 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
ed50d674d451324708f2a0c48f068b7cb1201be5d049eae856d7b635b987fb93
|
|
BLAKE2b-256 checksum How to use checksums |
d2921a33e21f7e57535e012964b47fab78dbd1ec98f1501a11320dab5d5f1c2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / gazetteer_matcher-1.2.0-cp311-abi3-win_amd64.whl
| Download URL | gazetteer_matcher-1.2.0-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 275.0 kB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5bd1967cdef3aa0c22dd8dddd3949f91e4e7c67f65a528aae92f0cf0e90c6b11
|
|
BLAKE2b-256 checksum How to use checksums |
6612a3d842f8cf113da8ba4db606c84bad515b923dabb0ea7726d142dd9edf56
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / gazetteer_matcher-1.2.0-cp311-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | gazetteer_matcher-1.2.0-cp311-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 212.3 kB |
| Tags | CPython 3.11 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
907e9210a8a9fb57136d7332272e79bef29c359fc41da98cb63c3fb5336b6c39
|
|
BLAKE2b-256 checksum How to use checksums |
c0135cc0dbbeee7769e0ede0eef42ae96beb92de976bd5176a3a69a79129d38b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / gazetteer_matcher-1.2.0-cp311-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
| Download URL | gazetteer_matcher-1.2.0-cp311-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 211.3 kB |
| Tags | CPython 3.11 Linux glibc 2.24+ ARM64 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
56927aea02974b2530ae93125761dd600140251ad5772d33cd4050fbca45932a
|
|
BLAKE2b-256 checksum How to use checksums |
aba956e983206b464e51404fad54cde47270ffcd95541b93fd1277694ff9ccdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / gazetteer_matcher-1.2.0-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | gazetteer_matcher-1.2.0-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 83.6 kB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f0a7a105f9cb4c1933916ef6af56bf9a263a8a263cb22dafe94c949e696a337a
|
|
BLAKE2b-256 checksum How to use checksums |
a019e35c3efeb2ac3c9623cab69a4db8c588e2bb6dffe7d93020ded8e487a6f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / gazetteer_matcher-1.2.0-cp311-abi3-macosx_10_9_x86_64.whl
| Download URL | gazetteer_matcher-1.2.0-cp311-abi3-macosx_10_9_x86_64.whl |
|---|---|
| Size | 84.2 kB |
| Tags | CPython 3.11 abi3 macOS 10.9+ x86-64 |
|
SHA-256 checksum How to use checksums |
a2fa70f809e66d8a40fe890ef0936e749ee408c7542065bbf2cf248179099165
|
|
BLAKE2b-256 checksum How to use checksums |
4d345d3d9d7c40b4a533fb8b27ac44aa4e6c89dc97fb5a28d1fb4e518a9103d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency log