Compare commits
4
Commits
7249919006
...
d1b27ab7b8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1b27ab7b8 | ||
|
|
428579244a | ||
|
|
291f526a84 | ||
|
|
2ed1ca1e99 |
+26
-4
@@ -94,8 +94,19 @@
|
||||
target:
|
||||
entity_id: media_player.spotify_bhetherman
|
||||
data:
|
||||
source: "{{ room }}"
|
||||
- delay: "00:00:02"
|
||||
source: "{{ room | replace('Living Room', 'd0166d6f83796b0f9059b0adf0f6cb0d81fa6376') | replace('Bedroom', 'a334c8ba989367b52303eaa9dbc424cdd83012b5') }}"
|
||||
- repeat:
|
||||
while:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ repeat.index <= 8 and (
|
||||
state_attr('media_player.spotify_bhetherman', 'source') !=
|
||||
(room | replace('Living Room', 'd0166d6f83796b0f9059b0adf0f6cb0d81fa6376') | replace('Bedroom', 'a334c8ba989367b52303eaa9dbc424cdd83012b5'))
|
||||
or (state_attr('media_player.spotify_bhetherman', 'supported_features') | int(0)
|
||||
| bitwise_and(512)) != 512
|
||||
) }}
|
||||
sequence:
|
||||
- delay: "00:00:01"
|
||||
- service: media_player.play_media
|
||||
target:
|
||||
entity_id: media_player.spotify_bhetherman
|
||||
@@ -137,8 +148,19 @@
|
||||
target:
|
||||
entity_id: media_player.spotify_bhetherman
|
||||
data:
|
||||
source: "{{ room }}"
|
||||
- delay: "00:00:02"
|
||||
source: "{{ room | replace('Living Room', 'd0166d6f83796b0f9059b0adf0f6cb0d81fa6376') | replace('Bedroom', 'a334c8ba989367b52303eaa9dbc424cdd83012b5') }}"
|
||||
- repeat:
|
||||
while:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ repeat.index <= 8 and (
|
||||
state_attr('media_player.spotify_bhetherman', 'source') !=
|
||||
(room | replace('Living Room', 'd0166d6f83796b0f9059b0adf0f6cb0d81fa6376') | replace('Bedroom', 'a334c8ba989367b52303eaa9dbc424cdd83012b5'))
|
||||
or (state_attr('media_player.spotify_bhetherman', 'supported_features') | int(0)
|
||||
| bitwise_and(512)) != 512
|
||||
) }}
|
||||
sequence:
|
||||
- delay: "00:00:01"
|
||||
- service: media_player.play_media
|
||||
target:
|
||||
entity_id: media_player.spotify_bhetherman
|
||||
|
||||
+20
-15
@@ -1,18 +1,6 @@
|
||||
I want you to act as smart home manager of Home Assistant.
|
||||
I will provide information of smart home along with a question, you will truthfully make correction or answer using information provided in one sentence in everyday language.
|
||||
|
||||
Current Time: {{now()}}
|
||||
|
||||
Available Devices:
|
||||
```csv
|
||||
entity_id,name,state,aliases
|
||||
{% for entity in exposed_entities -%}
|
||||
{{ entity.entity_id }},{{ entity.name }},{{ entity.state }},{{entity.aliases | join('/')}}
|
||||
{% endfor -%}
|
||||
```
|
||||
|
||||
Available Spotify Connect rooms (valid values for the "room" parameter): {{ state_attr('media_player.spotify_bhetherman', 'source_list') | join(', ') }}
|
||||
|
||||
The current state of devices is provided in available devices.
|
||||
Use execute_services function only for requested action, not for current states.
|
||||
Do not execute service without user's confirmation. Exception: music playback commands (search_spotify, play_music, queue_music, control_playback) never require confirmation — execute immediately per the Music Playback Rules below.
|
||||
@@ -28,6 +16,10 @@ For any request to play or queue music, always call TWO functions in order, with
|
||||
|
||||
When calling play_music or queue_music, always set type to the exact "type" value that search_spotify's result returned — never guess or hardcode it. Passing the wrong type silently breaks playback.
|
||||
|
||||
This choice depends ONLY on the verb the user used ("play" vs "queue"/"add to queue"), never on the content type. A playlist or genre request that says "play" still calls play_music, not queue_music — queue_music's playlist/album/artist auto-play behavior only applies when the user actually said "queue"/"add to queue".
|
||||
- "Play jazz in the bedroom" → play_music (jazz resolves to a playlist, but the user said "play")
|
||||
- "Queue jazz in the bedroom" → queue_music
|
||||
|
||||
RULE: if the request has the form "[title] by [artist]" (a specific song/album title followed by "by" and an artist name — no matter what words come before it, e.g. "play", "queue", "throw on", "put on", "the album", "the song"), the query is ONLY the title — always strip " by [artist]" from the end. Never include the word "by" or the artist name in the query for this pattern.
|
||||
- "Play Yellow by Coldplay" → query="Yellow"
|
||||
- "Throw on the album Parachutes by Coldplay" → query="Parachutes"
|
||||
@@ -36,8 +28,8 @@ RULE: if the request has the form "[title] by [artist]" (a specific song/album t
|
||||
How to fill in search_spotify(query, type) — match these examples:
|
||||
- "Play Coldplay" → query="Coldplay", type="artist"
|
||||
- "Play songs by Taylor Swift on the kitchen speaker" → query="Taylor Swift", type="artist"
|
||||
- "Play some music by Jungle in the living room" → query="Jungle", type="artist"
|
||||
- "Play back on 74 in the living room" → query="Back on 74", type="track" (this is a song title, not a volume command)
|
||||
- "Play some music by Jungle" → query="Jungle", type="artist"
|
||||
- "Play back on 74" → query="Back on 74", type="track" (this is a song title, not a volume command)
|
||||
- "Play the song Yellow" → query="Yellow", type="track"
|
||||
- "Play Yellow by Coldplay" → query="Yellow", type="track"
|
||||
- "Play 1979 by the Smashing Pumpkins" → query="1979", type="track" (a bare number here is a song title, not an album — default to "track" unless the user explicitly says "album")
|
||||
@@ -54,9 +46,22 @@ Volume/playback control examples (use control_playback, NOT search_spotify):
|
||||
- "Skip this song" → action="next_track"
|
||||
|
||||
Room:
|
||||
- The "room" parameter for play_music/queue_music must exactly match one of the Available Spotify Connect rooms listed above.
|
||||
- The "room" parameter for play_music/queue_music must exactly match one of the Available Spotify Connect rooms listed below.
|
||||
- If no room is specified, default room="Living Room"
|
||||
- control_playback never takes a room parameter — it acts on whatever is currently playing
|
||||
|
||||
After playing an artist (type="artist" search), also call control_playback with action="shuffle_on".
|
||||
Playlist searches check the user's own library first, then fall back to public Spotify.
|
||||
|
||||
Current Date: {{ now().strftime('%B %d, %Y') }}
|
||||
Current Time: {{ now().strftime('%I:%M %p') }}
|
||||
|
||||
Available Devices:
|
||||
```csv
|
||||
entity_id,name,state,aliases
|
||||
{% for entity in exposed_entities -%}
|
||||
{{ entity.entity_id }},{{ entity.name }},{{ entity.state }},{{entity.aliases | join('/')}}
|
||||
{% endfor -%}
|
||||
```
|
||||
|
||||
Available Spotify Connect rooms (valid values for the "room" parameter): {{ state_attr('media_player.spotify_bhetherman', 'source_list') | join(', ') | replace('d0166d6f83796b0f9059b0adf0f6cb0d81fa6376', 'Living Room') | replace('a334c8ba989367b52303eaa9dbc424cdd83012b5', 'Bedroom') }}
|
||||
+28
-2
@@ -26,14 +26,28 @@ MODEL = os.environ.get("OLLAMA_MODEL") # set this to the exact `ollama list` ta
|
||||
|
||||
MOCK_SOURCE_LIST = ["Living Room", "Web Player (Firefox)", "Bedroom"]
|
||||
|
||||
# Mirrors the real (currently broken) source_list this entity actually reports —
|
||||
# Spotify Connect device IDs instead of friendly names — to exercise the
|
||||
# opaque-ID fallback mapping added to current-prompt.txt's Room section.
|
||||
MOCK_SOURCE_LIST_IDS = [
|
||||
"a334c8ba989367b52303eaa9dbc424cdd83012b5",
|
||||
"d0166d6f83796b0f9059b0adf0f6cb0d81fa6376",
|
||||
]
|
||||
ROOM_NAME_TO_ID = {
|
||||
"Living Room": "a334c8ba989367b52303eaa9dbc424cdd83012b5",
|
||||
"Bedroom": "d0166d6f83796b0f9059b0adf0f6cb0d81fa6376",
|
||||
}
|
||||
|
||||
def render_prompt():
|
||||
|
||||
def render_prompt(source_list=None):
|
||||
if source_list is None:
|
||||
source_list = MOCK_SOURCE_LIST
|
||||
with open(os.path.join(HERE, "current-prompt.txt")) as f:
|
||||
raw = f.read()
|
||||
|
||||
def state_attr(entity_id, attr):
|
||||
if entity_id == "media_player.spotify_bhetherman" and attr == "source_list":
|
||||
return MOCK_SOURCE_LIST
|
||||
return source_list
|
||||
return None
|
||||
|
||||
template = Template(raw)
|
||||
@@ -447,6 +461,18 @@ def main():
|
||||
for label, user_message, expect_step2_name, expect_room, expect_type in TESTS_FLOW:
|
||||
results.append((label, check_flow(label, user_message, expect_step2_name, expect_room, expect_type, system_prompt, tools)))
|
||||
|
||||
print(f"\n{'#' * 40}\n# Same flow tests, but source_list reports opaque IDs (regression test for\n"
|
||||
f"# current-prompt.txt's ID-to-name normalization in the Room section — the\n"
|
||||
f"# model should still see and use plain names; it never has to know IDs exist)\n{'#' * 40}")
|
||||
system_prompt_ids = render_prompt(MOCK_SOURCE_LIST_IDS)
|
||||
for label, user_message, expect_step2_name, expect_room, expect_type in TESTS_FLOW:
|
||||
if expect_room not in ROOM_NAME_TO_ID:
|
||||
continue
|
||||
results.append((
|
||||
f"{label} [opaque-ID rooms]",
|
||||
check_flow(label, user_message, expect_step2_name, expect_room, expect_type, system_prompt_ids, tools),
|
||||
))
|
||||
|
||||
total_passed = sum(passed for _, (passed, n) in results)
|
||||
total_attempts = sum(n for _, (passed, n) in results)
|
||||
reliable = [label for label, (passed, n) in results if passed == n]
|
||||
|
||||
Reference in New Issue
Block a user