feat: optimize Housekeeper for Mistral-Nemo tool calling
- Rewrite system prompt with negative constraints and step-by-step process - Set temperature to 0.1 for deterministic tool calling - Sort room groups to top of device list (address positional bias) - Add [ROOM GROUP] marker in list_devices output - Update tool docstrings with explicit entity_id= parameter examples - Add optimization findings doc (experiment log: 0% → 100% success) - Add test script for room group detection regression testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,10 +59,27 @@ async def list_devices(
|
||||
|
||||
for dom, dom_devices in sorted(by_domain.items()):
|
||||
output_parts.append(f"### {dom.title()}s")
|
||||
for device in dom_devices:
|
||||
|
||||
# Sort devices: room groups first (using Home Assistant's is_hue_group attribute)
|
||||
def is_room_group(d: object) -> bool:
|
||||
"""Check if device is a room group based on HA attributes."""
|
||||
attrs = getattr(d, "attributes", {})
|
||||
# Check for Hue room groups
|
||||
if attrs.get("is_hue_group") and attrs.get("hue_type") == "room":
|
||||
return True
|
||||
# Check for other group indicators (icon or entity_id list)
|
||||
if "entity_id" in attrs and isinstance(attrs["entity_id"], list):
|
||||
return True
|
||||
return False
|
||||
|
||||
sorted_devices = sorted(dom_devices, key=lambda d: (not is_room_group(d), d.entity_id))
|
||||
|
||||
for device in sorted_devices:
|
||||
state_icon = "on" if device.state == "on" else "off" if device.state == "off" else device.state
|
||||
area_str = f" ({device.area})" if device.area else ""
|
||||
output_parts.append(f"- **{device.name}**{area_str}: {state_icon}")
|
||||
# Mark room groups clearly using actual HA data
|
||||
group_marker = " [ROOM GROUP]" if is_room_group(device) else ""
|
||||
output_parts.append(f"- **{device.name}**{area_str}{group_marker}: {state_icon}")
|
||||
output_parts.append(f" ID: `{device.entity_id}`")
|
||||
output_parts.append("")
|
||||
|
||||
@@ -164,12 +181,12 @@ async def turn_on(
|
||||
color_temp: int | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Turn on a device.
|
||||
Turn on a device. Use the entity_id parameter with the EXACT value from list_devices.
|
||||
|
||||
For lights, can optionally set brightness and color temperature.
|
||||
|
||||
Args:
|
||||
entity_id: Device to turn on (e.g., light.living_room, switch.coffee_maker)
|
||||
entity_id: The EXACT entity ID from list_devices including domain prefix.
|
||||
brightness: Optional brightness for lights (0-255, where 255 is full brightness)
|
||||
color_temp: Optional color temperature in Kelvin (2700=warm, 6500=cool)
|
||||
|
||||
@@ -177,10 +194,9 @@ async def turn_on(
|
||||
Confirmation of the action
|
||||
|
||||
Examples:
|
||||
turn_on("light.living_room") # Turn on at current brightness
|
||||
turn_on("light.bedroom", brightness=128) # Turn on at 50% brightness
|
||||
turn_on("light.office", brightness=255, color_temp=4000) # Full, neutral white
|
||||
turn_on("switch.coffee_maker") # Turn on a switch
|
||||
turn_on(entity_id="light.living_room")
|
||||
turn_on(entity_id="light.bedroom", brightness=128)
|
||||
turn_on(entity_id="switch.coffee_maker")
|
||||
"""
|
||||
try:
|
||||
async with CoreAPIClient() as client:
|
||||
@@ -209,17 +225,18 @@ async def turn_on(
|
||||
|
||||
async def turn_off(entity_id: str) -> str:
|
||||
"""
|
||||
Turn off a device.
|
||||
Turn off a device. Use the entity_id parameter with the EXACT value from list_devices.
|
||||
|
||||
Args:
|
||||
entity_id: Device to turn off (e.g., light.living_room, switch.coffee_maker)
|
||||
entity_id: The EXACT entity ID from list_devices including domain prefix.
|
||||
|
||||
Returns:
|
||||
Confirmation of the action
|
||||
|
||||
Examples:
|
||||
turn_off("light.living_room")
|
||||
turn_off("switch.coffee_maker")
|
||||
turn_off(entity_id="light.living_room")
|
||||
turn_off(entity_id="switch.coffee_maker")
|
||||
turn_off(entity_id="light.kitchen")
|
||||
"""
|
||||
try:
|
||||
async with CoreAPIClient() as client:
|
||||
@@ -239,15 +256,17 @@ async def toggle(entity_id: str) -> str:
|
||||
"""
|
||||
Toggle a device's state (on becomes off, off becomes on).
|
||||
|
||||
Use the entity_id parameter with the EXACT value from list_devices.
|
||||
|
||||
Args:
|
||||
entity_id: Device to toggle
|
||||
entity_id: The EXACT entity ID from list_devices including domain prefix.
|
||||
|
||||
Returns:
|
||||
Confirmation with the new state
|
||||
|
||||
Examples:
|
||||
toggle("light.living_room")
|
||||
toggle("switch.fan")
|
||||
toggle(entity_id="light.living_room")
|
||||
toggle(entity_id="switch.fan")
|
||||
"""
|
||||
try:
|
||||
async with CoreAPIClient() as client:
|
||||
|
||||
Reference in New Issue
Block a user