mirascope 2.0.0a3__py3-none-any.whl → 2.0.0a5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mirascope/api/_generated/__init__.py +78 -6
- mirascope/api/_generated/api_keys/__init__.py +7 -0
- mirascope/api/_generated/api_keys/client.py +453 -0
- mirascope/api/_generated/api_keys/raw_client.py +853 -0
- mirascope/api/_generated/api_keys/types/__init__.py +9 -0
- mirascope/api/_generated/api_keys/types/api_keys_create_response.py +36 -0
- mirascope/api/_generated/api_keys/types/api_keys_get_response.py +35 -0
- mirascope/api/_generated/api_keys/types/api_keys_list_response_item.py +35 -0
- mirascope/api/_generated/client.py +14 -0
- mirascope/api/_generated/environments/__init__.py +17 -0
- mirascope/api/_generated/environments/client.py +532 -0
- mirascope/api/_generated/environments/raw_client.py +1088 -0
- mirascope/api/_generated/environments/types/__init__.py +15 -0
- mirascope/api/_generated/environments/types/environments_create_response.py +26 -0
- mirascope/api/_generated/environments/types/environments_get_response.py +26 -0
- mirascope/api/_generated/environments/types/environments_list_response_item.py +26 -0
- mirascope/api/_generated/environments/types/environments_update_response.py +26 -0
- mirascope/api/_generated/errors/__init__.py +11 -1
- mirascope/api/_generated/errors/conflict_error.py +15 -0
- mirascope/api/_generated/errors/forbidden_error.py +15 -0
- mirascope/api/_generated/errors/internal_server_error.py +15 -0
- mirascope/api/_generated/errors/not_found_error.py +15 -0
- mirascope/api/_generated/organizations/__init__.py +25 -0
- mirascope/api/_generated/organizations/client.py +404 -0
- mirascope/api/_generated/organizations/raw_client.py +902 -0
- mirascope/api/_generated/organizations/types/__init__.py +23 -0
- mirascope/api/_generated/organizations/types/organizations_create_response.py +25 -0
- mirascope/api/_generated/organizations/types/organizations_create_response_role.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_get_response.py +25 -0
- mirascope/api/_generated/organizations/types/organizations_get_response_role.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_list_response_item.py +25 -0
- mirascope/api/_generated/organizations/types/organizations_list_response_item_role.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_update_response.py +25 -0
- mirascope/api/_generated/organizations/types/organizations_update_response_role.py +7 -0
- mirascope/api/_generated/projects/__init__.py +17 -0
- mirascope/api/_generated/projects/client.py +482 -0
- mirascope/api/_generated/projects/raw_client.py +1058 -0
- mirascope/api/_generated/projects/types/__init__.py +15 -0
- mirascope/api/_generated/projects/types/projects_create_response.py +31 -0
- mirascope/api/_generated/projects/types/projects_get_response.py +31 -0
- mirascope/api/_generated/projects/types/projects_list_response_item.py +31 -0
- mirascope/api/_generated/projects/types/projects_update_response.py +31 -0
- mirascope/api/_generated/reference.md +1311 -0
- mirascope/api/_generated/types/__init__.py +20 -4
- mirascope/api/_generated/types/already_exists_error.py +24 -0
- mirascope/api/_generated/types/already_exists_error_tag.py +5 -0
- mirascope/api/_generated/types/database_error.py +24 -0
- mirascope/api/_generated/types/database_error_tag.py +5 -0
- mirascope/api/_generated/types/http_api_decode_error.py +1 -3
- mirascope/api/_generated/types/issue.py +1 -5
- mirascope/api/_generated/types/not_found_error_body.py +24 -0
- mirascope/api/_generated/types/not_found_error_tag.py +5 -0
- mirascope/api/_generated/types/permission_denied_error.py +24 -0
- mirascope/api/_generated/types/permission_denied_error_tag.py +7 -0
- mirascope/api/_generated/types/property_key.py +2 -2
- mirascope/api/_generated/types/{property_key_tag.py → property_key_key.py} +3 -5
- mirascope/api/_generated/types/{property_key_tag_tag.py → property_key_key_tag.py} +1 -1
- mirascope/llm/__init__.py +6 -2
- mirascope/llm/exceptions.py +28 -0
- mirascope/llm/providers/__init__.py +12 -4
- mirascope/llm/providers/anthropic/__init__.py +6 -1
- mirascope/llm/providers/anthropic/_utils/__init__.py +17 -5
- mirascope/llm/providers/anthropic/_utils/beta_decode.py +271 -0
- mirascope/llm/providers/anthropic/_utils/beta_encode.py +216 -0
- mirascope/llm/providers/anthropic/_utils/decode.py +39 -7
- mirascope/llm/providers/anthropic/_utils/encode.py +156 -64
- mirascope/llm/providers/anthropic/_utils/errors.py +46 -0
- mirascope/llm/providers/anthropic/beta_provider.py +328 -0
- mirascope/llm/providers/anthropic/model_id.py +10 -27
- mirascope/llm/providers/anthropic/model_info.py +87 -0
- mirascope/llm/providers/anthropic/provider.py +132 -145
- mirascope/llm/providers/base/__init__.py +2 -1
- mirascope/llm/providers/base/_utils.py +15 -1
- mirascope/llm/providers/base/base_provider.py +173 -58
- mirascope/llm/providers/google/_utils/__init__.py +2 -0
- mirascope/llm/providers/google/_utils/decode.py +55 -3
- mirascope/llm/providers/google/_utils/encode.py +14 -6
- mirascope/llm/providers/google/_utils/errors.py +49 -0
- mirascope/llm/providers/google/model_id.py +7 -13
- mirascope/llm/providers/google/model_info.py +62 -0
- mirascope/llm/providers/google/provider.py +13 -8
- mirascope/llm/providers/mlx/_utils.py +31 -2
- mirascope/llm/providers/mlx/encoding/transformers.py +17 -1
- mirascope/llm/providers/mlx/provider.py +12 -0
- mirascope/llm/providers/ollama/__init__.py +19 -0
- mirascope/llm/providers/ollama/provider.py +71 -0
- mirascope/llm/providers/openai/__init__.py +10 -1
- mirascope/llm/providers/openai/_utils/__init__.py +5 -0
- mirascope/llm/providers/openai/_utils/errors.py +46 -0
- mirascope/llm/providers/openai/completions/__init__.py +6 -1
- mirascope/llm/providers/openai/completions/_utils/decode.py +57 -5
- mirascope/llm/providers/openai/completions/_utils/encode.py +9 -8
- mirascope/llm/providers/openai/completions/base_provider.py +513 -0
- mirascope/llm/providers/openai/completions/provider.py +13 -447
- mirascope/llm/providers/openai/model_info.py +57 -0
- mirascope/llm/providers/openai/provider.py +30 -5
- mirascope/llm/providers/openai/responses/_utils/decode.py +55 -4
- mirascope/llm/providers/openai/responses/_utils/encode.py +9 -9
- mirascope/llm/providers/openai/responses/provider.py +33 -28
- mirascope/llm/providers/provider_id.py +11 -1
- mirascope/llm/providers/provider_registry.py +59 -4
- mirascope/llm/providers/together/__init__.py +19 -0
- mirascope/llm/providers/together/provider.py +40 -0
- mirascope/llm/responses/__init__.py +3 -0
- mirascope/llm/responses/base_response.py +4 -0
- mirascope/llm/responses/base_stream_response.py +25 -1
- mirascope/llm/responses/finish_reason.py +1 -0
- mirascope/llm/responses/response.py +9 -0
- mirascope/llm/responses/root_response.py +5 -1
- mirascope/llm/responses/usage.py +95 -0
- mirascope/ops/_internal/closure.py +62 -11
- {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/METADATA +3 -3
- {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/RECORD +115 -56
- mirascope/llm/providers/load_provider.py +0 -48
- mirascope/llm/providers/openai/shared/__init__.py +0 -7
- mirascope/llm/providers/openai/shared/_utils.py +0 -59
- {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/WHEEL +0 -0
- {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"""Anthropic
|
|
1
|
+
"""Shared Anthropic encoding utilities."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from collections.abc import Sequence
|
|
5
5
|
from functools import lru_cache
|
|
6
|
-
from typing import Literal, TypedDict, cast
|
|
6
|
+
from typing import Any, Literal, TypedDict, cast
|
|
7
7
|
from typing_extensions import Required
|
|
8
8
|
|
|
9
9
|
from anthropic import Omit, types as anthropic_types
|
|
@@ -22,14 +22,14 @@ from ...base import Params, _utils as _base_utils
|
|
|
22
22
|
from ..model_id import AnthropicModelId, model_name
|
|
23
23
|
|
|
24
24
|
DEFAULT_MAX_TOKENS = 16000
|
|
25
|
+
# TODO: Change DEFAULT_FORMAT_MODE to strict when strict is no longer a beta feature.
|
|
26
|
+
DEFAULT_FORMAT_MODE = "tool"
|
|
25
27
|
|
|
26
28
|
AnthropicImageMimeType = Literal["image/jpeg", "image/png", "image/gif", "image/webp"]
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
def encode_image_mime_type(
|
|
30
|
-
|
|
31
|
-
) -> AnthropicImageMimeType:
|
|
32
|
-
"""Convert an ImageMimeType into anthropic supported mime type"""
|
|
31
|
+
def encode_image_mime_type(mime_type: ImageMimeType) -> AnthropicImageMimeType:
|
|
32
|
+
"""Convert an ImageMimeType into anthropic supported mime type."""
|
|
33
33
|
if mime_type in ("image/jpeg", "image/png", "image/gif", "image/webp"):
|
|
34
34
|
return mime_type
|
|
35
35
|
raise FeatureNotSupportedError(
|
|
@@ -37,13 +37,60 @@ def encode_image_mime_type(
|
|
|
37
37
|
) # pragma: no cover
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
class ProcessedParams(TypedDict, total=False):
|
|
41
|
+
"""Common parameters processed from Params."""
|
|
42
|
+
|
|
43
|
+
temperature: float
|
|
44
|
+
max_tokens: int
|
|
45
|
+
top_p: float
|
|
46
|
+
top_k: int
|
|
47
|
+
stop_sequences: list[str]
|
|
48
|
+
thinking: dict[str, Any]
|
|
49
|
+
encode_thoughts: bool
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def process_params(params: Params, default_max_tokens: int) -> ProcessedParams:
|
|
53
|
+
"""Process common Anthropic parameters from Params.
|
|
54
|
+
|
|
55
|
+
Returns a dict with processed parameters that can be merged into kwargs.
|
|
56
|
+
"""
|
|
57
|
+
result: ProcessedParams = {
|
|
58
|
+
"max_tokens": default_max_tokens,
|
|
59
|
+
"encode_thoughts": False,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
with _base_utils.ensure_all_params_accessed(
|
|
63
|
+
params=params, provider_id="anthropic", unsupported_params=["seed"]
|
|
64
|
+
) as param_accessor:
|
|
65
|
+
if param_accessor.temperature is not None:
|
|
66
|
+
result["temperature"] = param_accessor.temperature
|
|
67
|
+
if param_accessor.max_tokens is not None:
|
|
68
|
+
result["max_tokens"] = param_accessor.max_tokens
|
|
69
|
+
if param_accessor.top_p is not None:
|
|
70
|
+
result["top_p"] = param_accessor.top_p
|
|
71
|
+
if param_accessor.top_k is not None:
|
|
72
|
+
result["top_k"] = param_accessor.top_k
|
|
73
|
+
if param_accessor.stop_sequences is not None:
|
|
74
|
+
result["stop_sequences"] = param_accessor.stop_sequences
|
|
75
|
+
if param_accessor.thinking is not None:
|
|
76
|
+
if param_accessor.thinking:
|
|
77
|
+
budget_tokens = max(1024, result["max_tokens"] // 2)
|
|
78
|
+
result["thinking"] = {"type": "enabled", "budget_tokens": budget_tokens}
|
|
79
|
+
else:
|
|
80
|
+
result["thinking"] = {"type": "disabled"}
|
|
81
|
+
if param_accessor.encode_thoughts_as_text:
|
|
82
|
+
result["encode_thoughts"] = True
|
|
83
|
+
|
|
84
|
+
return result
|
|
85
|
+
|
|
86
|
+
|
|
40
87
|
class MessageCreateKwargs(TypedDict, total=False):
|
|
41
88
|
"""Kwargs for Anthropic Message.create method."""
|
|
42
89
|
|
|
43
90
|
model: Required[str]
|
|
44
91
|
max_tokens: Required[int]
|
|
45
92
|
messages: Sequence[anthropic_types.MessageParam]
|
|
46
|
-
system:
|
|
93
|
+
system: Sequence[anthropic_types.TextBlockParam] | Omit
|
|
47
94
|
tools: Sequence[anthropic_types.ToolParam] | Omit
|
|
48
95
|
tool_choice: anthropic_types.ToolChoiceParam | Omit
|
|
49
96
|
temperature: float | Omit
|
|
@@ -53,8 +100,10 @@ class MessageCreateKwargs(TypedDict, total=False):
|
|
|
53
100
|
thinking: anthropic_types.ThinkingConfigParam | Omit
|
|
54
101
|
|
|
55
102
|
|
|
56
|
-
def
|
|
57
|
-
content: Sequence[ContentPart],
|
|
103
|
+
def encode_content(
|
|
104
|
+
content: Sequence[ContentPart],
|
|
105
|
+
encode_thoughts: bool,
|
|
106
|
+
add_cache_control: bool,
|
|
58
107
|
) -> str | Sequence[anthropic_types.ContentBlockParam]:
|
|
59
108
|
"""Convert mirascope content to Anthropic content format."""
|
|
60
109
|
|
|
@@ -65,15 +114,42 @@ def _encode_content(
|
|
|
65
114
|
"anthropic",
|
|
66
115
|
message="Anthropic does not support empty message content.",
|
|
67
116
|
)
|
|
117
|
+
if add_cache_control:
|
|
118
|
+
return [
|
|
119
|
+
anthropic_types.TextBlockParam(
|
|
120
|
+
type="text",
|
|
121
|
+
text=content[0].text,
|
|
122
|
+
cache_control={"type": "ephemeral"},
|
|
123
|
+
)
|
|
124
|
+
]
|
|
68
125
|
return content[0].text
|
|
69
126
|
|
|
70
127
|
blocks: list[anthropic_types.ContentBlockParam] = []
|
|
71
128
|
|
|
72
|
-
|
|
129
|
+
# Find the last cacheable content part (text, image, tool_result, or tool_call)
|
|
130
|
+
last_cacheable_index = -1
|
|
131
|
+
if add_cache_control:
|
|
132
|
+
for i in range(len(content) - 1, -1, -1):
|
|
133
|
+
part = content[i]
|
|
134
|
+
if part.type in ("text", "image", "tool_output", "tool_call"):
|
|
135
|
+
if part.type == "text" and not part.text: # pragma: no cover
|
|
136
|
+
continue # Skip empty text
|
|
137
|
+
last_cacheable_index = i
|
|
138
|
+
break
|
|
139
|
+
|
|
140
|
+
for i, part in enumerate(content):
|
|
141
|
+
should_add_cache = add_cache_control and i == last_cacheable_index
|
|
142
|
+
|
|
73
143
|
if part.type == "text":
|
|
74
144
|
if part.text:
|
|
75
145
|
blocks.append(
|
|
76
|
-
anthropic_types.TextBlockParam(
|
|
146
|
+
anthropic_types.TextBlockParam(
|
|
147
|
+
type="text",
|
|
148
|
+
text=part.text,
|
|
149
|
+
cache_control={"type": "ephemeral"}
|
|
150
|
+
if should_add_cache
|
|
151
|
+
else None,
|
|
152
|
+
)
|
|
77
153
|
)
|
|
78
154
|
elif part.type == "image":
|
|
79
155
|
source: (
|
|
@@ -91,7 +167,13 @@ def _encode_content(
|
|
|
91
167
|
type="url",
|
|
92
168
|
url=part.source.url,
|
|
93
169
|
)
|
|
94
|
-
blocks.append(
|
|
170
|
+
blocks.append(
|
|
171
|
+
anthropic_types.ImageBlockParam(
|
|
172
|
+
type="image",
|
|
173
|
+
source=source,
|
|
174
|
+
cache_control={"type": "ephemeral"} if should_add_cache else None,
|
|
175
|
+
)
|
|
176
|
+
)
|
|
95
177
|
elif part.type == "audio":
|
|
96
178
|
raise FeatureNotSupportedError(
|
|
97
179
|
"audio input",
|
|
@@ -104,6 +186,7 @@ def _encode_content(
|
|
|
104
186
|
type="tool_result",
|
|
105
187
|
tool_use_id=part.id,
|
|
106
188
|
content=str(part.value),
|
|
189
|
+
cache_control={"type": "ephemeral"} if should_add_cache else None,
|
|
107
190
|
)
|
|
108
191
|
)
|
|
109
192
|
elif part.type == "tool_call":
|
|
@@ -113,6 +196,7 @@ def _encode_content(
|
|
|
113
196
|
id=part.id,
|
|
114
197
|
name=part.name,
|
|
115
198
|
input=json.loads(part.args),
|
|
199
|
+
cache_control={"type": "ephemeral"} if should_add_cache else None,
|
|
116
200
|
)
|
|
117
201
|
)
|
|
118
202
|
elif part.type == "thought":
|
|
@@ -139,33 +223,60 @@ def _encode_message(
|
|
|
139
223
|
message: UserMessage | AssistantMessage,
|
|
140
224
|
model_id: AnthropicModelId,
|
|
141
225
|
encode_thoughts: bool,
|
|
226
|
+
add_cache_control: bool = False,
|
|
142
227
|
) -> anthropic_types.MessageParam:
|
|
143
|
-
"""Convert user or assistant
|
|
228
|
+
"""Convert user or assistant Message to Anthropic MessageParam format.
|
|
144
229
|
|
|
145
230
|
Args:
|
|
146
|
-
|
|
147
|
-
model_id: The Anthropic model ID
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
A Sequence of converted Anthropic `MessageParam`
|
|
231
|
+
message: The message to encode
|
|
232
|
+
model_id: The Anthropic model ID
|
|
233
|
+
encode_thoughts: Whether to encode thought blocks as text
|
|
234
|
+
add_cache_control: Whether to add cache_control to the last content block
|
|
151
235
|
"""
|
|
152
|
-
|
|
153
236
|
if (
|
|
154
237
|
message.role == "assistant"
|
|
155
238
|
and message.provider_id == "anthropic"
|
|
156
239
|
and message.model_id == model_id
|
|
157
240
|
and message.raw_message
|
|
158
241
|
and not encode_thoughts
|
|
242
|
+
and not add_cache_control
|
|
159
243
|
):
|
|
160
244
|
return cast(anthropic_types.MessageParam, message.raw_message)
|
|
245
|
+
|
|
246
|
+
content = encode_content(message.content, encode_thoughts, add_cache_control)
|
|
247
|
+
|
|
161
248
|
return {
|
|
162
249
|
"role": message.role,
|
|
163
|
-
"content":
|
|
250
|
+
"content": content,
|
|
164
251
|
}
|
|
165
252
|
|
|
166
253
|
|
|
254
|
+
def _encode_messages(
|
|
255
|
+
messages: Sequence[UserMessage | AssistantMessage],
|
|
256
|
+
model_id: AnthropicModelId,
|
|
257
|
+
encode_thoughts: bool,
|
|
258
|
+
) -> Sequence[anthropic_types.MessageParam]:
|
|
259
|
+
"""Encode messages and add cache control for multi-turn conversations.
|
|
260
|
+
|
|
261
|
+
If the conversation contains assistant messages (indicating multi-turn),
|
|
262
|
+
adds cache_control to the last content block of the last message.
|
|
263
|
+
"""
|
|
264
|
+
# Detect multi-turn conversations by checking for assistant messages
|
|
265
|
+
has_assistant_message = any(msg.role == "assistant" for msg in messages)
|
|
266
|
+
|
|
267
|
+
# Encode messages, adding cache_control to the last message if multi-turn
|
|
268
|
+
encoded_messages: list[anthropic_types.MessageParam] = []
|
|
269
|
+
for i, message in enumerate(messages):
|
|
270
|
+
is_last = i == len(messages) - 1
|
|
271
|
+
add_cache = has_assistant_message and is_last
|
|
272
|
+
encoded_messages.append(
|
|
273
|
+
_encode_message(message, model_id, encode_thoughts, add_cache)
|
|
274
|
+
)
|
|
275
|
+
return encoded_messages
|
|
276
|
+
|
|
277
|
+
|
|
167
278
|
@lru_cache(maxsize=128)
|
|
168
|
-
def
|
|
279
|
+
def convert_tool_to_tool_param(tool: AnyToolSchema) -> anthropic_types.ToolParam:
|
|
169
280
|
"""Convert a single Mirascope tool to Anthropic tool format with caching."""
|
|
170
281
|
schema_dict = tool.parameters.model_dump(by_alias=True, exclude_none=True)
|
|
171
282
|
schema_dict["type"] = "object"
|
|
@@ -184,54 +295,29 @@ def encode_request(
|
|
|
184
295
|
format: type[FormattableT] | Format[FormattableT] | None,
|
|
185
296
|
params: Params,
|
|
186
297
|
) -> tuple[Sequence[Message], Format[FormattableT] | None, MessageCreateKwargs]:
|
|
187
|
-
"""Prepares a request for the
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
298
|
+
"""Prepares a request for the Anthropic messages.create method."""
|
|
299
|
+
|
|
300
|
+
processed = process_params(params, DEFAULT_MAX_TOKENS)
|
|
301
|
+
encode_thoughts = processed.pop("encode_thoughts", False)
|
|
302
|
+
max_tokens = processed.pop("max_tokens", DEFAULT_MAX_TOKENS)
|
|
192
303
|
|
|
193
304
|
kwargs: MessageCreateKwargs = MessageCreateKwargs(
|
|
194
|
-
{
|
|
195
|
-
"model": model_name(model_id),
|
|
196
|
-
"max_tokens": DEFAULT_MAX_TOKENS,
|
|
197
|
-
}
|
|
305
|
+
{"model": model_name(model_id), "max_tokens": max_tokens, **processed}
|
|
198
306
|
)
|
|
199
|
-
encode_thoughts = False
|
|
200
|
-
|
|
201
|
-
with _base_utils.ensure_all_params_accessed(
|
|
202
|
-
params=params, provider_id="anthropic", unsupported_params=["seed"]
|
|
203
|
-
) as param_accessor:
|
|
204
|
-
if param_accessor.temperature is not None:
|
|
205
|
-
kwargs["temperature"] = param_accessor.temperature
|
|
206
|
-
if param_accessor.max_tokens is not None:
|
|
207
|
-
kwargs["max_tokens"] = param_accessor.max_tokens
|
|
208
|
-
if param_accessor.top_p is not None:
|
|
209
|
-
kwargs["top_p"] = param_accessor.top_p
|
|
210
|
-
if param_accessor.top_k is not None:
|
|
211
|
-
kwargs["top_k"] = param_accessor.top_k
|
|
212
|
-
if param_accessor.stop_sequences is not None:
|
|
213
|
-
kwargs["stop_sequences"] = param_accessor.stop_sequences
|
|
214
|
-
if param_accessor.thinking is not None:
|
|
215
|
-
if param_accessor.thinking:
|
|
216
|
-
# Set budget to 50% of max_tokens with minimum of 1024
|
|
217
|
-
budget_tokens = max(1024, kwargs["max_tokens"] // 2)
|
|
218
|
-
kwargs["thinking"] = {"type": "enabled", "budget_tokens": budget_tokens}
|
|
219
|
-
else:
|
|
220
|
-
kwargs["thinking"] = {"type": "disabled"}
|
|
221
|
-
if param_accessor.encode_thoughts_as_text:
|
|
222
|
-
encode_thoughts = True
|
|
223
307
|
|
|
224
308
|
tools = tools.tools if isinstance(tools, BaseToolkit) else tools or []
|
|
225
|
-
anthropic_tools = [
|
|
226
|
-
format = resolve_format(format, default_mode=
|
|
309
|
+
anthropic_tools = [convert_tool_to_tool_param(tool) for tool in tools]
|
|
310
|
+
format = resolve_format(format, default_mode=DEFAULT_FORMAT_MODE)
|
|
227
311
|
if format is not None:
|
|
228
312
|
if format.mode == "strict":
|
|
229
313
|
raise FormattingModeNotSupportedError(
|
|
230
|
-
formatting_mode="strict",
|
|
314
|
+
formatting_mode="strict",
|
|
315
|
+
provider_id="anthropic",
|
|
316
|
+
model_id=model_id,
|
|
231
317
|
)
|
|
232
|
-
|
|
318
|
+
if format.mode == "tool":
|
|
233
319
|
format_tool_schema = _formatting_utils.create_tool_schema(format)
|
|
234
|
-
anthropic_tools.append(
|
|
320
|
+
anthropic_tools.append(convert_tool_to_tool_param(format_tool_schema))
|
|
235
321
|
if tools:
|
|
236
322
|
kwargs["tool_choice"] = {"type": "any"}
|
|
237
323
|
else:
|
|
@@ -247,18 +333,24 @@ def encode_request(
|
|
|
247
333
|
)
|
|
248
334
|
|
|
249
335
|
if anthropic_tools:
|
|
336
|
+
# Add cache control to the last tool for prompt caching
|
|
337
|
+
last_tool = anthropic_tools[-1]
|
|
338
|
+
last_tool["cache_control"] = {"type": "ephemeral"}
|
|
250
339
|
kwargs["tools"] = anthropic_tools
|
|
251
340
|
|
|
252
341
|
system_message_content, remaining_messages = _base_utils.extract_system_message(
|
|
253
342
|
messages
|
|
254
343
|
)
|
|
255
344
|
|
|
256
|
-
kwargs["messages"] =
|
|
257
|
-
_encode_message(remaining_message, model_id, encode_thoughts)
|
|
258
|
-
for remaining_message in remaining_messages
|
|
259
|
-
]
|
|
345
|
+
kwargs["messages"] = _encode_messages(remaining_messages, model_id, encode_thoughts)
|
|
260
346
|
|
|
261
347
|
if system_message_content:
|
|
262
|
-
kwargs["system"] =
|
|
348
|
+
kwargs["system"] = [
|
|
349
|
+
anthropic_types.TextBlockParam(
|
|
350
|
+
type="text",
|
|
351
|
+
text=system_message_content,
|
|
352
|
+
cache_control={"type": "ephemeral"},
|
|
353
|
+
)
|
|
354
|
+
]
|
|
263
355
|
|
|
264
356
|
return messages, format, kwargs
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Anthropic error handling utilities."""
|
|
2
|
+
|
|
3
|
+
from anthropic import (
|
|
4
|
+
AnthropicError,
|
|
5
|
+
APIConnectionError as AnthropicAPIConnectionError,
|
|
6
|
+
APIResponseValidationError as AnthropicAPIResponseValidationError,
|
|
7
|
+
APITimeoutError as AnthropicAPITimeoutError,
|
|
8
|
+
AuthenticationError as AnthropicAuthenticationError,
|
|
9
|
+
BadRequestError as AnthropicBadRequestError,
|
|
10
|
+
ConflictError as AnthropicConflictError,
|
|
11
|
+
InternalServerError as AnthropicInternalServerError,
|
|
12
|
+
NotFoundError as AnthropicNotFoundError,
|
|
13
|
+
PermissionDeniedError as AnthropicPermissionDeniedError,
|
|
14
|
+
RateLimitError as AnthropicRateLimitError,
|
|
15
|
+
UnprocessableEntityError as AnthropicUnprocessableEntityError,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from ....exceptions import (
|
|
19
|
+
APIError,
|
|
20
|
+
AuthenticationError,
|
|
21
|
+
BadRequestError,
|
|
22
|
+
ConnectionError,
|
|
23
|
+
NotFoundError,
|
|
24
|
+
PermissionError,
|
|
25
|
+
RateLimitError,
|
|
26
|
+
ResponseValidationError,
|
|
27
|
+
ServerError,
|
|
28
|
+
TimeoutError,
|
|
29
|
+
)
|
|
30
|
+
from ...base import ProviderErrorMap
|
|
31
|
+
|
|
32
|
+
# Shared error mapping used by both AnthropicProvider and AnthropicBetaProvider
|
|
33
|
+
ANTHROPIC_ERROR_MAP: ProviderErrorMap = {
|
|
34
|
+
AnthropicAuthenticationError: AuthenticationError,
|
|
35
|
+
AnthropicPermissionDeniedError: PermissionError,
|
|
36
|
+
AnthropicBadRequestError: BadRequestError,
|
|
37
|
+
AnthropicUnprocessableEntityError: BadRequestError,
|
|
38
|
+
AnthropicNotFoundError: NotFoundError,
|
|
39
|
+
AnthropicConflictError: BadRequestError,
|
|
40
|
+
AnthropicRateLimitError: RateLimitError,
|
|
41
|
+
AnthropicInternalServerError: ServerError,
|
|
42
|
+
AnthropicAPITimeoutError: TimeoutError,
|
|
43
|
+
AnthropicAPIConnectionError: ConnectionError,
|
|
44
|
+
AnthropicAPIResponseValidationError: ResponseValidationError,
|
|
45
|
+
AnthropicError: APIError, # Catch-all for unknown Anthropic errors
|
|
46
|
+
}
|