mirascope 2.0.0a6__py3-none-any.whl → 2.0.2__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/_utils.py +34 -0
- mirascope/api/_generated/__init__.py +186 -5
- mirascope/api/_generated/annotations/client.py +38 -6
- mirascope/api/_generated/annotations/raw_client.py +366 -47
- mirascope/api/_generated/annotations/types/annotations_create_response.py +19 -6
- mirascope/api/_generated/annotations/types/annotations_get_response.py +19 -6
- mirascope/api/_generated/annotations/types/annotations_list_response_annotations_item.py +22 -7
- mirascope/api/_generated/annotations/types/annotations_update_response.py +19 -6
- mirascope/api/_generated/api_keys/__init__.py +12 -2
- mirascope/api/_generated/api_keys/client.py +107 -6
- mirascope/api/_generated/api_keys/raw_client.py +486 -38
- mirascope/api/_generated/api_keys/types/__init__.py +7 -1
- mirascope/api/_generated/api_keys/types/api_keys_list_all_for_org_response_item.py +40 -0
- mirascope/api/_generated/client.py +36 -0
- mirascope/api/_generated/docs/raw_client.py +71 -9
- mirascope/api/_generated/environment.py +3 -3
- mirascope/api/_generated/environments/__init__.py +6 -0
- mirascope/api/_generated/environments/client.py +158 -9
- mirascope/api/_generated/environments/raw_client.py +620 -52
- mirascope/api/_generated/environments/types/__init__.py +10 -0
- mirascope/api/_generated/environments/types/environments_get_analytics_response.py +60 -0
- mirascope/api/_generated/environments/types/environments_get_analytics_response_top_functions_item.py +24 -0
- mirascope/api/_generated/{organizations/types/organizations_credits_response.py → environments/types/environments_get_analytics_response_top_models_item.py} +6 -3
- mirascope/api/_generated/errors/__init__.py +6 -0
- mirascope/api/_generated/errors/bad_request_error.py +5 -2
- mirascope/api/_generated/errors/conflict_error.py +5 -2
- mirascope/api/_generated/errors/payment_required_error.py +15 -0
- mirascope/api/_generated/errors/service_unavailable_error.py +14 -0
- mirascope/api/_generated/errors/too_many_requests_error.py +15 -0
- mirascope/api/_generated/functions/__init__.py +10 -0
- mirascope/api/_generated/functions/client.py +222 -8
- mirascope/api/_generated/functions/raw_client.py +975 -134
- mirascope/api/_generated/functions/types/__init__.py +28 -4
- mirascope/api/_generated/functions/types/functions_get_by_env_response.py +53 -0
- mirascope/api/_generated/functions/types/functions_get_by_env_response_dependencies_value.py +22 -0
- mirascope/api/_generated/functions/types/functions_list_by_env_response.py +25 -0
- mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item.py +56 -0
- mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item_dependencies_value.py +22 -0
- mirascope/api/_generated/health/raw_client.py +74 -10
- mirascope/api/_generated/organization_invitations/__init__.py +33 -0
- mirascope/api/_generated/organization_invitations/client.py +546 -0
- mirascope/api/_generated/organization_invitations/raw_client.py +1519 -0
- mirascope/api/_generated/organization_invitations/types/__init__.py +53 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response.py +34 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_request_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response.py +48 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_status.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response.py +48 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_status.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item.py +48 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_status.py +7 -0
- mirascope/api/_generated/organization_memberships/__init__.py +19 -0
- mirascope/api/_generated/organization_memberships/client.py +302 -0
- mirascope/api/_generated/organization_memberships/raw_client.py +736 -0
- mirascope/api/_generated/organization_memberships/types/__init__.py +27 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item.py +33 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item_role.py +7 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_update_request_role.py +7 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response.py +31 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response_role.py +7 -0
- mirascope/api/_generated/organizations/__init__.py +26 -2
- mirascope/api/_generated/organizations/client.py +442 -20
- mirascope/api/_generated/organizations/raw_client.py +1763 -164
- mirascope/api/_generated/organizations/types/__init__.py +48 -2
- mirascope/api/_generated/organizations/types/organizations_create_payment_intent_response.py +24 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_request_target_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response.py +47 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item.py +33 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item_resource.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_router_balance_response.py +24 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response.py +53 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_current_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_payment_method.py +26 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change.py +34 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change_target_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_update_subscription_request_target_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_update_subscription_response.py +35 -0
- mirascope/api/_generated/project_memberships/__init__.py +25 -0
- mirascope/api/_generated/project_memberships/client.py +437 -0
- mirascope/api/_generated/project_memberships/raw_client.py +1039 -0
- mirascope/api/_generated/project_memberships/types/__init__.py +29 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_create_request_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_create_response.py +35 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_create_response_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item.py +33 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_update_request_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_update_response.py +35 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_update_response_role.py +7 -0
- mirascope/api/_generated/projects/raw_client.py +415 -58
- mirascope/api/_generated/reference.md +2767 -397
- mirascope/api/_generated/tags/__init__.py +19 -0
- mirascope/api/_generated/tags/client.py +504 -0
- mirascope/api/_generated/tags/raw_client.py +1288 -0
- mirascope/api/_generated/tags/types/__init__.py +17 -0
- mirascope/api/_generated/tags/types/tags_create_response.py +41 -0
- mirascope/api/_generated/tags/types/tags_get_response.py +41 -0
- mirascope/api/_generated/tags/types/tags_list_response.py +23 -0
- mirascope/api/_generated/tags/types/tags_list_response_tags_item.py +41 -0
- mirascope/api/_generated/tags/types/tags_update_response.py +41 -0
- mirascope/api/_generated/token_cost/__init__.py +7 -0
- mirascope/api/_generated/token_cost/client.py +160 -0
- mirascope/api/_generated/token_cost/raw_client.py +264 -0
- mirascope/api/_generated/token_cost/types/__init__.py +8 -0
- mirascope/api/_generated/token_cost/types/token_cost_calculate_request_usage.py +54 -0
- mirascope/api/_generated/token_cost/types/token_cost_calculate_response.py +52 -0
- mirascope/api/_generated/traces/__init__.py +20 -0
- mirascope/api/_generated/traces/client.py +543 -0
- mirascope/api/_generated/traces/raw_client.py +1366 -96
- mirascope/api/_generated/traces/types/__init__.py +28 -0
- mirascope/api/_generated/traces/types/traces_get_analytics_summary_response.py +6 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response.py +33 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response_spans_item.py +88 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_response_spans_item.py +0 -2
- mirascope/api/_generated/traces/types/traces_list_by_function_hash_response.py +25 -0
- mirascope/api/_generated/traces/types/traces_list_by_function_hash_response_traces_item.py +44 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item.py +26 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item_operator.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_by.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_order.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_response.py +26 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_response_spans_item.py +50 -0
- mirascope/api/_generated/traces/types/traces_search_response_spans_item.py +10 -1
- mirascope/api/_generated/types/__init__.py +32 -2
- mirascope/api/_generated/types/bad_request_error_body.py +50 -0
- mirascope/api/_generated/types/date.py +3 -0
- mirascope/api/_generated/types/immutable_resource_error.py +22 -0
- mirascope/api/_generated/types/internal_server_error_body.py +3 -3
- mirascope/api/_generated/types/plan_limit_exceeded_error.py +32 -0
- mirascope/api/_generated/types/plan_limit_exceeded_error_tag.py +7 -0
- mirascope/api/_generated/types/pricing_unavailable_error.py +23 -0
- mirascope/api/_generated/types/rate_limit_error.py +31 -0
- mirascope/api/_generated/types/rate_limit_error_tag.py +5 -0
- mirascope/api/_generated/types/service_unavailable_error_body.py +24 -0
- mirascope/api/_generated/types/service_unavailable_error_tag.py +7 -0
- mirascope/api/_generated/types/subscription_past_due_error.py +31 -0
- mirascope/api/_generated/types/subscription_past_due_error_tag.py +7 -0
- mirascope/api/settings.py +19 -1
- mirascope/llm/__init__.py +53 -10
- mirascope/llm/calls/__init__.py +2 -1
- mirascope/llm/calls/calls.py +29 -20
- mirascope/llm/calls/decorator.py +21 -7
- mirascope/llm/content/tool_output.py +22 -5
- mirascope/llm/exceptions.py +284 -71
- mirascope/llm/formatting/__init__.py +17 -0
- mirascope/llm/formatting/format.py +112 -35
- mirascope/llm/formatting/output_parser.py +178 -0
- mirascope/llm/formatting/partial.py +80 -7
- mirascope/llm/formatting/primitives.py +192 -0
- mirascope/llm/formatting/types.py +20 -8
- mirascope/llm/messages/__init__.py +3 -0
- mirascope/llm/messages/_utils.py +34 -0
- mirascope/llm/models/__init__.py +5 -0
- mirascope/llm/models/models.py +137 -69
- mirascope/llm/{providers/base → models}/params.py +7 -57
- mirascope/llm/models/thinking_config.py +61 -0
- mirascope/llm/prompts/_utils.py +0 -32
- mirascope/llm/prompts/decorator.py +16 -5
- mirascope/llm/prompts/prompts.py +160 -92
- mirascope/llm/providers/__init__.py +1 -4
- mirascope/llm/providers/anthropic/_utils/__init__.py +2 -0
- mirascope/llm/providers/anthropic/_utils/beta_decode.py +18 -9
- mirascope/llm/providers/anthropic/_utils/beta_encode.py +62 -13
- mirascope/llm/providers/anthropic/_utils/decode.py +18 -9
- mirascope/llm/providers/anthropic/_utils/encode.py +26 -7
- mirascope/llm/providers/anthropic/_utils/errors.py +2 -2
- mirascope/llm/providers/anthropic/beta_provider.py +64 -18
- mirascope/llm/providers/anthropic/provider.py +91 -33
- mirascope/llm/providers/base/__init__.py +0 -4
- mirascope/llm/providers/base/_utils.py +55 -6
- mirascope/llm/providers/base/base_provider.py +116 -37
- mirascope/llm/providers/google/_utils/__init__.py +2 -0
- mirascope/llm/providers/google/_utils/decode.py +20 -7
- mirascope/llm/providers/google/_utils/encode.py +26 -7
- mirascope/llm/providers/google/_utils/errors.py +3 -2
- mirascope/llm/providers/google/provider.py +64 -18
- mirascope/llm/providers/mirascope/_utils.py +13 -17
- mirascope/llm/providers/mirascope/provider.py +49 -18
- mirascope/llm/providers/mlx/_utils.py +7 -2
- mirascope/llm/providers/mlx/encoding/base.py +5 -2
- mirascope/llm/providers/mlx/encoding/transformers.py +5 -2
- mirascope/llm/providers/mlx/mlx.py +23 -6
- mirascope/llm/providers/mlx/provider.py +42 -13
- mirascope/llm/providers/openai/_utils/errors.py +2 -2
- mirascope/llm/providers/openai/completions/_utils/encode.py +20 -16
- mirascope/llm/providers/openai/completions/base_provider.py +40 -11
- mirascope/llm/providers/openai/provider.py +40 -10
- mirascope/llm/providers/openai/responses/_utils/__init__.py +2 -0
- mirascope/llm/providers/openai/responses/_utils/decode.py +19 -6
- mirascope/llm/providers/openai/responses/_utils/encode.py +22 -10
- mirascope/llm/providers/openai/responses/provider.py +56 -18
- mirascope/llm/providers/provider_registry.py +93 -19
- mirascope/llm/responses/__init__.py +6 -1
- mirascope/llm/responses/_utils.py +102 -12
- mirascope/llm/responses/base_response.py +5 -2
- mirascope/llm/responses/base_stream_response.py +115 -25
- mirascope/llm/responses/response.py +2 -1
- mirascope/llm/responses/root_response.py +89 -17
- mirascope/llm/responses/stream_response.py +6 -9
- mirascope/llm/tools/decorator.py +9 -4
- mirascope/llm/tools/tool_schema.py +17 -6
- mirascope/llm/tools/toolkit.py +35 -27
- mirascope/llm/tools/tools.py +45 -20
- mirascope/ops/__init__.py +4 -0
- mirascope/ops/_internal/closure.py +4 -1
- mirascope/ops/_internal/configuration.py +82 -31
- mirascope/ops/_internal/exporters/exporters.py +55 -35
- mirascope/ops/_internal/exporters/utils.py +37 -0
- mirascope/ops/_internal/instrumentation/llm/common.py +530 -0
- mirascope/ops/_internal/instrumentation/llm/cost.py +190 -0
- mirascope/ops/_internal/instrumentation/llm/encode.py +1 -1
- mirascope/ops/_internal/instrumentation/llm/llm.py +116 -1242
- mirascope/ops/_internal/instrumentation/llm/model.py +1798 -0
- mirascope/ops/_internal/instrumentation/llm/response.py +521 -0
- mirascope/ops/_internal/instrumentation/llm/serialize.py +300 -0
- mirascope/ops/_internal/protocols.py +83 -1
- mirascope/ops/_internal/traced_calls.py +18 -0
- mirascope/ops/_internal/traced_functions.py +125 -10
- mirascope/ops/_internal/tracing.py +78 -1
- mirascope/ops/_internal/utils.py +60 -4
- mirascope/ops/_internal/versioned_functions.py +1 -1
- {mirascope-2.0.0a6.dist-info → mirascope-2.0.2.dist-info}/METADATA +12 -11
- mirascope-2.0.2.dist-info/RECORD +424 -0
- {mirascope-2.0.0a6.dist-info → mirascope-2.0.2.dist-info}/licenses/LICENSE +1 -1
- mirascope-2.0.0a6.dist-info/RECORD +0 -316
- {mirascope-2.0.0a6.dist-info → mirascope-2.0.2.dist-info}/WHEEL +0 -0
|
@@ -11,8 +11,11 @@ from ...llm.calls import AsyncCall, AsyncContextCall, Call, ContextCall
|
|
|
11
11
|
from ...llm.context import DepsT
|
|
12
12
|
from .protocols import (
|
|
13
13
|
AsyncFunction,
|
|
14
|
+
AsyncSpanFunction,
|
|
14
15
|
SyncFunction,
|
|
16
|
+
SyncSpanFunction,
|
|
15
17
|
fn_is_async,
|
|
18
|
+
fn_wants_span,
|
|
16
19
|
)
|
|
17
20
|
from .traced_calls import (
|
|
18
21
|
TracedAsyncCall,
|
|
@@ -24,7 +27,9 @@ from .traced_calls import (
|
|
|
24
27
|
)
|
|
25
28
|
from .traced_functions import (
|
|
26
29
|
AsyncTracedFunction,
|
|
30
|
+
AsyncTracedSpanFunction,
|
|
27
31
|
TracedFunction,
|
|
32
|
+
TracedSpanFunction,
|
|
28
33
|
)
|
|
29
34
|
from .types import P, R
|
|
30
35
|
|
|
@@ -43,7 +48,7 @@ class TraceDecorator:
|
|
|
43
48
|
"""Arbitrary key-value pairs for additional metadata."""
|
|
44
49
|
|
|
45
50
|
# IMPORTANT: The order of these overloads matters for type inference.
|
|
46
|
-
# Call type overloads come first, then function overloads.
|
|
51
|
+
# Call type overloads come first, then span function overloads, then regular functions.
|
|
47
52
|
@overload
|
|
48
53
|
def __call__( # pyright: ignore[reportOverlappingOverload]
|
|
49
54
|
self,
|
|
@@ -76,6 +81,22 @@ class TraceDecorator:
|
|
|
76
81
|
"""Overload for applying decorator to a Call."""
|
|
77
82
|
...
|
|
78
83
|
|
|
84
|
+
@overload
|
|
85
|
+
def __call__( # pyright: ignore[reportOverlappingOverload]
|
|
86
|
+
self,
|
|
87
|
+
fn: AsyncSpanFunction[P, R],
|
|
88
|
+
) -> AsyncTracedSpanFunction[P, R]:
|
|
89
|
+
"""Overload for applying decorator to an async function with span injection."""
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
@overload
|
|
93
|
+
def __call__(
|
|
94
|
+
self,
|
|
95
|
+
fn: SyncSpanFunction[P, R],
|
|
96
|
+
) -> TracedSpanFunction[P, R]:
|
|
97
|
+
"""Overload for applying decorator to a sync function with span injection."""
|
|
98
|
+
...
|
|
99
|
+
|
|
79
100
|
@overload
|
|
80
101
|
def __call__(
|
|
81
102
|
self,
|
|
@@ -99,6 +120,8 @@ class TraceDecorator:
|
|
|
99
120
|
| ContextCall[P, DepsT, FormattableT]
|
|
100
121
|
| AsyncCall[P, FormattableT]
|
|
101
122
|
| Call[P, FormattableT]
|
|
123
|
+
| AsyncSpanFunction[P, R]
|
|
124
|
+
| SyncSpanFunction[P, R]
|
|
102
125
|
| AsyncFunction[P, R]
|
|
103
126
|
| SyncFunction[P, R]
|
|
104
127
|
),
|
|
@@ -107,12 +130,21 @@ class TraceDecorator:
|
|
|
107
130
|
| TracedContextCall[P, DepsT, FormattableT]
|
|
108
131
|
| TracedAsyncCall[P, FormattableT]
|
|
109
132
|
| TracedCall[P, FormattableT]
|
|
133
|
+
| AsyncTracedSpanFunction[P, R]
|
|
134
|
+
| TracedSpanFunction[P, R]
|
|
110
135
|
| AsyncTracedFunction[P, R]
|
|
111
136
|
| TracedFunction[P, R]
|
|
112
137
|
):
|
|
113
138
|
"""Applies the decorator to the given function or Call object."""
|
|
114
139
|
if is_call_type(fn):
|
|
115
140
|
return wrap_call(fn=fn, tags=self.tags, metadata=self.metadata)
|
|
141
|
+
elif fn_wants_span(fn):
|
|
142
|
+
if fn_is_async(fn):
|
|
143
|
+
return AsyncTracedSpanFunction(
|
|
144
|
+
fn=fn, tags=self.tags, metadata=self.metadata
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
return TracedSpanFunction(fn=fn, tags=self.tags, metadata=self.metadata)
|
|
116
148
|
elif fn_is_async(fn):
|
|
117
149
|
return AsyncTracedFunction(fn=fn, tags=self.tags, metadata=self.metadata)
|
|
118
150
|
else:
|
|
@@ -174,6 +206,28 @@ def trace(
|
|
|
174
206
|
...
|
|
175
207
|
|
|
176
208
|
|
|
209
|
+
@overload
|
|
210
|
+
def trace( # pyright: ignore[reportOverlappingOverload]
|
|
211
|
+
__fn: AsyncSpanFunction[P, R],
|
|
212
|
+
*,
|
|
213
|
+
tags: None = None,
|
|
214
|
+
metadata: None = None,
|
|
215
|
+
) -> AsyncTracedSpanFunction[P, R]:
|
|
216
|
+
"""Overload for directly decorating an async function with span injection."""
|
|
217
|
+
...
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@overload
|
|
221
|
+
def trace(
|
|
222
|
+
__fn: SyncSpanFunction[P, R],
|
|
223
|
+
*,
|
|
224
|
+
tags: None = None,
|
|
225
|
+
metadata: None = None,
|
|
226
|
+
) -> TracedSpanFunction[P, R]:
|
|
227
|
+
"""Overload for directly decorating a sync function with span injection."""
|
|
228
|
+
...
|
|
229
|
+
|
|
230
|
+
|
|
177
231
|
@overload
|
|
178
232
|
def trace(
|
|
179
233
|
__fn: AsyncFunction[P, R],
|
|
@@ -202,6 +256,8 @@ def trace( # pyright: ignore[reportGeneralTypeIssues]
|
|
|
202
256
|
| ContextCall[P, DepsT, FormattableT]
|
|
203
257
|
| AsyncCall[P, FormattableT]
|
|
204
258
|
| Call[P, FormattableT]
|
|
259
|
+
| AsyncSpanFunction[P, R]
|
|
260
|
+
| SyncSpanFunction[P, R]
|
|
205
261
|
| AsyncFunction[P, R]
|
|
206
262
|
| SyncFunction[P, R]
|
|
207
263
|
| None
|
|
@@ -214,6 +270,8 @@ def trace( # pyright: ignore[reportGeneralTypeIssues]
|
|
|
214
270
|
| TracedContextCall[P, DepsT, FormattableT]
|
|
215
271
|
| TracedAsyncCall[P, FormattableT]
|
|
216
272
|
| TracedCall[P, FormattableT]
|
|
273
|
+
| AsyncTracedSpanFunction[P, R]
|
|
274
|
+
| TracedSpanFunction[P, R]
|
|
217
275
|
| AsyncTracedFunction[P, R]
|
|
218
276
|
| TracedFunction[P, R]
|
|
219
277
|
| TraceDecorator
|
|
@@ -227,6 +285,9 @@ def trace( # pyright: ignore[reportGeneralTypeIssues]
|
|
|
227
285
|
When decorating an @llm.call function, returns a TracedCall that wraps both
|
|
228
286
|
the call and stream methods with tracing capabilities.
|
|
229
287
|
|
|
288
|
+
If the decorated function has `trace_ctx: Span` as its first parameter,
|
|
289
|
+
the span will be injected automatically and callers should NOT pass it.
|
|
290
|
+
|
|
230
291
|
Args:
|
|
231
292
|
__fn: The function or Call object to decorate.
|
|
232
293
|
tags: Optional list of string tags to associate with traced executions.
|
|
@@ -262,6 +323,17 @@ def trace( # pyright: ignore[reportGeneralTypeIssues]
|
|
|
262
323
|
print(trace.result.content)
|
|
263
324
|
print(trace.span_id)
|
|
264
325
|
```
|
|
326
|
+
|
|
327
|
+
Example:
|
|
328
|
+
```python
|
|
329
|
+
@ops.trace
|
|
330
|
+
def my_fn(trace_ctx: Span, arg: str) -> str:
|
|
331
|
+
trace_ctx.info(f"Processing: {arg}")
|
|
332
|
+
return arg.upper()
|
|
333
|
+
|
|
334
|
+
# Call without trace_ctx - it's injected automatically
|
|
335
|
+
result = my_fn("hello") # Returns "HELLO"
|
|
336
|
+
```
|
|
265
337
|
"""
|
|
266
338
|
tags = tuple(sorted(set(tags or [])))
|
|
267
339
|
metadata = metadata or {}
|
|
@@ -270,6 +342,11 @@ def trace( # pyright: ignore[reportGeneralTypeIssues]
|
|
|
270
342
|
|
|
271
343
|
if is_call_type(__fn):
|
|
272
344
|
return wrap_call(fn=__fn, tags=tags, metadata=metadata)
|
|
345
|
+
elif fn_wants_span(__fn):
|
|
346
|
+
if fn_is_async(__fn):
|
|
347
|
+
return AsyncTracedSpanFunction(fn=__fn, tags=tags, metadata=metadata)
|
|
348
|
+
else:
|
|
349
|
+
return TracedSpanFunction(fn=__fn, tags=tags, metadata=metadata)
|
|
273
350
|
elif fn_is_async(__fn):
|
|
274
351
|
return AsyncTracedFunction(fn=__fn, tags=tags, metadata=metadata)
|
|
275
352
|
else:
|
mirascope/ops/_internal/utils.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import Any, TypeAlias
|
|
|
6
6
|
|
|
7
7
|
import orjson
|
|
8
8
|
|
|
9
|
-
from .protocols import P
|
|
9
|
+
from .protocols import P, fn_wants_span
|
|
10
10
|
|
|
11
11
|
ORJSON_OPTS = (
|
|
12
12
|
orjson.OPT_NON_STR_KEYS
|
|
@@ -25,18 +25,56 @@ def json_dumps(obj: Any) -> str: # noqa: ANN401
|
|
|
25
25
|
return orjson.dumps(obj, option=ORJSON_OPTS).decode("utf-8")
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
def _is_call_method(fn: Callable[..., Any]) -> bool:
|
|
29
|
+
"""Check if fn is a bound method of a Call object (e.g., Call.call or Call.stream)."""
|
|
30
|
+
return (
|
|
31
|
+
hasattr(fn, "__self__") and hasattr(fn.__self__, "prompt") # pyright: ignore[reportFunctionMemberAccess]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_original_fn(fn: Callable[..., Any]) -> Callable[..., Any]:
|
|
36
|
+
"""Get the original unwrapped function.
|
|
37
|
+
|
|
38
|
+
Follows the __wrapped__ chain set by copy_function_metadata() to find the
|
|
39
|
+
original function. Falls back to checking for Call methods for bound methods.
|
|
40
|
+
"""
|
|
41
|
+
# Follow __wrapped__ chain if available (set by copy_function_metadata)
|
|
42
|
+
# In practice, get_original_fn is called with original functions or bound methods,
|
|
43
|
+
# so this loop is defensive code for edge cases like @functools.wraps chains.
|
|
44
|
+
while hasattr(fn, "__wrapped__"):
|
|
45
|
+
fn = fn.__wrapped__ # pyright: ignore[reportFunctionMemberAccess] # pragma: no cover
|
|
46
|
+
|
|
47
|
+
# Handle bound methods of Call objects (e.g., Call.call or Call.stream)
|
|
48
|
+
if _is_call_method(fn):
|
|
49
|
+
prompt = fn.__self__.prompt # pyright: ignore[reportFunctionMemberAccess]
|
|
50
|
+
if hasattr(prompt, "fn"):
|
|
51
|
+
return get_original_fn(prompt.fn)
|
|
52
|
+
|
|
53
|
+
return fn
|
|
54
|
+
|
|
55
|
+
|
|
28
56
|
def get_qualified_name(fn: Callable[..., Any]) -> str:
|
|
29
57
|
"""Return the simplified qualified name of a function.
|
|
30
58
|
|
|
59
|
+
If the function is a bound method of a Call object (e.g., Call.call or Call.stream),
|
|
60
|
+
returns the qualified name of the original decorated function from prompt.fn,
|
|
61
|
+
suffixed with the method name (e.g., "recommend.call" or "recommend.stream").
|
|
62
|
+
|
|
31
63
|
If the function is defined locally, return the name after '<locals>.'; otherwise,
|
|
32
64
|
return the last non-empty part after splitting by '.'.
|
|
33
65
|
"""
|
|
66
|
+
# Check if this is a Call method and capture the method name
|
|
67
|
+
method_suffix = f".{fn.__name__}" if _is_call_method(fn) else ""
|
|
68
|
+
|
|
69
|
+
fn = get_original_fn(fn)
|
|
34
70
|
qualified_name = fn.__qualname__
|
|
35
71
|
if "<locals>." in qualified_name:
|
|
36
|
-
|
|
72
|
+
base_name = qualified_name.split("<locals>.")[-1]
|
|
37
73
|
else:
|
|
38
74
|
parts = [part for part in qualified_name.split(".") if part]
|
|
39
|
-
|
|
75
|
+
base_name = parts[-1] if parts else qualified_name
|
|
76
|
+
|
|
77
|
+
return f"{base_name}{method_suffix}"
|
|
40
78
|
|
|
41
79
|
|
|
42
80
|
def extract_arguments(
|
|
@@ -44,8 +82,26 @@ def extract_arguments(
|
|
|
44
82
|
*args: P.args,
|
|
45
83
|
**kwargs: P.kwargs,
|
|
46
84
|
) -> tuple[dict[str, str], dict[str, Any]]:
|
|
47
|
-
"""Returns a tuple of (arg_types, arg_values) dictionaries from function call.
|
|
85
|
+
"""Returns a tuple of (arg_types, arg_values) dictionaries from function call.
|
|
86
|
+
|
|
87
|
+
If the function is a Call method (e.g., Call.call), uses the original
|
|
88
|
+
decorated function's signature to get proper parameter names and types.
|
|
89
|
+
|
|
90
|
+
If the function has `trace_ctx: Span` as first parameter (detected via
|
|
91
|
+
fn_wants_span), that parameter is skipped since it's injected by the
|
|
92
|
+
decorator and shouldn't be recorded in span attributes.
|
|
93
|
+
"""
|
|
94
|
+
# Use original function signature for Call methods
|
|
95
|
+
fn = get_original_fn(fn)
|
|
48
96
|
signature = inspect.signature(fn)
|
|
97
|
+
|
|
98
|
+
# If function wants span injection, skip the first parameter
|
|
99
|
+
if fn_wants_span(fn):
|
|
100
|
+
params = list(signature.parameters.values())
|
|
101
|
+
if params:
|
|
102
|
+
remaining_params = params[1:]
|
|
103
|
+
signature = signature.replace(parameters=remaining_params)
|
|
104
|
+
|
|
49
105
|
bound_arguments = signature.bind(*args, **kwargs)
|
|
50
106
|
bound_arguments.apply_defaults()
|
|
51
107
|
|
|
@@ -196,7 +196,7 @@ class _BaseVersionedFunction(_BaseTracedFunction[P, R, Any]):
|
|
|
196
196
|
if self.name:
|
|
197
197
|
span.set(**{"mirascope.version.name": self.name})
|
|
198
198
|
if self.tags:
|
|
199
|
-
span.set(**{"mirascope.version.tags": self.tags})
|
|
199
|
+
span.set(**{"mirascope.version.tags": list(self.tags)})
|
|
200
200
|
if self.metadata:
|
|
201
201
|
for key, value in self.metadata.items():
|
|
202
202
|
span.set(**{f"mirascope.version.meta.{key}": value})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mirascope
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary: LLM
|
|
3
|
+
Version: 2.0.2
|
|
4
|
+
Summary: Every frontier LLM. One unified interface.
|
|
5
5
|
Project-URL: Homepage, https://mirascope.com
|
|
6
6
|
Project-URL: Documentation, https://mirascope.com/docs/mirascope/v2
|
|
7
7
|
Project-URL: Repository, https://github.com/Mirascope/mirascope/tree/v2
|
|
@@ -11,7 +11,7 @@ Author-email: William Bakst <william@mirascope.com>, Dandelion Mané <dandelion@
|
|
|
11
11
|
Maintainer-email: William Bakst <william@mirascope.com>, Dandelion Mané <dandelion@mirascope.com>
|
|
12
12
|
License: MIT License
|
|
13
13
|
|
|
14
|
-
Copyright (c)
|
|
14
|
+
Copyright (c) 2026 Mirascope, Inc.
|
|
15
15
|
|
|
16
16
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
17
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -31,8 +31,8 @@ License: MIT License
|
|
|
31
31
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
32
|
SOFTWARE.
|
|
33
33
|
License-File: LICENSE
|
|
34
|
-
Keywords: agents,artificial intelligence,developer tools,llm,llm tools,prompt engineering
|
|
35
|
-
Classifier: Development Status ::
|
|
34
|
+
Keywords: agents,anthropic,artificial intelligence,context engineering,developer tools,gemini,llm,llm tools,openai,prompt engineering
|
|
35
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
36
36
|
Classifier: Intended Audience :: Developers
|
|
37
37
|
Classifier: License :: OSI Approved :: MIT License
|
|
38
38
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -48,15 +48,16 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
48
48
|
Requires-Python: >=3.10
|
|
49
49
|
Requires-Dist: docstring-parser>=0.17.0
|
|
50
50
|
Requires-Dist: httpx>=0.27.0
|
|
51
|
+
Requires-Dist: jiter>=0.7.0
|
|
51
52
|
Requires-Dist: pydantic>=2.0.0
|
|
52
53
|
Requires-Dist: typing-extensions>=4.10.0
|
|
53
54
|
Provides-Extra: all
|
|
54
|
-
Requires-Dist: anthropic<1.0,>=0.
|
|
55
|
-
Requires-Dist: google-genai<2,>=1.
|
|
55
|
+
Requires-Dist: anthropic<1.0,>=0.76.0; extra == 'all'
|
|
56
|
+
Requires-Dist: google-genai<2,>=1.58.0; extra == 'all'
|
|
56
57
|
Requires-Dist: libcst>=1.8.6; extra == 'all'
|
|
57
58
|
Requires-Dist: mcp<2,>=1.25.0; extra == 'all'
|
|
58
59
|
Requires-Dist: mlx-lm<1,>=0.28.4; extra == 'all'
|
|
59
|
-
Requires-Dist: openai<3,>=2.
|
|
60
|
+
Requires-Dist: openai<3,>=2.15.0; extra == 'all'
|
|
60
61
|
Requires-Dist: opentelemetry-api<2,>=1.38.0; extra == 'all'
|
|
61
62
|
Requires-Dist: opentelemetry-exporter-otlp<2,>=1.38.0; extra == 'all'
|
|
62
63
|
Requires-Dist: opentelemetry-instrumentation<1,>=0.59b0; extra == 'all'
|
|
@@ -70,11 +71,11 @@ Requires-Dist: pillow<11,>=10.4.0; extra == 'all'
|
|
|
70
71
|
Requires-Dist: proto-plus>=1.24.0; extra == 'all'
|
|
71
72
|
Requires-Dist: pydantic-settings>=2.12.0; extra == 'all'
|
|
72
73
|
Provides-Extra: anthropic
|
|
73
|
-
Requires-Dist: anthropic<1.0,>=0.
|
|
74
|
+
Requires-Dist: anthropic<1.0,>=0.76.0; extra == 'anthropic'
|
|
74
75
|
Provides-Extra: api
|
|
75
76
|
Requires-Dist: pydantic-settings>=2.12.0; extra == 'api'
|
|
76
77
|
Provides-Extra: google
|
|
77
|
-
Requires-Dist: google-genai<2,>=1.
|
|
78
|
+
Requires-Dist: google-genai<2,>=1.58.0; extra == 'google'
|
|
78
79
|
Requires-Dist: pillow<11,>=10.4.0; extra == 'google'
|
|
79
80
|
Requires-Dist: proto-plus>=1.24.0; extra == 'google'
|
|
80
81
|
Provides-Extra: mcp
|
|
@@ -82,7 +83,7 @@ Requires-Dist: mcp<2,>=1.25.0; extra == 'mcp'
|
|
|
82
83
|
Provides-Extra: mlx
|
|
83
84
|
Requires-Dist: mlx-lm<1,>=0.28.4; extra == 'mlx'
|
|
84
85
|
Provides-Extra: openai
|
|
85
|
-
Requires-Dist: openai<3,>=2.
|
|
86
|
+
Requires-Dist: openai<3,>=2.15.0; extra == 'openai'
|
|
86
87
|
Provides-Extra: ops
|
|
87
88
|
Requires-Dist: libcst>=1.8.6; extra == 'ops'
|
|
88
89
|
Requires-Dist: opentelemetry-api<2,>=1.38.0; extra == 'ops'
|