Render one assistant message per turn, and make the request timeout a setting
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m16s
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m16s
Two setup failures found while calibrating the new benchmark tasks, both of which would also fail real milestones. Devstral's chat template (Mistral) rejected any turn in which the model wrote some text before a tool call: the OpenAI renderer made one message per event, so the turn became a text message and a tool-call message in a row, and llama.cpp answered 500. The renderer now folds consecutive user or assistant messages into one, which is the OpenAI format for a turn anyway. Checked against the live server: the captured failing request no longer occurs, over six real runs. LiteLLMClient gave up on any request after a fixed 120 s. A dense 27B model writing a whole module in one turn takes longer, so the executor escalated work that was going well. llm.request_timeout_s now sets it for both clients, default 600. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f41cbb00cf
commit
d49435d4e5
8 files changed
+139
-8
No files matched your search
@@ -60,7 +60,7 @@ class OpenAIChatRenderer:
|
||||
kept = effective_events(events)
|
||||
answered = {e.event.call_id for e in kept if isinstance(e.event, ToolResult)}
|
||||
for stored in kept:
|
||||
messages.append(self._message_for(stored.event))
|
||||
_append_merged(messages, self._message_for(stored.event))
|
||||
# Providers reject a tool call with no result following it. One
|
||||
# can legitimately be missing: a crash between the call and its
|
||||
# result (A3), or a turn-ending gate tool. Render a placeholder so
|
||||
@@ -128,3 +128,28 @@ class OpenAIChatRenderer:
|
||||
}
|
||||
case _:
|
||||
raise ValueError(f"unrenderable event: {event!r}")
|
||||
|
||||
|
||||
def _append_merged(messages: list[dict[str, Any]], message: dict[str, Any]) -> None:
|
||||
"""Append, folding into the previous message when both are the same user
|
||||
or assistant role.
|
||||
|
||||
One model turn is often several events (some text, then one or more tool
|
||||
calls), and the OpenAI format carries a turn as one assistant message
|
||||
with a tool_calls list. Strict chat templates enforce that: Devstral's
|
||||
(Mistral) rejected a turn rendered as a text message then a tool-call
|
||||
message with a 500, failing runs whenever the model spoke before acting."""
|
||||
previous = messages[-1] if messages else None
|
||||
role = message["role"]
|
||||
if (
|
||||
previous is None
|
||||
or previous["role"] != role
|
||||
or role not in ("user", "assistant")
|
||||
):
|
||||
messages.append(message)
|
||||
return
|
||||
texts = [t for t in (previous.get("content"), message.get("content")) if t]
|
||||
previous["content"] = "\n\n".join(texts) if texts else None
|
||||
calls = previous.get("tool_calls", []) + message.get("tool_calls", [])
|
||||
if calls:
|
||||
previous["tool_calls"] = calls
|
||||
Reference in new issue
Block a user