fix: preserve json mode preamble text

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
ryan 2026-10-28 08:37:57 +00:00
parent e50ae35dde
commit e323ea243a
3 changed files with 19 additions and 1 deletions

View file

@ -1633,6 +1633,7 @@ OPENAI_FINISH_REASONS: Final = [
]
HUMANLOOP_PROMPT_CACHE_TTL_SECONDS: Final = get_env_int("HUMANLOOP_PROMPT_CACHE_TTL_SECONDS", 60) # 1 minute
RESPONSE_FORMAT_TOOL_NAME = "json_tool_call" # default tool name used when converting response format to tool call
JSON_MODE_PREAMBLE_TEXT_KEY: Final = "json_mode_preamble_text"
########################### Logging Callback Constants ###########################
AZURE_STORAGE_MSFT_VERSION: Final = "2019-07-07"

View file

@ -21,6 +21,7 @@ from litellm.constants import (
DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_XHIGH_THINKING_BUDGET,
JSON_MODE_PREAMBLE_TEXT_KEY,
RESPONSE_FORMAT_TOOL_NAME,
)
from litellm.litellm_core_utils.core_helpers import drops_unsupported_params, map_finish_reason
@ -3056,7 +3057,12 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
REFUSAL_STOP_FIELDS.validate_python(completion_response)
)
completion_response["stop_reason"] = "stop"
if refusal_fields:
if text_content and text_content.strip():
json_mode_message.provider_specific_fields = {
**refusal_fields,
JSON_MODE_PREAMBLE_TEXT_KEY: text_content,
}
elif refusal_fields:
json_mode_message.provider_specific_fields = dict(refusal_fields)
if thinking_blocks:
json_mode_message.thinking_blocks = thinking_blocks

View file

@ -19,6 +19,7 @@ import litellm
from litellm._logging import verbose_logger
from litellm.constants import (
BEDROCK_MIN_THINKING_BUDGET_TOKENS,
JSON_MODE_PREAMBLE_TEXT_KEY,
RESPONSE_FORMAT_TOOL_NAME,
)
from litellm.litellm_core_utils.core_helpers import (
@ -2676,6 +2677,16 @@ class AmazonConverseConfig(BaseConfig):
json_mode_content_str: str | None = tools[0]["function"].get("arguments")
if json_mode_content_str is not None:
json_mode_content_str = AmazonConverseConfig._unwrap_bedrock_properties(json_mode_content_str)
message_fields: Final = as_str_mapping(chat_completion_message)
existing_content: Final = (message_fields or {}).get("content")
if isinstance(existing_content, str) and existing_content.strip():
existing_provider_fields: Final = TypeAdapter(dict[str, object]).validate_python(
(message_fields.get("provider_specific_fields") or {}) if message_fields is not None else {}
)
chat_completion_message["provider_specific_fields"] = { # rebind-ok: response is built in place
**existing_provider_fields,
JSON_MODE_PREAMBLE_TEXT_KEY: existing_content,
}
chat_completion_message["content"] = json_mode_content_str
return None