|
12 | 12 |
|
13 | 13 | from .models import AnthropicMessagesRequest |
14 | 14 |
|
| 15 | +MIN_THINKING_SIGNATURE_LENGTH = 100 |
| 16 | + |
15 | 17 |
|
16 | 18 | def anthropic_to_openai_messages( |
17 | 19 | anthropic_messages: List[dict], system: Optional[Union[str, List[dict]]] = None |
@@ -56,6 +58,8 @@ def anthropic_to_openai_messages( |
56 | 58 | # Handle content blocks |
57 | 59 | openai_content = [] |
58 | 60 | tool_calls = [] |
| 61 | + reasoning_content = "" |
| 62 | + thinking_signature = "" |
59 | 63 |
|
60 | 64 | for block in content: |
61 | 65 | if isinstance(block, dict): |
@@ -84,6 +88,17 @@ def anthropic_to_openai_messages( |
84 | 88 | "image_url": {"url": source.get("url", "")}, |
85 | 89 | } |
86 | 90 | ) |
| 91 | + elif block_type == "thinking": |
| 92 | + signature = block.get("signature", "") |
| 93 | + if signature and len(signature) >= MIN_THINKING_SIGNATURE_LENGTH: |
| 94 | + thinking_text = block.get("thinking", "") |
| 95 | + if thinking_text: |
| 96 | + reasoning_content += thinking_text |
| 97 | + thinking_signature = signature |
| 98 | + elif block_type == "redacted_thinking": |
| 99 | + signature = block.get("signature", "") |
| 100 | + if signature and len(signature) >= MIN_THINKING_SIGNATURE_LENGTH: |
| 101 | + thinking_signature = signature |
87 | 102 | elif block_type == "tool_use": |
88 | 103 | # Anthropic tool_use -> OpenAI tool_calls |
89 | 104 | tool_calls.append( |
@@ -196,16 +211,37 @@ def anthropic_to_openai_messages( |
196 | 211 | msg_dict["content"] = " ".join(text_parts) if text_parts else None |
197 | 212 | else: |
198 | 213 | msg_dict["content"] = None |
| 214 | + if reasoning_content: |
| 215 | + msg_dict["reasoning_content"] = reasoning_content |
| 216 | + if thinking_signature: |
| 217 | + msg_dict["thinking_signature"] = thinking_signature |
199 | 218 | msg_dict["tool_calls"] = tool_calls |
200 | 219 | openai_messages.append(msg_dict) |
201 | 220 | elif openai_content: |
202 | 221 | # Check if it's just text or mixed content |
203 | 222 | if len(openai_content) == 1 and openai_content[0].get("type") == "text": |
204 | | - openai_messages.append( |
205 | | - {"role": role, "content": openai_content[0].get("text", "")} |
206 | | - ) |
| 223 | + msg_dict = { |
| 224 | + "role": role, |
| 225 | + "content": openai_content[0].get("text", ""), |
| 226 | + } |
| 227 | + if reasoning_content: |
| 228 | + msg_dict["reasoning_content"] = reasoning_content |
| 229 | + if thinking_signature: |
| 230 | + msg_dict["thinking_signature"] = thinking_signature |
| 231 | + openai_messages.append(msg_dict) |
207 | 232 | else: |
208 | | - openai_messages.append({"role": role, "content": openai_content}) |
| 233 | + msg_dict = {"role": role, "content": openai_content} |
| 234 | + if reasoning_content: |
| 235 | + msg_dict["reasoning_content"] = reasoning_content |
| 236 | + if thinking_signature: |
| 237 | + msg_dict["thinking_signature"] = thinking_signature |
| 238 | + openai_messages.append(msg_dict) |
| 239 | + elif reasoning_content: |
| 240 | + msg_dict = {"role": role, "content": ""} |
| 241 | + msg_dict["reasoning_content"] = reasoning_content |
| 242 | + if thinking_signature: |
| 243 | + msg_dict["thinking_signature"] = thinking_signature |
| 244 | + openai_messages.append(msg_dict) |
209 | 245 |
|
210 | 246 | return openai_messages |
211 | 247 |
|
@@ -293,11 +329,18 @@ def openai_to_anthropic_response(openai_response: dict, original_model: str) -> |
293 | 329 | # Add thinking content block if reasoning_content is present |
294 | 330 | reasoning_content = message.get("reasoning_content") |
295 | 331 | if reasoning_content: |
| 332 | + thinking_signature = message.get("thinking_signature", "") |
| 333 | + signature = ( |
| 334 | + thinking_signature |
| 335 | + if thinking_signature |
| 336 | + and len(thinking_signature) >= MIN_THINKING_SIGNATURE_LENGTH |
| 337 | + else "" |
| 338 | + ) |
296 | 339 | content_blocks.append( |
297 | 340 | { |
298 | 341 | "type": "thinking", |
299 | 342 | "thinking": reasoning_content, |
300 | | - "signature": "", # Signature is typically empty for proxied responses |
| 343 | + "signature": signature, |
301 | 344 | } |
302 | 345 | ) |
303 | 346 |
|
|
0 commit comments