From bc8ef371926a09f1b3e462bf63bfab4d15c9ea03 Mon Sep 17 00:00:00 2001 From: Ray Myers Date: Thu, 17 Jul 2025 11:42:06 -0500 Subject: [PATCH] fix - Avoid building debug log message when not logged (#9600) --- openhands/llm/debug_mixin.py | 22 +++++++++++++++++++++- openhands/llm/llm.py | 14 ++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/openhands/llm/debug_mixin.py b/openhands/llm/debug_mixin.py index f80d98d7ad..7438f455c4 100644 --- a/openhands/llm/debug_mixin.py +++ b/openhands/llm/debug_mixin.py @@ -1,5 +1,9 @@ +from logging import DEBUG from typing import Any +from litellm import ChatCompletionMessageToolCall +from litellm.types.utils import ModelResponse + from openhands.core.logger import llm_prompt_logger, llm_response_logger from openhands.core.logger import openhands_logger as logger @@ -8,6 +12,9 @@ MESSAGE_SEPARATOR = '\n\n----------\n\n' class DebugMixin: def log_prompt(self, messages: list[dict[str, Any]] | dict[str, Any]) -> None: + if not logger.isEnabledFor(DEBUG): + # Don't use memory building message string if not logging. + return if not messages: logger.debug('No completion messages!') return @@ -24,7 +31,20 @@ class DebugMixin: else: logger.debug('No completion messages!') - def log_response(self, message_back: str) -> None: + def log_response(self, resp: ModelResponse) -> None: + if not logger.isEnabledFor(DEBUG): + # Don't use memory building message string if not logging. + return + message_back: str = resp['choices'][0]['message']['content'] or '' + tool_calls: list[ChatCompletionMessageToolCall] = resp['choices'][0][ + 'message' + ].get('tool_calls', []) + if tool_calls: + for tool_call in tool_calls: + fn_name = tool_call.function.name + fn_args = tool_call.function.arguments + message_back += f'\nFunction call: {fn_name}({fn_args})' + if message_back: llm_response_logger.debug(message_back) diff --git a/openhands/llm/llm.py b/openhands/llm/llm.py index 9c341d2f37..554693cd54 100644 --- a/openhands/llm/llm.py +++ b/openhands/llm/llm.py @@ -13,8 +13,8 @@ with warnings.catch_warnings(): warnings.simplefilter('ignore') import litellm -from litellm import ChatCompletionMessageToolCall, ModelInfo, PromptTokensDetails from litellm import Message as LiteLLMMessage +from litellm import ModelInfo, PromptTokensDetails from litellm import completion as litellm_completion from litellm import completion_cost as litellm_completion_cost from litellm.exceptions import ( @@ -365,18 +365,8 @@ class LLM(RetryMixin, DebugMixin): + str(resp) ) - message_back: str = resp['choices'][0]['message']['content'] or '' - tool_calls: list[ChatCompletionMessageToolCall] = resp['choices'][0][ - 'message' - ].get('tool_calls', []) - if tool_calls: - for tool_call in tool_calls: - fn_name = tool_call.function.name - fn_args = tool_call.function.arguments - message_back += f'\nFunction call: {fn_name}({fn_args})' - # log the LLM response - self.log_response(message_back) + self.log_response(resp) # post-process the response first to calculate cost cost = self._post_completion(resp)