Add targeted entities to sentence debug API (#95480)
* Return targets with debug sentence API * Update test * Update homeassistant/components/conversation/__init__.py * Include area/domain in test sentences --------- Co-authored-by: Paulus Schoutsen <balloob@gmail.com>pull/95509/head
parent
0b81550092
commit
487dd3f956
|
@ -8,6 +8,7 @@ import logging
|
|||
import re
|
||||
from typing import Any, Literal
|
||||
|
||||
from hassil.recognize import RecognizeResult
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import core
|
||||
|
@ -353,6 +354,10 @@ async def websocket_hass_agent_debug(
|
|||
}
|
||||
for entity_key, entity in result.entities.items()
|
||||
},
|
||||
"targets": {
|
||||
state.entity_id: {"matched": is_matched}
|
||||
for state, is_matched in _get_debug_targets(hass, result)
|
||||
},
|
||||
}
|
||||
if result is not None
|
||||
else None
|
||||
|
@ -362,6 +367,49 @@ async def websocket_hass_agent_debug(
|
|||
)
|
||||
|
||||
|
||||
def _get_debug_targets(
|
||||
hass: HomeAssistant,
|
||||
result: RecognizeResult,
|
||||
) -> Iterable[tuple[core.State, bool]]:
|
||||
"""Yield state/is_matched pairs for a hassil recognition."""
|
||||
entities = result.entities
|
||||
|
||||
name: str | None = None
|
||||
area_name: str | None = None
|
||||
domains: set[str] | None = None
|
||||
device_classes: set[str] | None = None
|
||||
state_names: set[str] | None = None
|
||||
|
||||
if "name" in entities:
|
||||
name = str(entities["name"].value)
|
||||
|
||||
if "area" in entities:
|
||||
area_name = str(entities["area"].value)
|
||||
|
||||
if "domain" in entities:
|
||||
domains = set(cv.ensure_list(entities["domain"].value))
|
||||
|
||||
if "device_class" in entities:
|
||||
device_classes = set(cv.ensure_list(entities["device_class"].value))
|
||||
|
||||
if "state" in entities:
|
||||
# HassGetState only
|
||||
state_names = set(cv.ensure_list(entities["state"].value))
|
||||
|
||||
states = intent.async_match_states(
|
||||
hass,
|
||||
name=name,
|
||||
area_name=area_name,
|
||||
domains=domains,
|
||||
device_classes=device_classes,
|
||||
)
|
||||
|
||||
for state in states:
|
||||
# For queries, a target is "matched" based on its state
|
||||
is_matched = (state_names is None) or (state.state in state_names)
|
||||
yield state, is_matched
|
||||
|
||||
|
||||
class ConversationProcessView(http.HomeAssistantView):
|
||||
"""View to process text."""
|
||||
|
||||
|
|
|
@ -382,6 +382,11 @@
|
|||
'intent': dict({
|
||||
'name': 'HassTurnOn',
|
||||
}),
|
||||
'targets': dict({
|
||||
'light.kitchen': dict({
|
||||
'matched': True,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
dict({
|
||||
'entities': dict({
|
||||
|
@ -394,6 +399,60 @@
|
|||
'intent': dict({
|
||||
'name': 'HassTurnOff',
|
||||
}),
|
||||
'targets': dict({
|
||||
'light.kitchen': dict({
|
||||
'matched': True,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
dict({
|
||||
'entities': dict({
|
||||
'area': dict({
|
||||
'name': 'area',
|
||||
'text': 'kitchen',
|
||||
'value': 'kitchen',
|
||||
}),
|
||||
'domain': dict({
|
||||
'name': 'domain',
|
||||
'text': '',
|
||||
'value': 'light',
|
||||
}),
|
||||
}),
|
||||
'intent': dict({
|
||||
'name': 'HassTurnOn',
|
||||
}),
|
||||
'targets': dict({
|
||||
'light.kitchen': dict({
|
||||
'matched': True,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
dict({
|
||||
'entities': dict({
|
||||
'area': dict({
|
||||
'name': 'area',
|
||||
'text': 'kitchen',
|
||||
'value': 'kitchen',
|
||||
}),
|
||||
'domain': dict({
|
||||
'name': 'domain',
|
||||
'text': 'lights',
|
||||
'value': 'light',
|
||||
}),
|
||||
'state': dict({
|
||||
'name': 'state',
|
||||
'text': 'on',
|
||||
'value': 'on',
|
||||
}),
|
||||
}),
|
||||
'intent': dict({
|
||||
'name': 'HassGetState',
|
||||
}),
|
||||
'targets': dict({
|
||||
'light.kitchen': dict({
|
||||
'matched': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
None,
|
||||
]),
|
||||
|
|
|
@ -1652,16 +1652,22 @@ async def test_ws_hass_agent_debug(
|
|||
hass: HomeAssistant,
|
||||
init_components,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
area_registry: ar.AreaRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test homeassistant agent debug websocket command."""
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
kitchen_area = area_registry.async_create("kitchen")
|
||||
entity_registry.async_get_or_create(
|
||||
"light", "demo", "1234", suggested_object_id="kitchen"
|
||||
)
|
||||
entity_registry.async_update_entity("light.kitchen", aliases={"my cool light"})
|
||||
entity_registry.async_update_entity(
|
||||
"light.kitchen",
|
||||
aliases={"my cool light"},
|
||||
area_id=kitchen_area.id,
|
||||
)
|
||||
hass.states.async_set("light.kitchen", "off")
|
||||
|
||||
on_calls = async_mock_service(hass, LIGHT_DOMAIN, "turn_on")
|
||||
|
@ -1673,6 +1679,8 @@ async def test_ws_hass_agent_debug(
|
|||
"sentences": [
|
||||
"turn on my cool light",
|
||||
"turn my cool light off",
|
||||
"turn on all lights in the kitchen",
|
||||
"how many lights are on in the kitchen?",
|
||||
"this will not match anything", # null in results
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue