Improve LLM tool quality by more clearly specifying device_class slots (#122723)

* Limit intent / llm API device_class slots to only necessary services and limited set of values

* Fix ruff errors

* Run ruff format

* Fix typing and improve output schema

* Fix schema and improve flattening

* Revert conftest

* Revert recorder

* Fix ruff format errors

* Update using latest version of voluptuous
This commit is contained in:
Allen Porter 2024-07-31 05:36:02 -07:00 committed by GitHub
parent 7c7b408df1
commit f14471112d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 183 additions and 21 deletions

View file

@ -765,7 +765,7 @@ async def test_service_intent_handler_required_domains(hass: HomeAssistant) -> N
)
# Still fails even if we provide the domain
with pytest.raises(intent.MatchFailedError):
with pytest.raises(intent.InvalidSlotInfo):
await intent.async_handle(
hass,
"test",
@ -777,7 +777,10 @@ async def test_service_intent_handler_required_domains(hass: HomeAssistant) -> N
async def test_service_handler_empty_strings(hass: HomeAssistant) -> None:
"""Test that passing empty strings for filters fails in ServiceIntentHandler."""
handler = intent.ServiceIntentHandler(
"TestType", "light", "turn_on", "Turned {} on"
"TestType",
"light",
"turn_on",
"Turned {} on",
)
intent.async_register(hass, handler)
@ -814,3 +817,55 @@ async def test_service_handler_no_filter(hass: HomeAssistant) -> None:
"test",
"TestType",
)
async def test_service_handler_device_classes(
hass: HomeAssistant, entity_registry: er.EntityRegistry
) -> None:
"""Test that passing empty strings for filters fails in ServiceIntentHandler."""
# Register a fake service and a switch intent handler
call_done = asyncio.Event()
calls = []
# Register a service that takes 0.1 seconds to execute
async def mock_service(call):
"""Mock service."""
call_done.set()
calls.append(call)
hass.services.async_register("switch", "turn_on", mock_service)
handler = intent.ServiceIntentHandler(
"TestType",
"switch",
"turn_on",
"Turned {} on",
device_classes={switch.SwitchDeviceClass},
)
intent.async_register(hass, handler)
# Create a switch enttiy and match by device class
hass.states.async_set(
"switch.bedroom", "off", attributes={"device_class": "outlet"}
)
hass.states.async_set("switch.living_room", "off")
await intent.async_handle(
hass,
"test",
"TestType",
slots={"device_class": {"value": "outlet"}},
)
await call_done.wait()
assert [call.data.get("entity_id") for call in calls] == ["switch.bedroom"]
calls.clear()
# Validate which device classes are allowed
with pytest.raises(intent.InvalidSlotInfo):
await intent.async_handle(
hass,
"test",
"TestType",
slots={"device_class": {"value": "light"}},
)