Add description to intent handlers and use in LLM helper (#117864)
This commit is contained in:
parent
0c37a065ad
commit
8079cc0464
13 changed files with 74 additions and 6 deletions
|
@ -22,6 +22,7 @@ class GetTemperatureIntent(intent.IntentHandler):
|
|||
"""Handle GetTemperature intents."""
|
||||
|
||||
intent_type = INTENT_GET_TEMPERATURE
|
||||
description = "Gets the current temperature of a climate device or entity"
|
||||
slot_schema = {vol.Optional("area"): str, vol.Optional("name"): str}
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
|
|
|
@ -33,6 +33,7 @@ class HumidityHandler(intent.IntentHandler):
|
|||
"""Handle set humidity intents."""
|
||||
|
||||
intent_type = INTENT_HUMIDITY
|
||||
description = "Set desired humidity level"
|
||||
slot_schema = {
|
||||
vol.Required("name"): cv.string,
|
||||
vol.Required("humidity"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
|
||||
|
@ -85,6 +86,7 @@ class SetModeHandler(intent.IntentHandler):
|
|||
"""Handle set humidity intents."""
|
||||
|
||||
intent_type = INTENT_MODE
|
||||
description = "Set humidifier mode"
|
||||
slot_schema = {
|
||||
vol.Required("name"): cv.string,
|
||||
vol.Required("mode"): cv.string,
|
||||
|
|
|
@ -73,15 +73,30 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
|
||||
intent.async_register(
|
||||
hass,
|
||||
OnOffIntentHandler(intent.INTENT_TURN_ON, HA_DOMAIN, SERVICE_TURN_ON),
|
||||
OnOffIntentHandler(
|
||||
intent.INTENT_TURN_ON,
|
||||
HA_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
description="Turns on/opens a device or entity",
|
||||
),
|
||||
)
|
||||
intent.async_register(
|
||||
hass,
|
||||
OnOffIntentHandler(intent.INTENT_TURN_OFF, HA_DOMAIN, SERVICE_TURN_OFF),
|
||||
OnOffIntentHandler(
|
||||
intent.INTENT_TURN_OFF,
|
||||
HA_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
description="Turns off/closes a device or entity",
|
||||
),
|
||||
)
|
||||
intent.async_register(
|
||||
hass,
|
||||
intent.ServiceIntentHandler(intent.INTENT_TOGGLE, HA_DOMAIN, SERVICE_TOGGLE),
|
||||
intent.ServiceIntentHandler(
|
||||
intent.INTENT_TOGGLE,
|
||||
HA_DOMAIN,
|
||||
SERVICE_TOGGLE,
|
||||
"Toggles a device or entity",
|
||||
),
|
||||
)
|
||||
intent.async_register(
|
||||
hass,
|
||||
|
@ -195,6 +210,7 @@ class GetStateIntentHandler(intent.IntentHandler):
|
|||
"""Answer questions about entity states."""
|
||||
|
||||
intent_type = intent.INTENT_GET_STATE
|
||||
description = "Gets or checks the state of a device or entity"
|
||||
slot_schema = {
|
||||
vol.Any("name", "area", "floor"): cv.string,
|
||||
vol.Optional("domain"): vol.All(cv.ensure_list, [cv.string]),
|
||||
|
@ -314,6 +330,7 @@ class NevermindIntentHandler(intent.IntentHandler):
|
|||
"""Takes no action."""
|
||||
|
||||
intent_type = intent.INTENT_NEVERMIND
|
||||
description = "Cancels the current request and does nothing"
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
"""Doe not do anything, and produces an empty response."""
|
||||
|
@ -323,6 +340,8 @@ class NevermindIntentHandler(intent.IntentHandler):
|
|||
class SetPositionIntentHandler(intent.DynamicServiceIntentHandler):
|
||||
"""Intent handler for setting positions."""
|
||||
|
||||
description = "Sets the position of a device or entity"
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Create set position handler."""
|
||||
super().__init__(
|
||||
|
|
|
@ -690,6 +690,7 @@ class StartTimerIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for starting a new timer."""
|
||||
|
||||
intent_type = intent.INTENT_START_TIMER
|
||||
description = "Starts a new timer"
|
||||
slot_schema = {
|
||||
vol.Required(vol.Any("hours", "minutes", "seconds")): cv.positive_int,
|
||||
vol.Optional("name"): cv.string,
|
||||
|
@ -733,6 +734,7 @@ class CancelTimerIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for cancelling a timer."""
|
||||
|
||||
intent_type = intent.INTENT_CANCEL_TIMER
|
||||
description = "Cancels a timer"
|
||||
slot_schema = {
|
||||
vol.Any("start_hours", "start_minutes", "start_seconds"): cv.positive_int,
|
||||
vol.Optional("name"): cv.string,
|
||||
|
@ -755,6 +757,7 @@ class IncreaseTimerIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for increasing the time of a timer."""
|
||||
|
||||
intent_type = intent.INTENT_INCREASE_TIMER
|
||||
description = "Adds more time to a timer"
|
||||
slot_schema = {
|
||||
vol.Any("hours", "minutes", "seconds"): cv.positive_int,
|
||||
vol.Any("start_hours", "start_minutes", "start_seconds"): cv.positive_int,
|
||||
|
@ -779,6 +782,7 @@ class DecreaseTimerIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for decreasing the time of a timer."""
|
||||
|
||||
intent_type = intent.INTENT_DECREASE_TIMER
|
||||
description = "Removes time from a timer"
|
||||
slot_schema = {
|
||||
vol.Required(vol.Any("hours", "minutes", "seconds")): cv.positive_int,
|
||||
vol.Any("start_hours", "start_minutes", "start_seconds"): cv.positive_int,
|
||||
|
@ -803,6 +807,7 @@ class PauseTimerIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for pausing a running timer."""
|
||||
|
||||
intent_type = intent.INTENT_PAUSE_TIMER
|
||||
description = "Pauses a running timer"
|
||||
slot_schema = {
|
||||
vol.Any("start_hours", "start_minutes", "start_seconds"): cv.positive_int,
|
||||
vol.Optional("name"): cv.string,
|
||||
|
@ -825,6 +830,7 @@ class UnpauseTimerIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for unpausing a paused timer."""
|
||||
|
||||
intent_type = intent.INTENT_UNPAUSE_TIMER
|
||||
description = "Resumes a paused timer"
|
||||
slot_schema = {
|
||||
vol.Any("start_hours", "start_minutes", "start_seconds"): cv.positive_int,
|
||||
vol.Optional("name"): cv.string,
|
||||
|
@ -847,6 +853,7 @@ class TimerStatusIntentHandler(intent.IntentHandler):
|
|||
"""Intent handler for reporting the status of a timer."""
|
||||
|
||||
intent_type = intent.INTENT_TIMER_STATUS
|
||||
description = "Reports the current status of timers"
|
||||
slot_schema = {
|
||||
vol.Any("start_hours", "start_minutes", "start_seconds"): cv.positive_int,
|
||||
vol.Optional("name"): cv.string,
|
||||
|
|
|
@ -32,5 +32,6 @@ async def async_setup_intents(hass: HomeAssistant) -> None:
|
|||
vol.Coerce(int), vol.Range(0, 100)
|
||||
),
|
||||
},
|
||||
description="Sets the brightness or color of a light",
|
||||
),
|
||||
)
|
||||
|
|
|
@ -65,6 +65,7 @@ async def async_setup_intents(hass: HomeAssistant) -> None:
|
|||
required_domains={DOMAIN},
|
||||
required_features=MediaPlayerEntityFeature.NEXT_TRACK,
|
||||
required_states={MediaPlayerState.PLAYING},
|
||||
description="Skips a media player to the next item",
|
||||
),
|
||||
)
|
||||
intent.async_register(
|
||||
|
@ -81,6 +82,7 @@ async def async_setup_intents(hass: HomeAssistant) -> None:
|
|||
vol.Coerce(int), vol.Range(min=0, max=100), lambda val: val / 100
|
||||
)
|
||||
},
|
||||
description="Sets the volume of a media player",
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -97,6 +99,7 @@ class MediaPauseHandler(intent.ServiceIntentHandler):
|
|||
required_domains={DOMAIN},
|
||||
required_features=MediaPlayerEntityFeature.PAUSE,
|
||||
required_states={MediaPlayerState.PLAYING},
|
||||
description="Pauses a media player",
|
||||
)
|
||||
self.last_paused = last_paused
|
||||
|
||||
|
@ -130,6 +133,7 @@ class MediaUnpauseHandler(intent.ServiceIntentHandler):
|
|||
SERVICE_MEDIA_PLAY,
|
||||
required_domains={DOMAIN},
|
||||
required_states={MediaPlayerState.PAUSED},
|
||||
description="Resumes a media player",
|
||||
)
|
||||
self.last_paused = last_paused
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ class AddItemIntent(intent.IntentHandler):
|
|||
"""Handle AddItem intents."""
|
||||
|
||||
intent_type = INTENT_ADD_ITEM
|
||||
description = "Adds an item to the shopping list"
|
||||
slot_schema = {"item": cv.string}
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
|
@ -39,6 +40,7 @@ class ListTopItemsIntent(intent.IntentHandler):
|
|||
"""Handle AddItem intents."""
|
||||
|
||||
intent_type = INTENT_LAST_ITEMS
|
||||
description = "List the top five items on the shopping list"
|
||||
slot_schema = {"item": cv.string}
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
|
|
|
@ -21,6 +21,7 @@ class ListAddItemIntent(intent.IntentHandler):
|
|||
"""Handle ListAddItem intents."""
|
||||
|
||||
intent_type = INTENT_LIST_ADD_ITEM
|
||||
description = "Add item to a todo list"
|
||||
slot_schema = {"item": cv.string, "name": cv.string}
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
|
|
|
@ -13,11 +13,16 @@ async def async_setup_intents(hass: HomeAssistant) -> None:
|
|||
"""Set up the vacuum intents."""
|
||||
intent.async_register(
|
||||
hass,
|
||||
intent.ServiceIntentHandler(INTENT_VACUUM_START, DOMAIN, SERVICE_START),
|
||||
intent.ServiceIntentHandler(
|
||||
INTENT_VACUUM_START, DOMAIN, SERVICE_START, description="Starts a vacuum"
|
||||
),
|
||||
)
|
||||
intent.async_register(
|
||||
hass,
|
||||
intent.ServiceIntentHandler(
|
||||
INTENT_VACUUM_RETURN_TO_BASE, DOMAIN, SERVICE_RETURN_TO_BASE
|
||||
INTENT_VACUUM_RETURN_TO_BASE,
|
||||
DOMAIN,
|
||||
SERVICE_RETURN_TO_BASE,
|
||||
description="Returns a vacuum to base",
|
||||
),
|
||||
)
|
||||
|
|
|
@ -23,6 +23,7 @@ class GetWeatherIntent(intent.IntentHandler):
|
|||
"""Handle GetWeather intents."""
|
||||
|
||||
intent_type = INTENT_GET_WEATHER
|
||||
description = "Gets the current weather"
|
||||
slot_schema = {vol.Optional("name"): cv.string}
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
|
|
|
@ -725,6 +725,7 @@ class IntentHandler:
|
|||
|
||||
intent_type: str
|
||||
platforms: Iterable[str] | None = []
|
||||
description: str | None = None
|
||||
|
||||
@property
|
||||
def slot_schema(self) -> dict | None:
|
||||
|
@ -784,6 +785,7 @@ class DynamicServiceIntentHandler(IntentHandler):
|
|||
required_domains: set[str] | None = None,
|
||||
required_features: int | None = None,
|
||||
required_states: set[str] | None = None,
|
||||
description: str | None = None,
|
||||
) -> None:
|
||||
"""Create Service Intent Handler."""
|
||||
self.intent_type = intent_type
|
||||
|
@ -791,6 +793,7 @@ class DynamicServiceIntentHandler(IntentHandler):
|
|||
self.required_domains = required_domains
|
||||
self.required_features = required_features
|
||||
self.required_states = required_states
|
||||
self.description = description
|
||||
|
||||
self.required_slots: dict[tuple[str, str], vol.Schema] = {}
|
||||
if required_slots:
|
||||
|
@ -1076,6 +1079,7 @@ class ServiceIntentHandler(DynamicServiceIntentHandler):
|
|||
required_domains: set[str] | None = None,
|
||||
required_features: int | None = None,
|
||||
required_states: set[str] | None = None,
|
||||
description: str | None = None,
|
||||
) -> None:
|
||||
"""Create service handler."""
|
||||
super().__init__(
|
||||
|
@ -1086,6 +1090,7 @@ class ServiceIntentHandler(DynamicServiceIntentHandler):
|
|||
required_domains=required_domains,
|
||||
required_features=required_features,
|
||||
required_states=required_states,
|
||||
description=description,
|
||||
)
|
||||
self.domain = domain
|
||||
self.service = service
|
||||
|
|
|
@ -136,7 +136,9 @@ class IntentTool(Tool):
|
|||
) -> None:
|
||||
"""Init the class."""
|
||||
self.name = intent_handler.intent_type
|
||||
self.description = f"Execute Home Assistant {self.name} intent"
|
||||
self.description = (
|
||||
intent_handler.description or f"Execute Home Assistant {self.name} intent"
|
||||
)
|
||||
if slot_schema := intent_handler.slot_schema:
|
||||
self.parameters = vol.Schema(slot_schema)
|
||||
|
||||
|
|
|
@ -118,3 +118,21 @@ async def test_assist_api(hass: HomeAssistant) -> None:
|
|||
"response_type": "action_done",
|
||||
"speech": {},
|
||||
}
|
||||
|
||||
|
||||
async def test_assist_api_description(hass: HomeAssistant) -> None:
|
||||
"""Test intent description with Assist API."""
|
||||
|
||||
class MyIntentHandler(intent.IntentHandler):
|
||||
intent_type = "test_intent"
|
||||
description = "my intent handler"
|
||||
|
||||
intent.async_register(hass, MyIntentHandler())
|
||||
|
||||
assert len(llm.async_get_apis(hass)) == 1
|
||||
api = llm.async_get_api(hass, "assist")
|
||||
tools = api.async_get_tools()
|
||||
assert len(tools) == 1
|
||||
tool = tools[0]
|
||||
assert tool.name == "test_intent"
|
||||
assert tool.description == "my intent handler"
|
||||
|
|
Loading…
Add table
Reference in a new issue