mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-11-01 03:10:57 +00:00
Surface output-limit truncation instead of misformat retries
Record the Chat Completions finish_reason on LLMResult and add a message_loop_result extension that, when a turn stopped at the output token limit (finish_reason "length"/"max_tokens") without a complete tool request, retries with a warning naming truncation as the cause rather than the generic misformat message. The warning counts toward the existing unusable-response loop limit. Context Doctor now leaves results already handled by an earlier extension untouched, so truncated envelopes are not repaired and dispatched with cut-off arguments. Fixes #1836
This commit is contained in:
parent
ff2a5b9c9c
commit
2f8a06515e
17 changed files with 166 additions and 3 deletions
|
|
@ -25,6 +25,7 @@ class StopUnusableResponseLoop(Extension):
|
|||
self.agent.read_prompt("fw.msg_empty_response.md"),
|
||||
self.agent.read_prompt("fw.msg_reasoning_only.md"),
|
||||
self.agent.read_prompt("fw.msg_thoughts_fallback.md"),
|
||||
self.agent.read_prompt("fw.msg_output_limit.md"),
|
||||
}:
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
## Ownership
|
||||
|
||||
- Extensions receive mutable `result_data` with `llm_result` and may set `skip_default_processing` after fully handling the turn.
|
||||
- `_05_truncated_response.py` retries turns the provider cut off at the output token limit (`LLMResult.truncated`) that carry no complete tool request: add an agent-facing `fw.msg_output_limit.md` history warning with a separate `fw.msg_output_limit_response.md` user notice naming the finish reason, instead of the generic misformat warning, and count them through the stop-unusable-response-loop extension.
|
||||
- `_20_empty_response.py` retries fully empty turns (no response and no reasoning): count them toward the unusable-response limit without adding a warning to model history, and use `fw.msg_empty_response.md` for agent-prefixed UI warning text only.
|
||||
- `_20_empty_response.py` retries reasoning-only turns: add an agent-facing `fw.msg_reasoning_only.md` history warning with a separate `fw.msg_reasoning_only_response.md` user notice, and count them through the stop-unusable-response-loop extension.
|
||||
- `_30_repeat_response.py` compares `LLMResult.repeat_response_text()` for native calls (public text plus all calls), otherwise full response text. It retries content that exactly matches `loop_data.last_response`, regardless of separate reasoning or provider IDs, using `fw.msg_repeat.md` for history and `fw.msg_repeat_response.md` for the agent-prefixed UI warning text. State advancement is owned by `hist_add_ai_response`; do not call `_remember_llm_result_state` manually.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
"""Retry model turns cut off by the output token limit with a specific warning."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from helpers import extract_tools
|
||||
from helpers.extension import Extension
|
||||
from helpers.print_style import PrintStyle
|
||||
|
||||
|
||||
class TruncatedResponse(Extension):
|
||||
def execute(self, result_data: dict[str, Any] | None = None, **kwargs: Any) -> None:
|
||||
if not self.agent or not isinstance(result_data, dict):
|
||||
return
|
||||
if result_data.get("skip_default_processing"):
|
||||
return
|
||||
|
||||
llm_result = result_data.get("llm_result")
|
||||
if not getattr(llm_result, "truncated", False):
|
||||
return
|
||||
if getattr(llm_result, "function_calls", None):
|
||||
return
|
||||
response = getattr(llm_result, "response", "")
|
||||
if isinstance(response, str) and extract_tools.extract_tool_request(response):
|
||||
return
|
||||
|
||||
# Name truncation as the cause instead of the generic misformat warning.
|
||||
warning = self.agent.read_prompt("fw.msg_output_limit.md")
|
||||
warning_message = self.agent.hist_add_warning(message=warning)
|
||||
notice = self.agent.read_prompt(
|
||||
"fw.msg_output_limit_response.md",
|
||||
finish_reason=getattr(llm_result, "finish_reason", ""),
|
||||
)
|
||||
PrintStyle(font_color="orange", padding=True).print(notice)
|
||||
self.agent.context.log.log(
|
||||
type="warning",
|
||||
content=f"{self.agent.agent_name}: {notice}",
|
||||
id=warning_message.id,
|
||||
)
|
||||
result_data["skip_default_processing"] = True
|
||||
Loading…
Add table
Add a link
Reference in a new issue