mirascope 2.1.0__py3-none-any.whl → 2.2.0__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/functions/client.py +10 -0
- mirascope/api/_generated/functions/raw_client.py +8 -0
- mirascope/api/_generated/functions/types/functions_create_response.py +25 -8
- mirascope/api/_generated/functions/types/functions_find_by_hash_response.py +25 -10
- mirascope/api/_generated/functions/types/functions_get_by_env_response.py +1 -0
- mirascope/api/_generated/functions/types/functions_get_response.py +25 -8
- mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item.py +1 -0
- mirascope/api/_generated/functions/types/functions_list_response_functions_item.py +22 -7
- mirascope/api/_generated/reference.md +9 -0
- mirascope/llm/__init__.py +42 -0
- mirascope/llm/calls/calls.py +38 -11
- mirascope/llm/exceptions.py +69 -0
- mirascope/llm/prompts/prompts.py +47 -9
- mirascope/llm/providers/__init__.py +3 -0
- mirascope/llm/providers/openai/completions/_utils/__init__.py +3 -0
- mirascope/llm/providers/openai/completions/_utils/encode.py +27 -32
- mirascope/llm/providers/openai/completions/_utils/feature_info.py +50 -0
- mirascope/llm/providers/openai/completions/base_provider.py +21 -0
- mirascope/llm/providers/openai/completions/provider.py +8 -2
- mirascope/llm/providers/openrouter/__init__.py +5 -0
- mirascope/llm/providers/openrouter/provider.py +67 -0
- mirascope/llm/providers/provider_id.py +2 -0
- mirascope/llm/providers/provider_registry.py +6 -0
- mirascope/llm/responses/response.py +217 -0
- mirascope/llm/responses/stream_response.py +234 -0
- mirascope/llm/retries/__init__.py +51 -0
- mirascope/llm/retries/retry_calls.py +159 -0
- mirascope/llm/retries/retry_config.py +168 -0
- mirascope/llm/retries/retry_decorator.py +258 -0
- mirascope/llm/retries/retry_models.py +1313 -0
- mirascope/llm/retries/retry_prompts.py +227 -0
- mirascope/llm/retries/retry_responses.py +340 -0
- mirascope/llm/retries/retry_stream_responses.py +571 -0
- mirascope/llm/retries/utils.py +159 -0
- mirascope/ops/_internal/versioned_calls.py +249 -9
- mirascope/ops/_internal/versioned_functions.py +2 -0
- {mirascope-2.1.0.dist-info → mirascope-2.2.0.dist-info}/METADATA +1 -1
- {mirascope-2.1.0.dist-info → mirascope-2.2.0.dist-info}/RECORD +40 -28
- {mirascope-2.1.0.dist-info → mirascope-2.2.0.dist-info}/WHEEL +0 -0
- {mirascope-2.1.0.dist-info → mirascope-2.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -66,6 +66,7 @@ class FunctionsClient:
|
|
|
66
66
|
signature: str,
|
|
67
67
|
signature_hash: str,
|
|
68
68
|
name: str,
|
|
69
|
+
language: str,
|
|
69
70
|
description: typing.Optional[str] = OMIT,
|
|
70
71
|
tags: typing.Optional[typing.Sequence[str]] = OMIT,
|
|
71
72
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
|
|
@@ -87,6 +88,8 @@ class FunctionsClient:
|
|
|
87
88
|
|
|
88
89
|
name : str
|
|
89
90
|
|
|
91
|
+
language : str
|
|
92
|
+
|
|
90
93
|
description : typing.Optional[str]
|
|
91
94
|
|
|
92
95
|
tags : typing.Optional[typing.Sequence[str]]
|
|
@@ -114,6 +117,7 @@ class FunctionsClient:
|
|
|
114
117
|
signature="signature",
|
|
115
118
|
signature_hash="signatureHash",
|
|
116
119
|
name="name",
|
|
120
|
+
language="language",
|
|
117
121
|
)
|
|
118
122
|
"""
|
|
119
123
|
_response = self._raw_client.create(
|
|
@@ -122,6 +126,7 @@ class FunctionsClient:
|
|
|
122
126
|
signature=signature,
|
|
123
127
|
signature_hash=signature_hash,
|
|
124
128
|
name=name,
|
|
129
|
+
language=language,
|
|
125
130
|
description=description,
|
|
126
131
|
tags=tags,
|
|
127
132
|
metadata=metadata,
|
|
@@ -359,6 +364,7 @@ class AsyncFunctionsClient:
|
|
|
359
364
|
signature: str,
|
|
360
365
|
signature_hash: str,
|
|
361
366
|
name: str,
|
|
367
|
+
language: str,
|
|
362
368
|
description: typing.Optional[str] = OMIT,
|
|
363
369
|
tags: typing.Optional[typing.Sequence[str]] = OMIT,
|
|
364
370
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
|
|
@@ -380,6 +386,8 @@ class AsyncFunctionsClient:
|
|
|
380
386
|
|
|
381
387
|
name : str
|
|
382
388
|
|
|
389
|
+
language : str
|
|
390
|
+
|
|
383
391
|
description : typing.Optional[str]
|
|
384
392
|
|
|
385
393
|
tags : typing.Optional[typing.Sequence[str]]
|
|
@@ -412,6 +420,7 @@ class AsyncFunctionsClient:
|
|
|
412
420
|
signature="signature",
|
|
413
421
|
signature_hash="signatureHash",
|
|
414
422
|
name="name",
|
|
423
|
+
language="language",
|
|
415
424
|
)
|
|
416
425
|
|
|
417
426
|
|
|
@@ -423,6 +432,7 @@ class AsyncFunctionsClient:
|
|
|
423
432
|
signature=signature,
|
|
424
433
|
signature_hash=signature_hash,
|
|
425
434
|
name=name,
|
|
435
|
+
language=language,
|
|
426
436
|
description=description,
|
|
427
437
|
tags=tags,
|
|
428
438
|
metadata=metadata,
|
|
@@ -167,6 +167,7 @@ class RawFunctionsClient:
|
|
|
167
167
|
signature: str,
|
|
168
168
|
signature_hash: str,
|
|
169
169
|
name: str,
|
|
170
|
+
language: str,
|
|
170
171
|
description: typing.Optional[str] = OMIT,
|
|
171
172
|
tags: typing.Optional[typing.Sequence[str]] = OMIT,
|
|
172
173
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
|
|
@@ -188,6 +189,8 @@ class RawFunctionsClient:
|
|
|
188
189
|
|
|
189
190
|
name : str
|
|
190
191
|
|
|
192
|
+
language : str
|
|
193
|
+
|
|
191
194
|
description : typing.Optional[str]
|
|
192
195
|
|
|
193
196
|
tags : typing.Optional[typing.Sequence[str]]
|
|
@@ -213,6 +216,7 @@ class RawFunctionsClient:
|
|
|
213
216
|
"signature": signature,
|
|
214
217
|
"signatureHash": signature_hash,
|
|
215
218
|
"name": name,
|
|
219
|
+
"language": language,
|
|
216
220
|
"description": description,
|
|
217
221
|
"tags": tags,
|
|
218
222
|
"metadata": metadata,
|
|
@@ -1094,6 +1098,7 @@ class AsyncRawFunctionsClient:
|
|
|
1094
1098
|
signature: str,
|
|
1095
1099
|
signature_hash: str,
|
|
1096
1100
|
name: str,
|
|
1101
|
+
language: str,
|
|
1097
1102
|
description: typing.Optional[str] = OMIT,
|
|
1098
1103
|
tags: typing.Optional[typing.Sequence[str]] = OMIT,
|
|
1099
1104
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT,
|
|
@@ -1115,6 +1120,8 @@ class AsyncRawFunctionsClient:
|
|
|
1115
1120
|
|
|
1116
1121
|
name : str
|
|
1117
1122
|
|
|
1123
|
+
language : str
|
|
1124
|
+
|
|
1118
1125
|
description : typing.Optional[str]
|
|
1119
1126
|
|
|
1120
1127
|
tags : typing.Optional[typing.Sequence[str]]
|
|
@@ -1140,6 +1147,7 @@ class AsyncRawFunctionsClient:
|
|
|
1140
1147
|
"signature": signature,
|
|
1141
1148
|
"signatureHash": signature_hash,
|
|
1142
1149
|
"name": name,
|
|
1150
|
+
"language": language,
|
|
1143
1151
|
"description": description,
|
|
1144
1152
|
"tags": tags,
|
|
1145
1153
|
"metadata": metadata,
|
|
@@ -6,13 +6,17 @@ import pydantic
|
|
|
6
6
|
import typing_extensions
|
|
7
7
|
from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
|
|
8
8
|
from ...core.serialization import FieldMetadata
|
|
9
|
-
from .functions_create_response_dependencies_value import
|
|
9
|
+
from .functions_create_response_dependencies_value import (
|
|
10
|
+
FunctionsCreateResponseDependenciesValue,
|
|
11
|
+
)
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class FunctionsCreateResponse(UniversalBaseModel):
|
|
13
15
|
id: str
|
|
14
16
|
hash: str
|
|
15
|
-
signature_hash: typing_extensions.Annotated[
|
|
17
|
+
signature_hash: typing_extensions.Annotated[
|
|
18
|
+
str, FieldMetadata(alias="signatureHash")
|
|
19
|
+
]
|
|
16
20
|
name: str
|
|
17
21
|
description: typing.Optional[str] = None
|
|
18
22
|
version: str
|
|
@@ -20,15 +24,28 @@ class FunctionsCreateResponse(UniversalBaseModel):
|
|
|
20
24
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
|
|
21
25
|
code: str
|
|
22
26
|
signature: str
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
language: str
|
|
28
|
+
dependencies: typing.Optional[
|
|
29
|
+
typing.Dict[str, typing.Optional[FunctionsCreateResponseDependenciesValue]]
|
|
30
|
+
] = None
|
|
31
|
+
environment_id: typing_extensions.Annotated[
|
|
32
|
+
str, FieldMetadata(alias="environmentId")
|
|
33
|
+
]
|
|
25
34
|
project_id: typing_extensions.Annotated[str, FieldMetadata(alias="projectId")]
|
|
26
|
-
organization_id: typing_extensions.Annotated[
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
organization_id: typing_extensions.Annotated[
|
|
36
|
+
str, FieldMetadata(alias="organizationId")
|
|
37
|
+
]
|
|
38
|
+
created_at: typing_extensions.Annotated[
|
|
39
|
+
typing.Optional[str], FieldMetadata(alias="createdAt")
|
|
40
|
+
] = None
|
|
41
|
+
updated_at: typing_extensions.Annotated[
|
|
42
|
+
typing.Optional[str], FieldMetadata(alias="updatedAt")
|
|
43
|
+
] = None
|
|
29
44
|
|
|
30
45
|
if IS_PYDANTIC_V2:
|
|
31
|
-
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
46
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
47
|
+
extra="allow", frozen=True
|
|
48
|
+
) # type: ignore # Pydantic v2
|
|
32
49
|
else:
|
|
33
50
|
|
|
34
51
|
class Config:
|
|
@@ -6,13 +6,17 @@ import pydantic
|
|
|
6
6
|
import typing_extensions
|
|
7
7
|
from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
|
|
8
8
|
from ...core.serialization import FieldMetadata
|
|
9
|
-
from .functions_find_by_hash_response_dependencies_value import
|
|
9
|
+
from .functions_find_by_hash_response_dependencies_value import (
|
|
10
|
+
FunctionsFindByHashResponseDependenciesValue,
|
|
11
|
+
)
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class FunctionsFindByHashResponse(UniversalBaseModel):
|
|
13
15
|
id: str
|
|
14
16
|
hash: str
|
|
15
|
-
signature_hash: typing_extensions.Annotated[
|
|
17
|
+
signature_hash: typing_extensions.Annotated[
|
|
18
|
+
str, FieldMetadata(alias="signatureHash")
|
|
19
|
+
]
|
|
16
20
|
name: str
|
|
17
21
|
description: typing.Optional[str] = None
|
|
18
22
|
version: str
|
|
@@ -20,17 +24,28 @@ class FunctionsFindByHashResponse(UniversalBaseModel):
|
|
|
20
24
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
|
|
21
25
|
code: str
|
|
22
26
|
signature: str
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
language: str
|
|
28
|
+
dependencies: typing.Optional[
|
|
29
|
+
typing.Dict[str, typing.Optional[FunctionsFindByHashResponseDependenciesValue]]
|
|
30
|
+
] = None
|
|
31
|
+
environment_id: typing_extensions.Annotated[
|
|
32
|
+
str, FieldMetadata(alias="environmentId")
|
|
33
|
+
]
|
|
27
34
|
project_id: typing_extensions.Annotated[str, FieldMetadata(alias="projectId")]
|
|
28
|
-
organization_id: typing_extensions.Annotated[
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
organization_id: typing_extensions.Annotated[
|
|
36
|
+
str, FieldMetadata(alias="organizationId")
|
|
37
|
+
]
|
|
38
|
+
created_at: typing_extensions.Annotated[
|
|
39
|
+
typing.Optional[str], FieldMetadata(alias="createdAt")
|
|
40
|
+
] = None
|
|
41
|
+
updated_at: typing_extensions.Annotated[
|
|
42
|
+
typing.Optional[str], FieldMetadata(alias="updatedAt")
|
|
43
|
+
] = None
|
|
31
44
|
|
|
32
45
|
if IS_PYDANTIC_V2:
|
|
33
|
-
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
46
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
47
|
+
extra="allow", frozen=True
|
|
48
|
+
) # type: ignore # Pydantic v2
|
|
34
49
|
else:
|
|
35
50
|
|
|
36
51
|
class Config:
|
|
@@ -24,6 +24,7 @@ class FunctionsGetByEnvResponse(UniversalBaseModel):
|
|
|
24
24
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
|
|
25
25
|
code: str
|
|
26
26
|
signature: str
|
|
27
|
+
language: str
|
|
27
28
|
dependencies: typing.Optional[
|
|
28
29
|
typing.Dict[str, typing.Optional[FunctionsGetByEnvResponseDependenciesValue]]
|
|
29
30
|
] = None
|
|
@@ -6,13 +6,17 @@ import pydantic
|
|
|
6
6
|
import typing_extensions
|
|
7
7
|
from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
|
|
8
8
|
from ...core.serialization import FieldMetadata
|
|
9
|
-
from .functions_get_response_dependencies_value import
|
|
9
|
+
from .functions_get_response_dependencies_value import (
|
|
10
|
+
FunctionsGetResponseDependenciesValue,
|
|
11
|
+
)
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class FunctionsGetResponse(UniversalBaseModel):
|
|
13
15
|
id: str
|
|
14
16
|
hash: str
|
|
15
|
-
signature_hash: typing_extensions.Annotated[
|
|
17
|
+
signature_hash: typing_extensions.Annotated[
|
|
18
|
+
str, FieldMetadata(alias="signatureHash")
|
|
19
|
+
]
|
|
16
20
|
name: str
|
|
17
21
|
description: typing.Optional[str] = None
|
|
18
22
|
version: str
|
|
@@ -20,15 +24,28 @@ class FunctionsGetResponse(UniversalBaseModel):
|
|
|
20
24
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
|
|
21
25
|
code: str
|
|
22
26
|
signature: str
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
language: str
|
|
28
|
+
dependencies: typing.Optional[
|
|
29
|
+
typing.Dict[str, typing.Optional[FunctionsGetResponseDependenciesValue]]
|
|
30
|
+
] = None
|
|
31
|
+
environment_id: typing_extensions.Annotated[
|
|
32
|
+
str, FieldMetadata(alias="environmentId")
|
|
33
|
+
]
|
|
25
34
|
project_id: typing_extensions.Annotated[str, FieldMetadata(alias="projectId")]
|
|
26
|
-
organization_id: typing_extensions.Annotated[
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
organization_id: typing_extensions.Annotated[
|
|
36
|
+
str, FieldMetadata(alias="organizationId")
|
|
37
|
+
]
|
|
38
|
+
created_at: typing_extensions.Annotated[
|
|
39
|
+
typing.Optional[str], FieldMetadata(alias="createdAt")
|
|
40
|
+
] = None
|
|
41
|
+
updated_at: typing_extensions.Annotated[
|
|
42
|
+
typing.Optional[str], FieldMetadata(alias="updatedAt")
|
|
43
|
+
] = None
|
|
29
44
|
|
|
30
45
|
if IS_PYDANTIC_V2:
|
|
31
|
-
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
46
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
47
|
+
extra="allow", frozen=True
|
|
48
|
+
) # type: ignore # Pydantic v2
|
|
32
49
|
else:
|
|
33
50
|
|
|
34
51
|
class Config:
|
|
@@ -14,7 +14,9 @@ from .functions_list_response_functions_item_dependencies_value import (
|
|
|
14
14
|
class FunctionsListResponseFunctionsItem(UniversalBaseModel):
|
|
15
15
|
id: str
|
|
16
16
|
hash: str
|
|
17
|
-
signature_hash: typing_extensions.Annotated[
|
|
17
|
+
signature_hash: typing_extensions.Annotated[
|
|
18
|
+
str, FieldMetadata(alias="signatureHash")
|
|
19
|
+
]
|
|
18
20
|
name: str
|
|
19
21
|
description: typing.Optional[str] = None
|
|
20
22
|
version: str
|
|
@@ -22,17 +24,30 @@ class FunctionsListResponseFunctionsItem(UniversalBaseModel):
|
|
|
22
24
|
metadata: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
|
|
23
25
|
code: str
|
|
24
26
|
signature: str
|
|
27
|
+
language: str
|
|
25
28
|
dependencies: typing.Optional[
|
|
26
|
-
typing.Dict[
|
|
29
|
+
typing.Dict[
|
|
30
|
+
str, typing.Optional[FunctionsListResponseFunctionsItemDependenciesValue]
|
|
31
|
+
]
|
|
27
32
|
] = None
|
|
28
|
-
environment_id: typing_extensions.Annotated[
|
|
33
|
+
environment_id: typing_extensions.Annotated[
|
|
34
|
+
str, FieldMetadata(alias="environmentId")
|
|
35
|
+
]
|
|
29
36
|
project_id: typing_extensions.Annotated[str, FieldMetadata(alias="projectId")]
|
|
30
|
-
organization_id: typing_extensions.Annotated[
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
organization_id: typing_extensions.Annotated[
|
|
38
|
+
str, FieldMetadata(alias="organizationId")
|
|
39
|
+
]
|
|
40
|
+
created_at: typing_extensions.Annotated[
|
|
41
|
+
typing.Optional[str], FieldMetadata(alias="createdAt")
|
|
42
|
+
] = None
|
|
43
|
+
updated_at: typing_extensions.Annotated[
|
|
44
|
+
typing.Optional[str], FieldMetadata(alias="updatedAt")
|
|
45
|
+
] = None
|
|
33
46
|
|
|
34
47
|
if IS_PYDANTIC_V2:
|
|
35
|
-
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
48
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
|
|
49
|
+
extra="allow", frozen=True
|
|
50
|
+
) # type: ignore # Pydantic v2
|
|
36
51
|
else:
|
|
37
52
|
|
|
38
53
|
class Config:
|
|
@@ -3749,6 +3749,7 @@ client.functions.create(
|
|
|
3749
3749
|
signature="signature",
|
|
3750
3750
|
signature_hash="signatureHash",
|
|
3751
3751
|
name="name",
|
|
3752
|
+
language="language",
|
|
3752
3753
|
)
|
|
3753
3754
|
|
|
3754
3755
|
```
|
|
@@ -3805,6 +3806,14 @@ client.functions.create(
|
|
|
3805
3806
|
<dl>
|
|
3806
3807
|
<dd>
|
|
3807
3808
|
|
|
3809
|
+
**language:** `str`
|
|
3810
|
+
|
|
3811
|
+
</dd>
|
|
3812
|
+
</dl>
|
|
3813
|
+
|
|
3814
|
+
<dl>
|
|
3815
|
+
<dd>
|
|
3816
|
+
|
|
3808
3817
|
**description:** `typing.Optional[str]`
|
|
3809
3818
|
|
|
3810
3819
|
</dd>
|
mirascope/llm/__init__.py
CHANGED
|
@@ -20,6 +20,7 @@ from . import (
|
|
|
20
20
|
prompts,
|
|
21
21
|
providers,
|
|
22
22
|
responses,
|
|
23
|
+
retries,
|
|
23
24
|
tools,
|
|
24
25
|
types,
|
|
25
26
|
)
|
|
@@ -67,7 +68,9 @@ from .exceptions import (
|
|
|
67
68
|
ProviderError,
|
|
68
69
|
RateLimitError,
|
|
69
70
|
ResponseValidationError,
|
|
71
|
+
RetriesExhausted,
|
|
70
72
|
ServerError,
|
|
73
|
+
StreamRestarted,
|
|
71
74
|
TimeoutError,
|
|
72
75
|
ToolError,
|
|
73
76
|
ToolExecutionError,
|
|
@@ -144,6 +147,25 @@ from .responses import (
|
|
|
144
147
|
Usage,
|
|
145
148
|
UsageDeltaChunk,
|
|
146
149
|
)
|
|
150
|
+
from .retries import (
|
|
151
|
+
AsyncContextRetryResponse,
|
|
152
|
+
AsyncContextRetryStreamResponse,
|
|
153
|
+
AsyncRetryCall,
|
|
154
|
+
AsyncRetryPrompt,
|
|
155
|
+
AsyncRetryResponse,
|
|
156
|
+
AsyncRetryStreamResponse,
|
|
157
|
+
ContextRetryResponse,
|
|
158
|
+
ContextRetryStreamResponse,
|
|
159
|
+
RetryCall,
|
|
160
|
+
RetryConfig,
|
|
161
|
+
RetryModel,
|
|
162
|
+
RetryModelParams,
|
|
163
|
+
RetryPrompt,
|
|
164
|
+
RetryResponse,
|
|
165
|
+
RetryStreamResponse,
|
|
166
|
+
retry,
|
|
167
|
+
retry_model,
|
|
168
|
+
)
|
|
147
169
|
from .tools import (
|
|
148
170
|
AnyToolFn,
|
|
149
171
|
AnyTools,
|
|
@@ -184,12 +206,18 @@ __all__ = [
|
|
|
184
206
|
"AsyncContextCall",
|
|
185
207
|
"AsyncContextPrompt",
|
|
186
208
|
"AsyncContextResponse",
|
|
209
|
+
"AsyncContextRetryResponse",
|
|
210
|
+
"AsyncContextRetryStreamResponse",
|
|
187
211
|
"AsyncContextStreamResponse",
|
|
188
212
|
"AsyncContextTool",
|
|
189
213
|
"AsyncContextToolkit",
|
|
190
214
|
"AsyncContextTools",
|
|
191
215
|
"AsyncPrompt",
|
|
192
216
|
"AsyncResponse",
|
|
217
|
+
"AsyncRetryCall",
|
|
218
|
+
"AsyncRetryPrompt",
|
|
219
|
+
"AsyncRetryResponse",
|
|
220
|
+
"AsyncRetryStreamResponse",
|
|
193
221
|
"AsyncStream",
|
|
194
222
|
"AsyncStreamResponse",
|
|
195
223
|
"AsyncTextStream",
|
|
@@ -212,6 +240,8 @@ __all__ = [
|
|
|
212
240
|
"ContextCall",
|
|
213
241
|
"ContextPrompt",
|
|
214
242
|
"ContextResponse",
|
|
243
|
+
"ContextRetryResponse",
|
|
244
|
+
"ContextRetryStreamResponse",
|
|
215
245
|
"ContextStreamResponse",
|
|
216
246
|
"ContextTool",
|
|
217
247
|
"ContextToolkit",
|
|
@@ -249,11 +279,20 @@ __all__ = [
|
|
|
249
279
|
"RawMessageChunk",
|
|
250
280
|
"Response",
|
|
251
281
|
"ResponseValidationError",
|
|
282
|
+
"RetriesExhausted",
|
|
283
|
+
"RetryCall",
|
|
284
|
+
"RetryConfig",
|
|
285
|
+
"RetryModel",
|
|
286
|
+
"RetryModelParams",
|
|
287
|
+
"RetryPrompt",
|
|
288
|
+
"RetryResponse",
|
|
289
|
+
"RetryStreamResponse",
|
|
252
290
|
"RootResponse",
|
|
253
291
|
"ServerError",
|
|
254
292
|
"Stream",
|
|
255
293
|
"StreamResponse",
|
|
256
294
|
"StreamResponseChunk",
|
|
295
|
+
"StreamRestarted",
|
|
257
296
|
"SystemContent",
|
|
258
297
|
"SystemMessage",
|
|
259
298
|
"Text",
|
|
@@ -309,6 +348,9 @@ __all__ = [
|
|
|
309
348
|
"register_provider",
|
|
310
349
|
"reset_provider_registry",
|
|
311
350
|
"responses",
|
|
351
|
+
"retries",
|
|
352
|
+
"retry",
|
|
353
|
+
"retry_model",
|
|
312
354
|
"tool",
|
|
313
355
|
"tools",
|
|
314
356
|
"types",
|
mirascope/llm/calls/calls.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""The Call module for generating responses using LLMs."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
-
from dataclasses import dataclass, field
|
|
5
4
|
from typing import Any, Generic, TypeVar, overload
|
|
6
5
|
|
|
7
6
|
from ..._utils import copy_function_metadata
|
|
@@ -31,7 +30,6 @@ PromptT = TypeVar("PromptT", bound=BasePrompt[Callable[..., Any]])
|
|
|
31
30
|
CallT = TypeVar("CallT", bound="BaseCall[Any]")
|
|
32
31
|
|
|
33
32
|
|
|
34
|
-
@dataclass(kw_only=True)
|
|
35
33
|
class BaseCall(Generic[PromptT]):
|
|
36
34
|
"""Base class for all Call types with shared model functionality."""
|
|
37
35
|
|
|
@@ -41,20 +39,20 @@ class BaseCall(Generic[PromptT]):
|
|
|
41
39
|
prompt: PromptT
|
|
42
40
|
"""The underlying Prompt instance that generates messages with tools and format."""
|
|
43
41
|
|
|
44
|
-
__name__: str =
|
|
42
|
+
__name__: str = ""
|
|
45
43
|
"""The name of the underlying function (preserved for decorator stacking)."""
|
|
46
44
|
|
|
45
|
+
def __init__(self, *, default_model: Model, prompt: PromptT) -> None:
|
|
46
|
+
self.default_model = default_model
|
|
47
|
+
self.prompt = prompt
|
|
48
|
+
copy_function_metadata(self, self.prompt.fn)
|
|
49
|
+
|
|
47
50
|
@property
|
|
48
51
|
def model(self) -> Model:
|
|
49
52
|
"""The model used for generating responses. May be overwritten via `with llm.model(...)`."""
|
|
50
53
|
return use_model(self.default_model)
|
|
51
54
|
|
|
52
|
-
def __post_init__(self) -> None:
|
|
53
|
-
"""Preserve standard function attributes for decorator stacking."""
|
|
54
|
-
copy_function_metadata(self, self.prompt.fn)
|
|
55
|
-
|
|
56
55
|
|
|
57
|
-
@dataclass
|
|
58
56
|
class Call(BaseCall[Prompt[P, FormattableT]], Generic[P, FormattableT]):
|
|
59
57
|
"""A call that directly generates LLM responses without requiring a model argument.
|
|
60
58
|
|
|
@@ -67,6 +65,14 @@ class Call(BaseCall[Prompt[P, FormattableT]], Generic[P, FormattableT]):
|
|
|
67
65
|
The model can be overridden at runtime using `with llm.model(...)` context manager.
|
|
68
66
|
"""
|
|
69
67
|
|
|
68
|
+
def __init__(
|
|
69
|
+
self,
|
|
70
|
+
*,
|
|
71
|
+
default_model: Model,
|
|
72
|
+
prompt: Prompt[P, FormattableT],
|
|
73
|
+
) -> None:
|
|
74
|
+
super().__init__(default_model=default_model, prompt=prompt)
|
|
75
|
+
|
|
70
76
|
@overload
|
|
71
77
|
def __call__(
|
|
72
78
|
self: "Call[P, None]", *args: P.args, **kwargs: P.kwargs
|
|
@@ -114,7 +120,6 @@ class Call(BaseCall[Prompt[P, FormattableT]], Generic[P, FormattableT]):
|
|
|
114
120
|
return self.prompt.stream(self.model, *args, **kwargs)
|
|
115
121
|
|
|
116
122
|
|
|
117
|
-
@dataclass
|
|
118
123
|
class AsyncCall(BaseCall[AsyncPrompt[P, FormattableT]], Generic[P, FormattableT]):
|
|
119
124
|
"""An async call that directly generates LLM responses without requiring a model argument.
|
|
120
125
|
|
|
@@ -127,6 +132,14 @@ class AsyncCall(BaseCall[AsyncPrompt[P, FormattableT]], Generic[P, FormattableT]
|
|
|
127
132
|
The model can be overridden at runtime using `with llm.model(...)` context manager.
|
|
128
133
|
"""
|
|
129
134
|
|
|
135
|
+
def __init__(
|
|
136
|
+
self,
|
|
137
|
+
*,
|
|
138
|
+
default_model: Model,
|
|
139
|
+
prompt: AsyncPrompt[P, FormattableT],
|
|
140
|
+
) -> None:
|
|
141
|
+
super().__init__(default_model=default_model, prompt=prompt)
|
|
142
|
+
|
|
130
143
|
@overload
|
|
131
144
|
async def __call__(
|
|
132
145
|
self: "AsyncCall[P, None]", *args: P.args, **kwargs: P.kwargs
|
|
@@ -176,7 +189,6 @@ class AsyncCall(BaseCall[AsyncPrompt[P, FormattableT]], Generic[P, FormattableT]
|
|
|
176
189
|
return await self.prompt.stream(self.model, *args, **kwargs)
|
|
177
190
|
|
|
178
191
|
|
|
179
|
-
@dataclass
|
|
180
192
|
class ContextCall(
|
|
181
193
|
BaseCall[ContextPrompt[P, DepsT, FormattableT]], Generic[P, DepsT, FormattableT]
|
|
182
194
|
):
|
|
@@ -192,6 +204,14 @@ class ContextCall(
|
|
|
192
204
|
The model can be overridden at runtime using `with llm.model(...)` context manager.
|
|
193
205
|
"""
|
|
194
206
|
|
|
207
|
+
def __init__(
|
|
208
|
+
self,
|
|
209
|
+
*,
|
|
210
|
+
default_model: Model,
|
|
211
|
+
prompt: ContextPrompt[P, DepsT, FormattableT],
|
|
212
|
+
) -> None:
|
|
213
|
+
super().__init__(default_model=default_model, prompt=prompt)
|
|
214
|
+
|
|
195
215
|
@overload
|
|
196
216
|
def __call__(
|
|
197
217
|
self: "ContextCall[P, DepsT, None]",
|
|
@@ -261,7 +281,6 @@ class ContextCall(
|
|
|
261
281
|
return self.prompt.stream(self.model, ctx, *args, **kwargs)
|
|
262
282
|
|
|
263
283
|
|
|
264
|
-
@dataclass
|
|
265
284
|
class AsyncContextCall(
|
|
266
285
|
BaseCall[AsyncContextPrompt[P, DepsT, FormattableT]],
|
|
267
286
|
Generic[P, DepsT, FormattableT],
|
|
@@ -278,6 +297,14 @@ class AsyncContextCall(
|
|
|
278
297
|
The model can be overridden at runtime using `with llm.model(...)` context manager.
|
|
279
298
|
"""
|
|
280
299
|
|
|
300
|
+
def __init__(
|
|
301
|
+
self,
|
|
302
|
+
*,
|
|
303
|
+
default_model: Model,
|
|
304
|
+
prompt: AsyncContextPrompt[P, DepsT, FormattableT],
|
|
305
|
+
) -> None:
|
|
306
|
+
super().__init__(default_model=default_model, prompt=prompt)
|
|
307
|
+
|
|
281
308
|
@overload
|
|
282
309
|
async def __call__(
|
|
283
310
|
self: "AsyncContextCall[P, DepsT, None]",
|
mirascope/llm/exceptions.py
CHANGED
|
@@ -7,6 +7,7 @@ from pydantic import ValidationError
|
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from .providers import ModelId, ProviderId
|
|
10
|
+
from .retries.utils import RetryFailure
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class Error(Exception):
|
|
@@ -358,3 +359,71 @@ class MissingAPIKeyError(Error):
|
|
|
358
359
|
super().__init__(message)
|
|
359
360
|
self.provider_id = provider_id
|
|
360
361
|
self.env_var = env_var
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
class RetriesExhausted(Error):
|
|
365
|
+
"""Raised when all retry attempts (including fallback models) have been exhausted.
|
|
366
|
+
|
|
367
|
+
This exception preserves the full failure history, allowing users to inspect
|
|
368
|
+
what went wrong at each attempt.
|
|
369
|
+
|
|
370
|
+
Example:
|
|
371
|
+
```python
|
|
372
|
+
try:
|
|
373
|
+
response = retry_model.generate("Tell me a story")
|
|
374
|
+
except llm.RetriesExhausted as e:
|
|
375
|
+
print(f"Failed after {len(e.failures)} attempts:")
|
|
376
|
+
for failure in e.failures:
|
|
377
|
+
print(f" - {failure.model.model}: {failure.exception}")
|
|
378
|
+
```
|
|
379
|
+
"""
|
|
380
|
+
|
|
381
|
+
failures: list["RetryFailure"]
|
|
382
|
+
"""All failed attempts, in order. The last failure triggered exhaustion."""
|
|
383
|
+
|
|
384
|
+
def __init__(self, failures: list["RetryFailure"]) -> None:
|
|
385
|
+
model_names = [f.model.model_id for f in failures]
|
|
386
|
+
message = (
|
|
387
|
+
f"All retries exhausted after {len(failures)} attempt(s) "
|
|
388
|
+
f"across models: {model_names}"
|
|
389
|
+
)
|
|
390
|
+
super().__init__(message)
|
|
391
|
+
self.failures = failures
|
|
392
|
+
# Chain to the last error for standard traceback behavior
|
|
393
|
+
if failures:
|
|
394
|
+
self.__cause__ = failures[-1].exception
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
class StreamRestarted(Error):
|
|
398
|
+
"""Raised when a stream restarts due to a retryable error.
|
|
399
|
+
|
|
400
|
+
This exception signals that the stream encountered an error and has been
|
|
401
|
+
reset for a retry attempt. Users should catch this exception and re-iterate
|
|
402
|
+
the response to continue streaming from the new attempt.
|
|
403
|
+
|
|
404
|
+
Example:
|
|
405
|
+
```python
|
|
406
|
+
response = retry_call.stream("fantasy")
|
|
407
|
+
|
|
408
|
+
while True:
|
|
409
|
+
try:
|
|
410
|
+
for chunk in response.text_stream():
|
|
411
|
+
print(chunk, end="", flush=True)
|
|
412
|
+
break # Success
|
|
413
|
+
except llm.StreamRestarted as e:
|
|
414
|
+
print(e.message)
|
|
415
|
+
# Loop continues, re-iterates the response
|
|
416
|
+
```
|
|
417
|
+
"""
|
|
418
|
+
|
|
419
|
+
failure: "RetryFailure"
|
|
420
|
+
"""The failure that triggered the restart."""
|
|
421
|
+
|
|
422
|
+
def __init__(
|
|
423
|
+
self,
|
|
424
|
+
failure: "RetryFailure",
|
|
425
|
+
) -> None:
|
|
426
|
+
message = f"Stream restarted due to: {failure.exception}"
|
|
427
|
+
super().__init__(message)
|
|
428
|
+
self.failure = failure
|
|
429
|
+
self.__cause__ = failure.exception
|