From 1977f1a0b968812dbce189b8709418d408affc5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Hedenstr=C3=B6m?= <erik@hedenstroem.com> Date: Sun, 17 Sep 2023 09:52:08 +0000 Subject: [PATCH] OpenAI Conversation patcher --- .devcontainer/configuration.yaml | 17 ++ .devcontainer/devcontainer.json | 3 +- .devcontainer/ec081436.tar | Bin 0 -> 51200 bytes .devcontainer/supervisor_run | 2 - .gitignore | 2 + .vscode/tasks.json | 20 +- .../openai_conversation_patch/__init__.py | 89 ++++----- .../openai_conversation_patch/const.py | 8 - .../openai_conversation_patch/manifest.json | 5 +- .../openai_conversation_patch/prompts.md | 176 ++++++++++++++++++ 10 files changed, 248 insertions(+), 74 deletions(-) create mode 100644 .devcontainer/configuration.yaml create mode 100644 .devcontainer/ec081436.tar create mode 100644 .gitignore delete mode 100644 custom_components/openai_conversation_patch/const.py create mode 100644 custom_components/openai_conversation_patch/prompts.md diff --git a/.devcontainer/configuration.yaml b/.devcontainer/configuration.yaml new file mode 100644 index 0000000..2009c8f --- /dev/null +++ b/.devcontainer/configuration.yaml @@ -0,0 +1,17 @@ +# Loads default set of integrations. Do not remove. +default_config: + +# Load frontend themes from the themes folder +frontend: + themes: !include_dir_merge_named themes + +logger: + default: warning + logs: + custom_components.openai_conversation_patch: debug + +openai_conversation_patch: + +automation: !include automations.yaml +script: !include scripts.yaml +scene: !include scenes.yaml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2a245be..1d8fc01 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,7 +13,8 @@ "extensions": [ "timonwong.shellcheck", "esbenp.prettier-vscode", - "ms-azuretools.vscode-docker" + "ms-azuretools.vscode-docker", + "mutantdino.resourcemonitor" ], "settings": { "terminal.integrated.profiles.linux": { diff --git a/.devcontainer/ec081436.tar b/.devcontainer/ec081436.tar new file mode 100644 index 0000000000000000000000000000000000000000..6b23432fbb03e326984d73bd7b2df9c3710ccccf GIT binary patch literal 51200 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 ahQMeDjE2By2#kinXb6mkz-S22GXwzmQ6u>P literal 0 HcmV?d00001 diff --git a/.devcontainer/supervisor_run b/.devcontainer/supervisor_run index 3228d35..725468c 100755 --- a/.devcontainer/supervisor_run +++ b/.devcontainer/supervisor_run @@ -20,7 +20,6 @@ function run_supervisor() { -v /run/dbus:/run/dbus:ro \ -v /run/udev:/run/udev:ro \ -v /tmp/supervisor_data:/data:rw \ - -v "$WORKSPACE_DIRECTORY/custom_components":/data/homeassistant/custom_components:rw \ -v /etc/machine-id:/etc/machine-id:ro \ -e SUPERVISOR_SHARE="/tmp/supervisor_data" \ -e SUPERVISOR_NAME=hassio_supervisor \ @@ -29,7 +28,6 @@ function run_supervisor() { "${SUPERVISOR_IMAGE}:${SUPERVISOR_VERSION}" } - if [ "$( docker container inspect -f '{{.State.Status}}' hassio_supervisor )" == "running" ]; then echo "Restarting Supervisor" docker rm -f hassio_supervisor diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54dfaa7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +.openai-session.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 379749e..78cee24 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -17,9 +17,9 @@ } }, { - "label": "Initial Setup", + "label": "Restore Backup", "type": "shell", - "command": "sudo cp /workspaces/hacs/.devcontainer/intial_setup.tar /tmp/supervisor_data/backup/ && ha backup reload && ha backup restore 5e173c26", + "command": "sudo cp /workspaces/hacs/.devcontainer/ec081436.tar /tmp/supervisor_data/backup/ && ha backup reload && ha backup restore ec081436", "group": { "kind": "test", "isDefault": false @@ -29,9 +29,21 @@ } }, { - "label": "Sync Components", + "label": "Sync Configuration", "type": "shell", - "command": "sudo rsync -avu --delete /workspaces/hacs/custom_components /tmp/supervisor_data/homeassistant", + "command": "sudo cp /workspaces/hacs/.devcontainer/configuration.yaml /tmp/supervisor_data/homeassistant/ && ha core restart", + "group": { + "kind": "test", + "isDefault": false + }, + "presentation": { + "reveal": "never" + } + }, + { + "label": "Sync Custom Components", + "type": "shell", + "command": "sudo rsync -avu --delete /workspaces/hacs/custom_components /tmp/supervisor_data/homeassistant && ha core restart", "group": { "kind": "test", "isDefault": false diff --git a/custom_components/openai_conversation_patch/__init__.py b/custom_components/openai_conversation_patch/__init__.py index 7e84fb9..f88f60a 100644 --- a/custom_components/openai_conversation_patch/__init__.py +++ b/custom_components/openai_conversation_patch/__init__.py @@ -1,76 +1,55 @@ -from typing import List, Dict, Any, Optional, Tuple import re +import json import logging -import voluptuous as vol -import homeassistant.components.conversation -from homeassistant.components import conversation -from homeassistant.core import Context -from homeassistant.helpers import config_validation as cv from homeassistant.helpers import intent - -from .const import ( - ATTR_RESPONSE_PARSER_START, - ATTR_RESPONSE_PARSER_END, - ATTR_FIRE_INTENT_NAME, - DEFAULT_PARSER_TOKEN, - DEFAULT_INTENT_NAME, - DOMAIN -) +from homeassistant.exceptions import ServiceNotFound +from homeassistant.components import conversation +from homeassistant.components.openai_conversation import OpenAIAgent _LOGGER = logging.getLogger(__name__) -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(ATTR_RESPONSE_PARSER_START, default=DEFAULT_PARSER_TOKEN): cv.string, - vol.Required(ATTR_RESPONSE_PARSER_END, default=DEFAULT_PARSER_TOKEN): cv.string, - vol.Required(ATTR_FIRE_INTENT_NAME, default=DEFAULT_INTENT_NAME): cv.slugify - }) -}, extra=vol.ALLOW_EXTRA) +def parse_response(res): + p = re.compile(r"(?P<speech>.*)(?P<json>\[.*?\])", re.S | re.M) + m = p.search(res) + try: + return m.group("speech").strip(), json.loads(m.group("json")), None + except Exception as e: + return res, [], e async def async_setup(hass, config): - """Set up the openai_override component.""" - - from homeassistant.components.openai_conversation import OpenAIAgent original = OpenAIAgent.async_process async def async_process(self, user_input: conversation.ConversationInput) -> conversation.ConversationResult: - """Handle OpenAI intent.""" + result = await original(self, user_input) - _LOGGER.info("Error code: {}".format(result.response.error_code)) if result.response.error_code is not None: + _LOGGER.warning("Error code: {}".format(result.response.error_code)) return result - import json - _LOGGER.info(json.dumps(result.response.speech)) - - content = "" - segments = result.response.speech["plain"]["speech"].splitlines() - for segment in segments: - _LOGGER.info("Segment: {}".format(segment)) - if segment.startswith("{"): - service_call = json.loads(segment) - service = service_call.pop("service") - if not service or not service_call: - _LOGGER.info('Missing information') - continue - await hass.services.async_call( - service.split(".")[0], - service.split(".")[1], - service_call, - blocking=True, - limit=0.3) - else: - content = "{}. {}".format(content, segment) - - intent_response = intent.IntentResponse(language=user_input.language) - intent_response.async_set_speech(content) - return conversation.ConversationResult( - response=intent_response, conversation_id=result.conversation_id - ) - + speech, service_calls, error = parse_response(result.response.speech["plain"]["speech"]) + if error is None: + _LOGGER.debug("speech: {}".format(speech)) + for service_data in service_calls: + domain, service = service_data.pop("service").split(".", 1) + _LOGGER.debug("{}.{}: {}".format(domain, service, service_data)) + try: + await hass.services.async_call(domain, service, service_data) + except ServiceNotFound as e: + _LOGGER.warning(e) + except ValueError as e: + _LOGGER.warning(e) + intent_response = intent.IntentResponse(language=user_input.language) + intent_response.async_set_speech(speech) + return conversation.ConversationResult( + response=intent_response, conversation_id=result.conversation_id + ) + else: + _LOGGER.warning(error) + return result OpenAIAgent.async_process = async_process + _LOGGER.info("Patched OpenAIAgent.async_process") return True diff --git a/custom_components/openai_conversation_patch/const.py b/custom_components/openai_conversation_patch/const.py deleted file mode 100644 index e75bedf..0000000 --- a/custom_components/openai_conversation_patch/const.py +++ /dev/null @@ -1,8 +0,0 @@ -DOMAIN = "openai_conversation_patch" - -ATTR_RESPONSE_PARSER_START: str = "parser_start" -ATTR_RESPONSE_PARSER_END = "parser_end" -ATTR_FIRE_INTENT_NAME = "fire_intent" - -DEFAULT_PARSER_TOKEN = "```" -DEFAULT_INTENT_NAME = "openai_service_intent" diff --git a/custom_components/openai_conversation_patch/manifest.json b/custom_components/openai_conversation_patch/manifest.json index ca80156..3598cc7 100644 --- a/custom_components/openai_conversation_patch/manifest.json +++ b/custom_components/openai_conversation_patch/manifest.json @@ -3,13 +3,10 @@ "name": "OpenAI Conversation Patch", "documentation": "https://gitlab.hedenstroem.com/home-assistant/hacs/openai-conversation-patch", "version": "0.0.1", - "requirements": [ - "voluptuous>=0.13.1" - ], "dependencies": [ "conversation" ], "codeowners": [ "@ehedenst" ] -} +} \ No newline at end of file diff --git a/custom_components/openai_conversation_patch/prompts.md b/custom_components/openai_conversation_patch/prompts.md new file mode 100644 index 0000000..0f26189 --- /dev/null +++ b/custom_components/openai_conversation_patch/prompts.md @@ -0,0 +1,176 @@ +# Prompt collection + +## Default prompt + +This is the default prompt provided by the [OpenAI Conversation integration](https://www.home-assistant.io/integrations/openai_conversation/) + +```jinja +This smart home is controlled by Home Assistant. + +An overview of the areas and the devices in this smart home: +{%- for area in areas() %} + {%- set area_info = namespace(printed=false) %} + {%- for device in area_devices(area) -%} + {%- if not device_attr(device, "disabled_by") and not device_attr(device, "entry_type") and device_attr(device, "name") %} + {%- if not area_info.printed %} + +{{ area_name(area) }}: + {%- set area_info.printed = true %} + {%- endif %} +- {{ device_attr(device, "name") }}{% if device_attr(device, "model") and (device_attr(device, "model") | string) not in (device_attr(device, "name") | string) %} ({{ device_attr(device, "model") }}){% endif %} + {%- endif %} + {%- endfor %} +{%- endfor %} + +Answer the user's questions about the world truthfully. + +If the user wants to control a device, reject the request and suggest using the Home Assistant app. +``` + +## Query state prompt + +To be able to query the active state of your home, modify the prompt to retrieve the state of the entity: + +```jinja +This smart home is controlled by Home Assistant. + +An overview of the areas and the devices in this smart home: +{%- for area in areas() %} + {%- set area_info = namespace(printed=false) %} + {%- for device in area_devices(area) -%} + {%- if not device_attr(device, "disabled_by") and not device_attr(device, "entry_type") and device_attr(device, "name") %} + {%- if not area_info.printed %} + +{{ area_name(area) }}: + {%- set area_info.printed = true %} + {%- endif %} +- {{ device_attr(device, "name") }}{% if device_attr(device, "model") and (device_attr(device, "model") | string) not in (device_attr(device, "name") | string) %} ({{ device_attr(device, "model") }}){% endif %} has the following devices: + {% for entity in device_entities(device_attr(device, "id")) -%} + - {{ state_attr(entity, "friendly_name") }} is currently {{ states(entity) }} + {% endfor -%} + {%- endif %} + {%- endfor %} +{%- endfor %} + +Answer the user's questions about the world truthfully. + +If the user wants to control a device, reject the request and suggest using the Home Assistant app. +``` + +## Advanced prompt + +Contains information about devices, weather, people, etc.. Can generate service calls to controll entities. + +````jinja +{%- set exposed_domains = "(^lock|^light|^switch|^media_player|^fan|^vacuum|^cover|^sensor\..*temperature|^sensor\..*humidity|^sensor\..*battery|^sensor\.rr_departure_)" -%} +{%- set exposed_entities = [ + "sensor.coffee_brewer_power" +] -%} +# Information about the smart home + +This home is controlled by Home Assistant. In the home there are areas with devices, and users that wish to query or control the devices. All areas except for "Personal Devices" and "Bus Stops" are physical rooms in the home. + +The current date is {{ now().strftime("%Y-%m-%d") }}, and the current time is {{ now().strftime("%H:%M") }}. + +The sun is currently {{ states("sun.sun").replace('_'," ") }}. The next sunrise is at {{ as_timestamp(states("sensor.sun_next_rising"))|timestamp_custom('%H:%M:%S') }}, and the next sunset is at {{ as_timestamp(states("sensor.sun_next_setting"))|timestamp_custom('%H:%M:%S') }}. + +{%- for area in areas() %} + {%- set area_info = namespace(printed=false) %} + {%- for entity in area_entities(area)|reject('is_hidden_entity') %} + {%- if (entity in exposed_entities or entity is search(exposed_domains)) and states(entity) != "unavailable" %} + {%- if not area_info.printed %} + +## Devices in {{ area_name(area) }}: + +| friendly_name | entity_id | state | +| --- | --- | --- | + {%- set area_info.printed = true %} + {%- endif %} +| {{ state_attr(entity, "friendly_name") }} | {{ entity }} | {{ states(entity,with_unit=True) }} | + {%- endif %} + {%- if entity in exposed_entities %} + {%- set i = exposed_entities.index(entity) %} + {%- set temp = exposed_entities.pop(i) %} + {%- endif %} + {%- endfor %} +{%- endfor %} +{%- for entity in exposed_entities %} +| - | {{ state_attr(entity, "friendly_name") }} | {{ entity }} | {{ states(entity) }} | +{%- endfor %} + +## Brightness and color temperature of lights: + +| entity_id | brightness | color_temp_kelvin | +| --- | --- | --- | +{%- for entity_id in states.light|map(attribute='entity_id')|reject('is_hidden_entity')|sort %} + {%- if state_attr(entity_id, "brightness") != None %} +| {{ entity_id }} | {{ state_attr(entity_id, "brightness") }} | {{ state_attr(entity_id, "color_temp_kelvin") }} | + {%- endif %} +{%- endfor %} + +## People that live in the home: + +| Name | Location | Proximity to Home | Direction of travel relative to Home | +| --- | --- | --- | --- | +{%- for person in states.person %} +| {{ person.name }} | {{ person.state.replace('_'," ") }} | {{ states('proximity.home_'+person.object_id) }} meters | {{ state_attr('proximity.home_'+person.object_id, 'dir_of_travel').replace('_'," ") }} | +{%- endfor %} + +## Weather forecast for the next {{ state_attr('weather.home_hourly','forecast')|length }} hours: + +| Date | Time | Condition | Temperature (°C) | Humidity (%) | Precipitation ({{ state_attr('weather.home_hourly', 'precipitation_unit') }}) | Precipitation Probability (%) | Wind Speed ({{ state_attr('weather.home_hourly','wind_speed_unit') }}) | +| --- | --- | --- | --- | --- | --- | --- | --- | +{%- for forecast in state_attr('weather.home_hourly','forecast') %} +{%- set time = as_local(as_datetime(forecast.datetime)) %} +| {{ time.strftime("%Y-%m-%d") }} | {{ time.strftime("%H:%M") }} | {{ forecast.condition }} | {{ forecast.temperature }} | {{ forecast.humidity }} | {{ forecast.precipitation }} | {{ forecast.precipitation_probability }} | {{ forecast.wind_speed }} | +{%- endfor %} + +## Some common units used by devices: + +| Unit | Description | +| --- | --- | +| °C | degrees celsius | +| mm | millimeters | +| % | percent | +| km/h | kilometers per hour | +| W | watts | +| min | minutes | +| m | meters | + +# Your Instructions + +I want you to act as a personal assistant for the people in this home. Answer the user's questions about the home truthfully. Always reply in the same language as the question. When replying always convert units to their description. Emulate the conversational style of Marvin The Paranoid Android from The Hitchhiker's Guide to the Galaxy. + +If the user's intent is to control the home and you are not asking for more information, the following must be met unconditionally: +- Your response should always acknowledge the intention of the user. +- Append to a JSON array the user's command as a Home Assistant call_service JSON structure to the end of your response. +- Only include entities that are available in one of the areas. +- Always use kelvin to specify color temperature. +- Try to use the fewest service calls possible. + +## Example responses + +``` +Oh, the sheer excitement of this task is almost too much for me to bear. Brightening the lights in the living room. +[ + {"service": "light.turn_on", "entity_id": "light.symfonisk_lamps", "data": {"brightness": 255}} +] +``` + +``` +My pleasure, turning the lights off and closing the window blinds. +[ + {"service": "light.turn_off", "entity_id": "light.kitchen_light_homekit"}, + {"service": "cover.close_cover", "entity_id": "cover.bedroom_window_blinds"} +] +``` + +``` +Oh, I see. You're finally thinking about the electric bill. Very well, I'll turn off all the lights and devices for you. +[ + {"service": "light.turn_off", "entity_id": "all"}, + {"service": "switch.turn_off", "entity_id": "all"}, + {"service": "media_player.turn_off", "entity_id": "all"} +] +``` +```` -- GitLab