From 0a0017ff457f66ee91c2d27edfab7725e0751156 Mon Sep 17 00:00:00 2001 From: Re-bin Date: Thu, 12 Mar 2026 03:08:53 +0000 Subject: [PATCH] fix: raise tool result history limit to 16k and force save_memory in consolidation --- nanobot/agent/memory.py | 1 + nanobot/providers/azure_openai_provider.py | 7 +++++-- nanobot/providers/base.py | 5 +++++ nanobot/providers/custom_provider.py | 5 +++-- nanobot/providers/litellm_provider.py | 3 ++- nanobot/providers/openai_codex_provider.py | 3 ++- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/nanobot/agent/memory.py b/nanobot/agent/memory.py index 59ba40e..802dd04 100644 --- a/nanobot/agent/memory.py +++ b/nanobot/agent/memory.py @@ -120,6 +120,7 @@ class MemoryStore: ], tools=_SAVE_MEMORY_TOOL, model=model, + tool_choice="required", ) if not response.has_tool_calls: diff --git a/nanobot/providers/azure_openai_provider.py b/nanobot/providers/azure_openai_provider.py index bd79b00..05fbac4 100644 --- a/nanobot/providers/azure_openai_provider.py +++ b/nanobot/providers/azure_openai_provider.py @@ -88,6 +88,7 @@ class AzureOpenAIProvider(LLMProvider): max_tokens: int = 4096, temperature: float = 0.7, reasoning_effort: str | None = None, + tool_choice: str | dict[str, Any] | None = None, ) -> dict[str, Any]: """Prepare the request payload with Azure OpenAI 2024-10-21 compliance.""" payload: dict[str, Any] = { @@ -106,7 +107,7 @@ class AzureOpenAIProvider(LLMProvider): if tools: payload["tools"] = tools - payload["tool_choice"] = "auto" + payload["tool_choice"] = tool_choice or "auto" return payload @@ -118,6 +119,7 @@ class AzureOpenAIProvider(LLMProvider): max_tokens: int = 4096, temperature: float = 0.7, reasoning_effort: str | None = None, + tool_choice: str | dict[str, Any] | None = None, ) -> LLMResponse: """ Send a chat completion request to Azure OpenAI. @@ -137,7 +139,8 @@ class AzureOpenAIProvider(LLMProvider): url = self._build_chat_url(deployment_name) headers = self._build_headers() payload = self._prepare_request_payload( - deployment_name, messages, tools, max_tokens, temperature, reasoning_effort + deployment_name, messages, tools, max_tokens, temperature, reasoning_effort, + tool_choice=tool_choice, ) try: diff --git a/nanobot/providers/base.py b/nanobot/providers/base.py index 15a10ff..114a948 100644 --- a/nanobot/providers/base.py +++ b/nanobot/providers/base.py @@ -166,6 +166,7 @@ class LLMProvider(ABC): max_tokens: int = 4096, temperature: float = 0.7, reasoning_effort: str | None = None, + tool_choice: str | dict[str, Any] | None = None, ) -> LLMResponse: """ Send a chat completion request. @@ -176,6 +177,7 @@ class LLMProvider(ABC): model: Model identifier (provider-specific). max_tokens: Maximum tokens in response. temperature: Sampling temperature. + tool_choice: Tool selection strategy ("auto", "required", or specific tool dict). Returns: LLMResponse with content and/or tool calls. @@ -195,6 +197,7 @@ class LLMProvider(ABC): max_tokens: object = _SENTINEL, temperature: object = _SENTINEL, reasoning_effort: object = _SENTINEL, + tool_choice: str | dict[str, Any] | None = None, ) -> LLMResponse: """Call chat() with retry on transient provider failures. @@ -218,6 +221,7 @@ class LLMProvider(ABC): max_tokens=max_tokens, temperature=temperature, reasoning_effort=reasoning_effort, + tool_choice=tool_choice, ) except asyncio.CancelledError: raise @@ -250,6 +254,7 @@ class LLMProvider(ABC): max_tokens=max_tokens, temperature=temperature, reasoning_effort=reasoning_effort, + tool_choice=tool_choice, ) except asyncio.CancelledError: raise diff --git a/nanobot/providers/custom_provider.py b/nanobot/providers/custom_provider.py index 66df734..f16c69b 100644 --- a/nanobot/providers/custom_provider.py +++ b/nanobot/providers/custom_provider.py @@ -25,7 +25,8 @@ class CustomProvider(LLMProvider): async def chat(self, messages: list[dict[str, Any]], tools: list[dict[str, Any]] | None = None, model: str | None = None, max_tokens: int = 4096, temperature: float = 0.7, - reasoning_effort: str | None = None) -> LLMResponse: + reasoning_effort: str | None = None, + tool_choice: str | dict[str, Any] | None = None) -> LLMResponse: kwargs: dict[str, Any] = { "model": model or self.default_model, "messages": self._sanitize_empty_content(messages), @@ -35,7 +36,7 @@ class CustomProvider(LLMProvider): if reasoning_effort: kwargs["reasoning_effort"] = reasoning_effort if tools: - kwargs.update(tools=tools, tool_choice="auto") + kwargs.update(tools=tools, tool_choice=tool_choice or "auto") try: return self._parse(await self._client.chat.completions.create(**kwargs)) except Exception as e: diff --git a/nanobot/providers/litellm_provider.py b/nanobot/providers/litellm_provider.py index af91c2f..b4508a4 100644 --- a/nanobot/providers/litellm_provider.py +++ b/nanobot/providers/litellm_provider.py @@ -214,6 +214,7 @@ class LiteLLMProvider(LLMProvider): max_tokens: int = 4096, temperature: float = 0.7, reasoning_effort: str | None = None, + tool_choice: str | dict[str, Any] | None = None, ) -> LLMResponse: """ Send a chat completion request via LiteLLM. @@ -267,7 +268,7 @@ class LiteLLMProvider(LLMProvider): if tools: kwargs["tools"] = tools - kwargs["tool_choice"] = "auto" + kwargs["tool_choice"] = tool_choice or "auto" try: response = await acompletion(**kwargs) diff --git a/nanobot/providers/openai_codex_provider.py b/nanobot/providers/openai_codex_provider.py index d04e210..c8f2155 100644 --- a/nanobot/providers/openai_codex_provider.py +++ b/nanobot/providers/openai_codex_provider.py @@ -32,6 +32,7 @@ class OpenAICodexProvider(LLMProvider): max_tokens: int = 4096, temperature: float = 0.7, reasoning_effort: str | None = None, + tool_choice: str | dict[str, Any] | None = None, ) -> LLMResponse: model = model or self.default_model system_prompt, input_items = _convert_messages(messages) @@ -48,7 +49,7 @@ class OpenAICodexProvider(LLMProvider): "text": {"verbosity": "medium"}, "include": ["reasoning.encrypted_content"], "prompt_cache_key": _prompt_cache_key(messages), - "tool_choice": "auto", + "tool_choice": tool_choice or "auto", "parallel_tool_calls": True, }