fix: describe local intent answers to the model instead of replaying them
With prefer_local_intents, Home Assistant puts requests its local intents answered into the chat log as external calls of intents like HassGetCurrentTime. The model does not have these tools, and replayed as its own calls they make it apologise for using tools it does not have and doubt answers it never gave. They are now passed as a developer note with the intent, its arguments and its result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e54f0f0fa1
commit
6aed494e44
3 files changed
+77
-1
No files matched your search
@@ -180,13 +180,35 @@ def _convert_content_to_param(
|
||||
"""Convert any native chat message for this agent to the native format."""
|
||||
messages: ResponseInputParam = []
|
||||
reasoning_summary: list[str] = []
|
||||
# Requests that Home Assistant's local intents answered without the model
|
||||
# (prefer_local_intents) are in the chat log as calls of intents like
|
||||
# HassGetCurrentTime, which are not among the model's tools. Replayed as
|
||||
# the model's own calls, they make it apologise for using tools it does
|
||||
# not have, so they are described to it as a note instead.
|
||||
local_calls: dict[str, llm.ToolInput] = {}
|
||||
|
||||
for content in chat_content:
|
||||
if isinstance(content, conversation.ToolResultContent):
|
||||
if (tool_call := local_calls.pop(content.tool_call_id, None)) is not None:
|
||||
messages.append(
|
||||
EasyInputMessageParam(
|
||||
type="message",
|
||||
role="developer",
|
||||
content=(
|
||||
"Home Assistant's local intent recognition answered "
|
||||
"the last user request itself, without you: it ran "
|
||||
f"{tool_call.tool_name} with "
|
||||
f"{json_dumps(tool_call.tool_args)} and got "
|
||||
f"{json_dumps(content.tool_result)}. The assistant "
|
||||
"reply after this note is its wording, not yours. "
|
||||
"That intent is not one of your tools."
|
||||
),
|
||||
)
|
||||
)
|
||||
# Earlier web searches are not replayed: the chat log only keeps
|
||||
# their status, not their results, and a search without results
|
||||
# makes the model disown the answer it based on that search.
|
||||
if content.tool_name != "web_search_call":
|
||||
elif content.tool_name != "web_search_call":
|
||||
messages.append(
|
||||
FunctionCallOutput(
|
||||
type="function_call_output",
|
||||
@@ -211,6 +233,9 @@ def _convert_content_to_param(
|
||||
for tool_call in content.tool_calls:
|
||||
if tool_call.external and tool_call.tool_name == "web_search_call":
|
||||
continue
|
||||
if tool_call.external and tool_call.tool_name != "code_interpreter":
|
||||
local_calls[tool_call.id] = tool_call
|
||||
continue
|
||||
messages.append(
|
||||
ResponseFunctionToolCallParam(
|
||||
type="function_call",
|
||||
|
||||
Reference in new issue
Block a user