File tree Expand file tree Collapse file tree 3 files changed +19
-3
lines changed Expand file tree Collapse file tree 3 files changed +19
-3
lines changed Original file line number Diff line number Diff line change @@ -257,7 +257,15 @@ async def _fetch_response(
257257 stream : bool = False ,
258258 prompt : Any | None = None ,
259259 ) -> litellm .types .utils .ModelResponse | tuple [Response , AsyncStream [ChatCompletionChunk ]]:
260- converted_messages = Converter .items_to_messages (input )
260+ # Preserve reasoning messages for tool calls when reasoning is on
261+ # This is needed for models like Claude 4 Sonnet/Opus which support interleaved thinking
262+ preserve_reasoning_message = (
263+ model_settings .reasoning is not None and model_settings .reasoning .effort is not None
264+ )
265+
266+ converted_messages = Converter .items_to_messages (
267+ input , preserve_reasoning_message = preserve_reasoning_message
268+ )
261269
262270 if system_instructions :
263271 converted_messages .insert (
Original file line number Diff line number Diff line change @@ -315,10 +315,18 @@ def extract_all_content(
315315 def items_to_messages (
316316 cls ,
317317 items : str | Iterable [TResponseInputItem ],
318+ preserve_reasoning_message : bool = False ,
318319 ) -> list [ChatCompletionMessageParam ]:
319320 """
320321 Convert a sequence of 'Item' objects into a list of ChatCompletionMessageParam.
321322
323+ Args:
324+ items: A string or iterable of response input items to convert
325+ preserve_reasoning_message: Whether to preserve reasoning messages (thinking blocks)
326+ in tool calls for reasoning models like Claude 4 Sonnet/Opus which support
327+ interleaved thinking. When True, thinking blocks are reconstructed and
328+ included in assistant messages with tool calls.
329+
322330 Rules:
323331 - EasyInputMessage or InputMessage (role=user) => ChatCompletionUserMessageParam
324332 - EasyInputMessage or InputMessage (role=system) => ChatCompletionSystemMessageParam
@@ -512,7 +520,7 @@ def ensure_assistant_message() -> ChatCompletionAssistantMessageParam:
512520 content_items = reasoning_item .get ("content" , [])
513521 signature = reasoning_item .get ("encrypted_content" )
514522
515- if content_items :
523+ if content_items and preserve_reasoning_message :
516524 # Reconstruct thinking blocks from content and signature
517525 pending_thinking_blocks = []
518526 for content_item in content_items :
Original file line number Diff line number Diff line change @@ -176,7 +176,7 @@ def test_anthropic_thinking_blocks_with_tool_calls():
176176 else :
177177 items_as_dicts .append (cast (dict [str , Any ], item ))
178178
179- messages = Converter .items_to_messages (items_as_dicts ) # type: ignore[arg-type]
179+ messages = Converter .items_to_messages (items_as_dicts , preserve_reasoning_message = True ) # type: ignore[arg-type]
180180
181181 # Find the assistant message with tool calls
182182 assistant_messages = [
You can’t perform that action at this time.
0 commit comments