Skip to content

Commit dedcded

Browse files
authored
Merge pull request #897 from Mirascope/v1.21
Release v1.21
2 parents 34d63e5 + 02c8e36 commit dedcded

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4790
-582
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
.python-version
33
.python-versions
44

5+
# Claude
6+
CLAUDE.md
7+
58
# Byte-compiled / optimized / DLL files
69
__pycache__/
710
*.py[cod]

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ repos:
1515
- id: ruff-format
1616
files: "^mirascope|^tests|^examples|^docs"
1717
- repo: https://github.com/RobertCraigie/pyright-python
18-
rev: v1.1.394
18+
rev: v1.1.396
1919
hooks:
2020
- id: pyright
2121
- repo: local

docs/learn/prompts.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ Legend: ✓ (Supported), - (Not Supported)
228228

229229
??? info "Additional String Template Document Functionality"
230230

231-
When using string templates, you can also specify `:documents` to inject multiple audio inputs through a single template variable.
231+
When using string templates, you can also specify `:documents` to inject multiple document inputs through a single template variable.
232232

233233
The `:document` and `:documents` tags support the `bytes | str` and `list[bytes] | list[str]` types, respectively. When passing in a `str`, the string template assumes it indicates a url or local filepath and will attempt to load the bytes from the source.
234234

docs/learn/response_models.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -122,20 +122,20 @@ Note that we have no way of attaching `BaseCallResponse` to built-in types, so u
122122

123123
While Mirascope provides a consistent interface, type support varies among providers:
124124

125-
| Type | Anthropic | Cohere | Gemini | Groq | Mistral | OpenAI |
126-
|---------------|-----------|--------|--------|------|---------|--------|
127-
| str |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
128-
| int |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
129-
| float |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
130-
| bool |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
131-
| bytes |✓✓|✓✓|-✓|✓✓|✓✓|✓✓|
132-
| list |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
133-
| set |✓✓|✓✓|--|✓✓|✓✓|✓✓|
134-
| tuple |✓✓|✓✓|-✓|✓✓|✓✓|-|
135-
| dict |✓✓|✓✓|✓✓|✓✓|✓✓|-|
136-
| Literal/Enum |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
137-
| BaseModel |✓✓|-✓|✓✓|✓✓|✓✓|✓✓|
138-
| Nested ($def) |✓✓|--|--|✓✓|✓✓|✓✓|
125+
| Type | OpenAI | Anthropic | Google | Groq | xAI | Mistral | Cohere |
126+
|---------------|--------|-----------|--------|------|-----|---------|--------|
127+
| str |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
128+
| int |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
129+
| float |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
130+
| bool |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
131+
| bytes |✓✓|✓✓|-✓|✓✓|✓✓|✓✓|✓✓|
132+
| list |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
133+
| set |✓✓|✓✓|--|✓✓|✓✓|✓✓|✓✓|
134+
| tuple |-✓|✓✓|-✓|✓✓|-✓|✓✓||
135+
| dict |-✓|✓✓|✓✓|✓✓|-✓|✓✓||
136+
| Literal/Enum |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|
137+
| BaseModel |✓✓|✓✓|✓✓|✓✓|✓✓||-|
138+
| Nested ($def) |✓✓|✓✓|✓✓|✓✓|✓✓|✓✓|--|
139139

140140
✓✓ : Fully Supported, -✓: Only JSON Mode Support, -- : Not supported
141141

docs/learn/retries.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ To make it easier to make such updates, Mirascope provides a `collect_errors` ha
9999
=== "{{ provider }}"
100100

101101
{% if method == "string_template" %}
102-
```python hl_lines="4 14 26 41"
102+
```python hl_lines="4 14 28 43"
103103
{% elif method == "shorthand" %}
104-
```python hl_lines="4 14 18 32"
104+
```python hl_lines="4 14 20 34"
105105
{% else %}
106-
```python hl_lines="4 14 19 36"
106+
```python hl_lines="4 14 21 38"
107107
{% endif %}
108108
--8<-- "build/snippets/learn/retries/error_reinsertion/{{ provider | provider_dir }}/{{ method }}.py"
109109
```

docs/learn/tools.md

+14-15
Original file line numberDiff line numberDiff line change
@@ -159,25 +159,24 @@ The `BaseTool` instances have a `tool_call` property for accessing the original
159159
160160
{% endfor %}
161161

162-
163162
## Supported Field Types
164163

165164
While Mirascope provides a consistent interface, type support varies among providers:
166165

167-
| Type | Anthropic | Cohere | Gemini | Groq | Mistral | OpenAI |
168-
|---------------|-----------|--------|--------|------|---------|--------|
169-
| str | | |||||
170-
| int | | |||||
171-
| float | | |||||
172-
| bool | | |||||
173-
| bytes | | | - ||||
174-
| list | | |||||
175-
| set | | | - ||||
176-
| tuple | | | - ||| - |
177-
| dict | | |||| - |
178-
| Literal/Enum | | |||||
179-
| BaseModel | | - ||| | |
180-
| Nested ($def) | | - | - || | |
166+
| Type | OpenAI | Anthropic | Google | Groq | xAI | Mistral | Cohere |
167+
|---------------|--------|-----------|--------|------|-----|---------|--------|
168+
| str || || | |||
169+
| int || || | |||
170+
| float || || | |||
171+
| bool || || | |||
172+
| bytes || | - | | |||
173+
| list || || | |||
174+
| set || | - | | |||
175+
| tuple | - | | - || - | | |
176+
| dict | - | ||| - | | |
177+
| Literal/Enum || || | |||
178+
| BaseModel || |||| | - |
179+
| Nested ($def) || | ||| | - |
181180

182181
Legend: ✓ (Supported), - (Not Supported)
183182

examples/learn/retries/error_reinsertion/base_message_param.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ def is_upper(v: str) -> str:
1212

1313

1414
@retry(stop=stop_after_attempt(3), after=collect_errors(ValidationError))
15-
@llm.call(provider="openai", model="gpt-4o-mini",
15+
@llm.call(
16+
provider="openai",
17+
model="gpt-4o-mini",
1618
response_model=Annotated[str, AfterValidator(is_upper)], # pyright: ignore [reportArgumentType, reportCallIssue]
1719
)
1820
def identify_author(

examples/learn/retries/error_reinsertion/messages.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ def is_upper(v: str) -> str:
1212

1313

1414
@retry(stop=stop_after_attempt(3), after=collect_errors(ValidationError))
15-
@llm.call(provider="openai", model="gpt-4o-mini",
15+
@llm.call(
16+
provider="openai",
17+
model="gpt-4o-mini",
1618
response_model=Annotated[str, AfterValidator(is_upper)], # pyright: ignore [reportArgumentType, reportCallIssue]
1719
)
1820
def identify_author(

examples/learn/retries/error_reinsertion/shorthand.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ def is_upper(v: str) -> str:
1212

1313

1414
@retry(stop=stop_after_attempt(3), after=collect_errors(ValidationError))
15-
@llm.call(provider="openai", model="gpt-4o-mini",
15+
@llm.call(
16+
provider="openai",
17+
model="gpt-4o-mini",
1618
response_model=Annotated[str, AfterValidator(is_upper)], # pyright: ignore [reportArgumentType, reportCallIssue]
1719
)
1820
def identify_author(book: str, *, errors: list[ValidationError] | None = None) -> str:

examples/learn/retries/error_reinsertion/string_template.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ def is_upper(v: str) -> str:
1212

1313

1414
@retry(stop=stop_after_attempt(3), after=collect_errors(ValidationError))
15-
@llm.call(provider="openai", model="gpt-4o-mini",
15+
@llm.call(
16+
provider="openai",
17+
model="gpt-4o-mini",
1618
response_model=Annotated[str, AfterValidator(is_upper)], # pyright: ignore [reportArgumentType, reportCallIssue]
1719
)
1820
@prompt_template(

mirascope/core/anthropic/call_response.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@
2020
from ._utils._convert_finish_reason_to_common_finish_reasons import (
2121
_convert_finish_reasons_to_common_finish_reasons,
2222
)
23-
from ._utils._message_param_converter import (
24-
AnthropicMessageParamConverter,
25-
)
23+
from ._utils._message_param_converter import AnthropicMessageParamConverter
2624
from .call_params import AnthropicCallParams
2725
from .dynamic_config import AnthropicDynamicConfig, AsyncAnthropicDynamicConfig
2826
from .tool import AnthropicTool
@@ -37,6 +35,7 @@ class AnthropicCallResponse(
3735
MessageParam,
3836
AnthropicCallParams,
3937
MessageParam,
38+
AnthropicMessageParamConverter,
4039
]
4140
):
4241
"""A convenience wrapper around the Anthropic `Message` response.
@@ -62,6 +61,10 @@ def recommend_book(genre: str) -> str:
6261
```
6362
"""
6463

64+
_message_converter: type[AnthropicMessageParamConverter] = (
65+
AnthropicMessageParamConverter
66+
)
67+
6568
_provider = "anthropic"
6669

6770
@computed_field

mirascope/core/azure/call_response.py

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class AzureCallResponse(
3838
ChatRequestMessage,
3939
AzureCallParams,
4040
UserMessage,
41+
AzureMessageParamConverter,
4142
]
4243
):
4344
"""A convenience wrapper around the Azure `ChatCompletion` response.
@@ -64,6 +65,7 @@ def recommend_book(genre: str) -> str:
6465
"""
6566

6667
response: SkipValidation[ChatCompletions]
68+
_message_converter: type[AzureMessageParamConverter] = AzureMessageParamConverter
6769

6870
_provider = "azure"
6971

mirascope/core/base/_create.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ async def inner_async(
187187
start_time = datetime.datetime.now().timestamp() * 1000
188188
response = await create(stream=False, **call_kwargs)
189189
end_time = datetime.datetime.now().timestamp() * 1000
190-
output = TCallResponse(
190+
output = TCallResponse( # pyright: ignore [reportCallIssue]
191191
metadata=get_metadata(fn, dynamic_config),
192192
response=response,
193193
tool_types=tool_types, # pyright: ignore [reportArgumentType]
@@ -231,7 +231,7 @@ def inner(
231231
start_time = datetime.datetime.now().timestamp() * 1000
232232
response = create(stream=False, **call_kwargs)
233233
end_time = datetime.datetime.now().timestamp() * 1000
234-
output = TCallResponse(
234+
output = TCallResponse( # pyright: ignore [reportCallIssue]
235235
metadata=get_metadata(fn, dynamic_config),
236236
response=response,
237237
tool_types=tool_types, # pyright: ignore [reportArgumentType]

mirascope/core/base/_utils/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Internal Utilities."""
22

3+
from ._base_message_param_converter import BaseMessageParamConverter
34
from ._base_type import BaseType, is_base_type
45
from ._convert_base_model_to_base_tool import convert_base_model_to_base_tool
56
from ._convert_base_type_to_base_tool import convert_base_type_to_base_tool
@@ -46,8 +47,10 @@
4647
__all__ = [
4748
"DEFAULT_TOOL_DOCSTRING",
4849
"AsyncCreateFn",
50+
"BaseMessageParamConverter",
4951
"BaseType",
5052
"CalculateCost",
53+
"CallDecorator",
5154
"CreateFn",
5255
"GetJsonOutput",
5356
"HandleStream",

mirascope/core/base/_utils/_base_message_param_converter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from abc import ABC, abstractmethod
44
from typing import Any
55

6-
from mirascope.core import BaseMessageParam
6+
from mirascope.core.base.message_param import BaseMessageParam
77

88

99
class BaseMessageParamConverter(ABC):

mirascope/core/base/call_response.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
)
2020

2121
from ..costs import calculate_cost
22-
from ._utils import BaseType, get_common_usage
22+
from ._utils import BaseMessageParamConverter, BaseType, get_common_usage
2323
from .call_kwargs import BaseCallKwargs
2424
from .call_params import BaseCallParams
2525
from .dynamic_config import BaseDynamicConfig
@@ -40,6 +40,9 @@
4040
_CallParamsT = TypeVar("_CallParamsT", bound=BaseCallParams)
4141
_UserMessageParamT = TypeVar("_UserMessageParamT", bound=Any)
4242
_BaseCallResponseT = TypeVar("_BaseCallResponseT", bound="BaseCallResponse")
43+
_BaseMessageParamConverterT = TypeVar(
44+
"_BaseMessageParamConverterT", bound=BaseMessageParamConverter
45+
)
4346

4447

4548
def transform_tool_outputs(
@@ -97,6 +100,7 @@ class BaseCallResponse(
97100
_MessageParamT,
98101
_CallParamsT,
99102
_UserMessageParamT,
103+
_BaseMessageParamConverterT,
100104
],
101105
ABC,
102106
):
@@ -131,6 +135,7 @@ class BaseCallResponse(
131135
start_time: float
132136
end_time: float
133137

138+
_message_converter: type[_BaseMessageParamConverterT]
134139
_provider: ClassVar[str] = "NO PROVIDER"
135140
_model: str = "NO MODEL"
136141

@@ -313,6 +318,11 @@ def common_user_message_param(self) -> BaseMessageParam | None:
313318
"""Provider-agnostic user message param."""
314319
...
315320

321+
@property
322+
def common_messages(self) -> list[BaseMessageParam]:
323+
"""Provider-agnostic list of messages."""
324+
return self._message_converter.from_provider(self.messages)
325+
316326
@property
317327
def common_tools(self) -> list[Tool] | None:
318328
"""Provider-agnostic tools."""

mirascope/core/bedrock/call_response.py

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class BedrockCallResponse(
5151
InternalBedrockMessageParam,
5252
BedrockCallParams,
5353
UserMessageTypeDef,
54+
BedrockMessageParamConverter,
5455
]
5556
):
5657
"""A convenience wrapper around the Bedrock `ChatCompletion` response.
@@ -78,6 +79,9 @@ def recommend_book(genre: str):
7879
"""
7980

8081
response: SkipValidation[SyncConverseResponseTypeDef | AsyncConverseResponseTypeDef]
82+
_message_converter: type[BedrockMessageParamConverter] = (
83+
BedrockMessageParamConverter
84+
)
8185

8286
_provider = "bedrock"
8387

mirascope/core/cohere/call_response.py

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class CohereCallResponse(
3535
SkipValidation[ChatMessage],
3636
CohereCallParams,
3737
SkipValidation[ChatMessage],
38+
CohereMessageParamConverter,
3839
]
3940
):
4041
"""A convenience wrapper around the Cohere `ChatCompletion` response.
@@ -60,6 +61,8 @@ def recommend_book(genre: str) -> str:
6061
```
6162
"""
6263

64+
_message_converter: type[CohereMessageParamConverter] = CohereMessageParamConverter
65+
6366
_provider = "cohere"
6467

6568
@computed_field

mirascope/core/gemini/call_response.py

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class GeminiCallResponse(
3636
ContentsType,
3737
GeminiCallParams,
3838
ContentDict,
39+
GeminiMessageParamConverter,
3940
]
4041
):
4142
"""A convenience wrapper around the Gemini API response.
@@ -62,6 +63,8 @@ def recommend_book(genre: str) -> str:
6263
```
6364
"""
6465

66+
_message_converter: type[GeminiMessageParamConverter] = GeminiMessageParamConverter
67+
6568
_provider = "gemini"
6669

6770
@computed_field

mirascope/core/google/call_response.py

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class GoogleCallResponse(
4040
ContentListUnion | ContentListUnionDict,
4141
GoogleCallParams,
4242
ContentDict,
43+
GoogleMessageParamConverter,
4344
]
4445
):
4546
"""A convenience wrapper around the Google API response.
@@ -66,6 +67,8 @@ def recommend_book(genre: str) -> str:
6667
```
6768
"""
6869

70+
_message_converter: type[GoogleMessageParamConverter] = GoogleMessageParamConverter
71+
6972
_provider = "google"
7073

7174
@computed_field

0 commit comments

Comments
 (0)