Agent as a tool fix

This commit is contained in:
luijait 2025-09-29 17:30:40 +02:00
parent 9a5a067712
commit 58df53c94d
2 changed files with 61 additions and 14 deletions

View File

@ -2534,21 +2534,22 @@ class OpenAIChatCompletionsModel(Model):
# start by re-fetching self.is_ollama
self.is_ollama = os.getenv("OLLAMA") is not None and os.getenv("OLLAMA").lower() == "true"
# IMPORTANT: Include existing message history for context
# IMPORTANT: Build the prompt from history and avoid double-adding the current input.
# History already contains the latest user/tool messages for this turn.
converted_messages = []
# First, add all existing messages from history
# Add existing history first (copy to avoid in-place mutations)
if self.message_history:
for msg in self.message_history:
msg_copy = msg.copy() # Use copy to avoid modifying original
# Remove any existing cache_control to avoid exceeding the 4-block limit
if "cache_control" in msg_copy:
del msg_copy["cache_control"]
msg_copy = msg.copy()
# Remove any existing cache_control to avoid exceeding provider limits
msg_copy.pop("cache_control", None)
converted_messages.append(msg_copy)
# Then convert and add the new input
new_messages = self._converter.items_to_messages(input, model_instance=self)
converted_messages.extend(new_messages)
# Only add converted input if there is no history yet (e.g., very first turn)
if not self.message_history:
new_messages = self._converter.items_to_messages(input, model_instance=self)
converted_messages.extend(new_messages)
if system_instructions:
# Check if we already have a system message
@ -3233,7 +3234,7 @@ class OpenAIChatCompletionsModel(Model):
try:
if stream:
# Standard LiteLLM handling for streaming
ret = await litellm.acompletion(**kwargs)
# Create a single streaming generator; avoid duplicate calls which leak connections
stream_obj = await litellm.acompletion(**kwargs)
response = Response(
@ -3287,7 +3288,7 @@ class OpenAIChatCompletionsModel(Model):
kwargs["messages"] = messages
# Retry once, silently
if stream:
ret = await litellm.acompletion(**kwargs)
# Retry with a single streaming generator
stream_obj = await litellm.acompletion(**kwargs)
response = Response(
id=FAKE_RESPONSES_ID,

View File

@ -1377,7 +1377,53 @@ def fix_message_list(messages): # pylint: disable=R0914,R0915,R0912
i += 2
else:
i += 1
return processed_messages
# Final de-duplication pass to remove accidental duplicates in chat history
# This addresses cases where the latest user message or tool pair was added twice upstream.
deduped = []
for msg in processed_messages:
if not deduped:
deduped.append(msg)
continue
prev = deduped[-1]
# Normalize messages for comparison (ignore ephemeral fields ordering)
def _norm_tool_calls(m):
tcs = m.get("tool_calls") or []
norm = []
for tc in tcs:
if isinstance(tc, dict):
fn = tc.get("function") or {}
norm.append((tc.get("type"), fn.get("name"), fn.get("arguments")))
return tuple(norm)
same_role = prev.get("role") == msg.get("role")
# Compare content for text messages
same_content = str(prev.get("content")) == str(msg.get("content"))
# Compare tool ids for tool messages
same_tool_id = (
prev.get("role") == "tool"
and msg.get("role") == "tool"
and str(prev.get("tool_call_id")) == str(msg.get("tool_call_id"))
and str(prev.get("content")) == str(msg.get("content"))
)
# Compare assistant tool calls by name/args (IDs may differ by truncation)
same_assistant_tool_calls = (
prev.get("role") == "assistant"
and msg.get("role") == "assistant"
and prev.get("tool_calls")
and msg.get("tool_calls")
and _norm_tool_calls(prev) == _norm_tool_calls(msg)
)
if (same_role and same_content) or same_tool_id or same_assistant_tool_calls:
# Skip exact duplicate
continue
deduped.append(msg)
return deduped
def cli_print_tool_call(tool_name="", args="", output="", prefix=" "):