hermes: sanitize classifier tool history
This commit is contained in:
parent
7dbde8e85d
commit
c7dc81c0c3
@ -79,18 +79,20 @@ def _compact_message(message: dict[str, Any], limit: int) -> dict[str, Any]:
|
||||
result = copy.deepcopy(message)
|
||||
if "content" in result:
|
||||
result["content"] = _compact_content(result["content"], limit)
|
||||
tool_calls = result.get("tool_calls")
|
||||
if isinstance(tool_calls, list):
|
||||
kept: list[dict[str, Any]] = []
|
||||
for call in tool_calls[-4:]:
|
||||
if not isinstance(call, dict):
|
||||
continue
|
||||
item = copy.deepcopy(call)
|
||||
function = item.get("function")
|
||||
if isinstance(function, dict) and isinstance(function.get("arguments"), str):
|
||||
function["arguments"] = _bounded_text(function["arguments"], 600)
|
||||
kept.append(item)
|
||||
result["tool_calls"] = kept
|
||||
# The local judge only classifies the current boundary. OpenAI-compatible
|
||||
# Ollama validates assistant tool-call JSON and tool/result pairing before
|
||||
# inference, so a bounded or selectively retained transcript can become an
|
||||
# invalid conversation even though its text is sufficient for routing.
|
||||
# Preserve tool evidence as plain user text and remove protocol metadata.
|
||||
had_tool_calls = bool(result.pop("tool_calls", None))
|
||||
result.pop("tool_call_id", None)
|
||||
result.pop("name", None)
|
||||
if result.get("role") == "tool":
|
||||
result["role"] = "user"
|
||||
content = result.get("content")
|
||||
result["content"] = f"[tool evidence]\n{content or ''}"
|
||||
elif had_tool_calls and not result.get("content"):
|
||||
result["content"] = "[assistant requested an external tool]"
|
||||
return result
|
||||
|
||||
|
||||
@ -153,6 +155,8 @@ def compact_payload(payload: dict[str, Any]) -> dict[str, Any]:
|
||||
# The judge never needs tools or binary inputs. Switchyard supplies a
|
||||
# response schema separately, and that contract must remain untouched.
|
||||
result.pop("tools", None)
|
||||
result.pop("tool_choice", None)
|
||||
result.pop("parallel_tool_calls", None)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@ -1229,10 +1229,24 @@ def test_classifier_broker_bounds_history_without_losing_routing_intent(monkeypa
|
||||
"role": "user",
|
||||
"content": "Build and verify the Cassandra release safely.",
|
||||
},
|
||||
{"role": "assistant", "content": "working"},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": None,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_large",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "large_tool",
|
||||
"arguments": '{"command":"' + ("x" * 5000) + '"}',
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"content": "unbounded test output " * 10000,
|
||||
"tool_call_id": "call_large",
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@ -1243,6 +1257,8 @@ def test_classifier_broker_bounds_history_without_losing_routing_intent(monkeypa
|
||||
},
|
||||
],
|
||||
"tools": [{"type": "function", "function": {"name": "large_tool"}}],
|
||||
"tool_choice": "auto",
|
||||
"parallel_tool_calls": True,
|
||||
"response_format": {"type": "json_object"},
|
||||
}
|
||||
|
||||
@ -1252,6 +1268,13 @@ def test_classifier_broker_bounds_history_without_losing_routing_intent(monkeypa
|
||||
assert compacted["model"] == payload["model"]
|
||||
assert compacted["response_format"] == payload["response_format"]
|
||||
assert "tools" not in compacted
|
||||
assert "tool_choice" not in compacted
|
||||
assert "parallel_tool_calls" not in compacted
|
||||
assert all(message.get("role") != "tool" for message in compacted["messages"])
|
||||
assert all("tool_call_id" not in message for message in compacted["messages"])
|
||||
assert all("tool_calls" not in message for message in compacted["messages"])
|
||||
assert "[tool evidence]" in encoded
|
||||
assert "[assistant requested an external tool]" in encoded
|
||||
assert "Build and verify the Cassandra release safely." in encoded
|
||||
assert "Turn this cat into a cute clown." in encoded
|
||||
assert "image attachment available to the selected worker" in encoded
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user