mirascope 1.18.3__py3-none-any.whl → 1.19.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/__init__.py +20 -2
- mirascope/beta/openai/__init__.py +1 -1
- mirascope/beta/openai/realtime/__init__.py +1 -1
- mirascope/beta/openai/realtime/tool.py +1 -1
- mirascope/beta/rag/__init__.py +2 -2
- mirascope/beta/rag/base/__init__.py +2 -2
- mirascope/beta/rag/weaviate/__init__.py +1 -1
- mirascope/core/__init__.py +26 -8
- mirascope/core/anthropic/__init__.py +3 -3
- mirascope/core/anthropic/_utils/_calculate_cost.py +114 -47
- mirascope/core/anthropic/call_response.py +9 -1
- mirascope/core/anthropic/call_response_chunk.py +7 -0
- mirascope/core/anthropic/stream.py +3 -1
- mirascope/core/azure/__init__.py +2 -2
- mirascope/core/azure/_utils/_calculate_cost.py +4 -1
- mirascope/core/azure/call_response.py +9 -1
- mirascope/core/azure/call_response_chunk.py +5 -0
- mirascope/core/azure/stream.py +3 -1
- mirascope/core/base/__init__.py +11 -9
- mirascope/core/base/_utils/__init__.py +10 -10
- mirascope/core/base/_utils/_get_common_usage.py +8 -4
- mirascope/core/base/_utils/_get_create_fn_or_async_create_fn.py +2 -2
- mirascope/core/base/_utils/_protocols.py +9 -8
- mirascope/core/base/call_response.py +22 -20
- mirascope/core/base/call_response_chunk.py +12 -1
- mirascope/core/base/stream.py +24 -21
- mirascope/core/base/tool.py +7 -5
- mirascope/core/base/types.py +22 -5
- mirascope/core/bedrock/__init__.py +3 -3
- mirascope/core/bedrock/_utils/_calculate_cost.py +4 -1
- mirascope/core/bedrock/call_response.py +8 -1
- mirascope/core/bedrock/call_response_chunk.py +5 -0
- mirascope/core/bedrock/stream.py +3 -1
- mirascope/core/cohere/__init__.py +2 -2
- mirascope/core/cohere/_utils/_calculate_cost.py +4 -3
- mirascope/core/cohere/call_response.py +9 -1
- mirascope/core/cohere/call_response_chunk.py +5 -0
- mirascope/core/cohere/stream.py +3 -1
- mirascope/core/gemini/__init__.py +2 -2
- mirascope/core/gemini/_utils/_calculate_cost.py +4 -1
- mirascope/core/gemini/_utils/_convert_message_params.py +1 -1
- mirascope/core/gemini/call_response.py +9 -1
- mirascope/core/gemini/call_response_chunk.py +5 -0
- mirascope/core/gemini/stream.py +3 -1
- mirascope/core/google/__init__.py +2 -2
- mirascope/core/google/_utils/_calculate_cost.py +141 -14
- mirascope/core/google/_utils/_convert_message_params.py +23 -51
- mirascope/core/google/_utils/_message_param_converter.py +34 -33
- mirascope/core/google/_utils/_validate_media_type.py +34 -0
- mirascope/core/google/call_response.py +26 -4
- mirascope/core/google/call_response_chunk.py +17 -9
- mirascope/core/google/stream.py +20 -2
- mirascope/core/groq/__init__.py +2 -2
- mirascope/core/groq/_utils/_calculate_cost.py +12 -11
- mirascope/core/groq/call_response.py +9 -1
- mirascope/core/groq/call_response_chunk.py +5 -0
- mirascope/core/groq/stream.py +3 -1
- mirascope/core/litellm/__init__.py +1 -1
- mirascope/core/litellm/_utils/_setup_call.py +7 -3
- mirascope/core/mistral/__init__.py +2 -2
- mirascope/core/mistral/_utils/_calculate_cost.py +10 -9
- mirascope/core/mistral/call_response.py +9 -1
- mirascope/core/mistral/call_response_chunk.py +5 -0
- mirascope/core/mistral/stream.py +3 -1
- mirascope/core/openai/__init__.py +2 -2
- mirascope/core/openai/_utils/_calculate_cost.py +78 -37
- mirascope/core/openai/call_params.py +13 -0
- mirascope/core/openai/call_response.py +14 -1
- mirascope/core/openai/call_response_chunk.py +12 -0
- mirascope/core/openai/stream.py +6 -4
- mirascope/core/vertex/__init__.py +1 -1
- mirascope/core/vertex/_utils/_calculate_cost.py +1 -0
- mirascope/core/vertex/_utils/_convert_message_params.py +1 -1
- mirascope/core/vertex/call_response.py +9 -1
- mirascope/core/vertex/call_response_chunk.py +5 -0
- mirascope/core/vertex/stream.py +3 -1
- mirascope/core/xai/__init__.py +28 -0
- mirascope/core/xai/_call.py +67 -0
- mirascope/core/xai/_utils/__init__.py +6 -0
- mirascope/core/xai/_utils/_calculate_cost.py +104 -0
- mirascope/core/xai/_utils/_setup_call.py +113 -0
- mirascope/core/xai/call_params.py +10 -0
- mirascope/core/xai/call_response.py +27 -0
- mirascope/core/xai/call_response_chunk.py +14 -0
- mirascope/core/xai/dynamic_config.py +8 -0
- mirascope/core/xai/py.typed +0 -0
- mirascope/core/xai/stream.py +57 -0
- mirascope/core/xai/tool.py +13 -0
- mirascope/integrations/_middleware_factory.py +6 -6
- mirascope/integrations/logfire/_utils.py +1 -1
- mirascope/llm/__init__.py +2 -2
- mirascope/llm/_protocols.py +34 -28
- mirascope/llm/call_response.py +16 -7
- mirascope/llm/llm_call.py +50 -46
- mirascope/llm/stream.py +43 -31
- mirascope/retries/__init__.py +1 -1
- mirascope/tools/__init__.py +2 -2
- {mirascope-1.18.3.dist-info → mirascope-1.19.0.dist-info}/METADATA +3 -1
- {mirascope-1.18.3.dist-info → mirascope-1.19.0.dist-info}/RECORD +101 -88
- {mirascope-1.18.3.dist-info → mirascope-1.19.0.dist-info}/WHEEL +0 -0
- {mirascope-1.18.3.dist-info → mirascope-1.19.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
def calculate_cost(
|
|
5
5
|
input_tokens: int | float | None,
|
|
6
|
+
cached_tokens: int | float | None,
|
|
6
7
|
output_tokens: int | float | None,
|
|
7
8
|
model: str = "gpt-3.5-turbo-16k",
|
|
8
9
|
) -> float | None:
|
|
@@ -10,196 +11,236 @@ def calculate_cost(
|
|
|
10
11
|
|
|
11
12
|
https://openai.com/pricing
|
|
12
13
|
|
|
13
|
-
Model Input Output
|
|
14
|
-
gpt-4o $2.50 / 1M tokens $10.00 / 1M tokens
|
|
15
|
-
gpt-4o-2024-11-20 $2.50 / 1M tokens $10.00 / 1M tokens
|
|
16
|
-
gpt-4o-2024-08-06 $2.50 / 1M tokens $10.00 / 1M tokens
|
|
17
|
-
gpt-4o-2024-05-13 $5.00 / 1M tokens $15.00 / 1M tokens
|
|
18
|
-
gpt-4o-audio-preview $2.50 / 1M tokens $10.00 / 1M tokens
|
|
19
|
-
gpt-4o-audio-preview-2024-12-17 $2.50 / 1M tokens $10.00 / 1M tokens
|
|
20
|
-
gpt-4o-audio-preview-2024-10-01 $2.50 / 1M tokens $10.00 / 1M tokens
|
|
21
|
-
gpt-4o-realtime-preview $5.00 / 1M tokens $20.00 / 1M tokens
|
|
22
|
-
gpt-4o-realtime-preview-2024-12-17 $5.00 / 1M tokens $20.00 / 1M tokens
|
|
23
|
-
gpt-4o-realtime-preview-2024-10-01 $5.00 / 1M tokens $20.00 / 1M tokens
|
|
24
|
-
gpt-4o-mini $0.15 / 1M tokens $0.60 / 1M tokens
|
|
25
|
-
gpt-4o-mini-2024-07-18 $0.15 / 1M tokens $0.60 / 1M tokens
|
|
26
|
-
gpt-4o-mini-audio-preview $0.15 / 1M tokens $0.60 / 1M tokens
|
|
27
|
-
gpt-4o-mini-audio-preview-2024-12-17 $0.15 / 1M tokens $0.60 / 1M tokens
|
|
28
|
-
gpt-4o-mini-realtime-preview $0.60 / 1M tokens $2.40 / 1M tokens
|
|
29
|
-
gpt-4o-mini-realtime-preview-2024-12-17 $0.60 / 1M tokens $2.40 / 1M tokens
|
|
30
|
-
o1 $15.00 / 1M tokens $60.00 / 1M tokens
|
|
31
|
-
o1-2024-12-17 $15.00 / 1M tokens $60.00 / 1M tokens
|
|
32
|
-
o1-preview-2024-09-12 $15.00 / 1M tokens $60.00 / 1M tokens
|
|
33
|
-
o3-mini $1.10 / 1M tokens $4.40 / 1M tokens
|
|
34
|
-
o3-mini-2025-01-31 $1.10 / 1M tokens $4.40 / 1M tokens
|
|
35
|
-
o1-mini $1.10 / 1M tokens $4.40 / 1M tokens
|
|
36
|
-
o1-mini-2024-09-12 $1.10 / 1M tokens $4.40 / 1M tokens
|
|
37
|
-
gpt-4-turbo $10.00 / 1M tokens
|
|
38
|
-
gpt-4-turbo-2024-04-09 $10.00 / 1M tokens
|
|
39
|
-
gpt-3.5-turbo-0125 $0.50
|
|
40
|
-
gpt-3.5-turbo-1106 $1.00
|
|
41
|
-
gpt-4-1106-preview $10.00 / 1M tokens
|
|
42
|
-
gpt-4 $30.00 / 1M tokens
|
|
43
|
-
text-embedding-3-small $0.02
|
|
44
|
-
text-embedding-3-large $0.13
|
|
45
|
-
text-embedding-ada-0002 $0.10
|
|
14
|
+
Model Input Cached Output
|
|
15
|
+
gpt-4o $2.50 / 1M tokens $1.25 / 1M tokens $10.00 / 1M tokens
|
|
16
|
+
gpt-4o-2024-11-20 $2.50 / 1M tokens $1.25 / 1M tokens $10.00 / 1M tokens
|
|
17
|
+
gpt-4o-2024-08-06 $2.50 / 1M tokens $1.25 / 1M tokens $10.00 / 1M tokens
|
|
18
|
+
gpt-4o-2024-05-13 $5.00 / 1M tokens $2.50 / 1M tokens $15.00 / 1M tokens
|
|
19
|
+
gpt-4o-audio-preview $2.50 / 1M tokens $1.25 / 1M tokens $10.00 / 1M tokens
|
|
20
|
+
gpt-4o-audio-preview-2024-12-17 $2.50 / 1M tokens $1.25 / 1M tokens $10.00 / 1M tokens
|
|
21
|
+
gpt-4o-audio-preview-2024-10-01 $2.50 / 1M tokens $1.25 / 1M tokens $10.00 / 1M tokens
|
|
22
|
+
gpt-4o-realtime-preview $5.00 / 1M tokens $2.50 / 1M tokens $20.00 / 1M tokens
|
|
23
|
+
gpt-4o-realtime-preview-2024-12-17 $5.00 / 1M tokens $2.50 / 1M tokens $20.00 / 1M tokens
|
|
24
|
+
gpt-4o-realtime-preview-2024-10-01 $5.00 / 1M tokens $2.50 / 1M tokens $20.00 / 1M tokens
|
|
25
|
+
gpt-4o-mini $0.15 / 1M tokens $0.08 / 1M tokens $0.60 / 1M tokens
|
|
26
|
+
gpt-4o-mini-2024-07-18 $0.15 / 1M tokens $0.08 / 1M tokens $0.60 / 1M tokens
|
|
27
|
+
gpt-4o-mini-audio-preview $0.15 / 1M tokens $0.08 / 1M tokens $0.60 / 1M tokens
|
|
28
|
+
gpt-4o-mini-audio-preview-2024-12-17 $0.15 / 1M tokens $0.08 / 1M tokens $0.60 / 1M tokens
|
|
29
|
+
gpt-4o-mini-realtime-preview $0.60 / 1M tokens $0.30 / 1M tokens $2.40 / 1M tokens
|
|
30
|
+
gpt-4o-mini-realtime-preview-2024-12-17 $0.60 / 1M tokens $0.30 / 1M tokens $2.40 / 1M tokens
|
|
31
|
+
o1 $15.00 / 1M tokens $7.50 / 1M tokens $60.00 / 1M tokens
|
|
32
|
+
o1-2024-12-17 $15.00 / 1M tokens $7.50 / 1M tokens $60.00 / 1M tokens
|
|
33
|
+
o1-preview-2024-09-12 $15.00 / 1M tokens $7.50 / 1M tokens $60.00 / 1M tokens
|
|
34
|
+
o3-mini $1.10 / 1M tokens $0.55 / 1M tokens $4.40 / 1M tokens
|
|
35
|
+
o3-mini-2025-01-31 $1.10 / 1M tokens $0.55 / 1M tokens $4.40 / 1M tokens
|
|
36
|
+
o1-mini $1.10 / 1M tokens $0.55 / 1M tokens $4.40 / 1M tokens
|
|
37
|
+
o1-mini-2024-09-12 $1.10 / 1M tokens $0.55 / 1M tokens $4.40 / 1M tokens
|
|
38
|
+
gpt-4-turbo $10.00 / 1M tokens $30.00 / 1M tokens
|
|
39
|
+
gpt-4-turbo-2024-04-09 $10.00 / 1M tokens $30.00 / 1M tokens
|
|
40
|
+
gpt-3.5-turbo-0125 $0.50 / 1M tokens $1.50 / 1M tokens
|
|
41
|
+
gpt-3.5-turbo-1106 $1.00 / 1M tokens $2.00 / 1M tokens
|
|
42
|
+
gpt-4-1106-preview $10.00 / 1M tokens $30.00 / 1M tokens
|
|
43
|
+
gpt-4 $30.00 / 1M tokens $60.00 / 1M tokens
|
|
44
|
+
text-embedding-3-small $0.02 / 1M tokens
|
|
45
|
+
text-embedding-3-large $0.13 / 1M tokens
|
|
46
|
+
text-embedding-ada-0002 $0.10 / 1M tokens
|
|
46
47
|
"""
|
|
47
48
|
pricing = {
|
|
48
49
|
"gpt-4o": {
|
|
49
50
|
"prompt": 0.000_002_5,
|
|
51
|
+
"cached": 0.000_001_25,
|
|
50
52
|
"completion": 0.000_01,
|
|
51
53
|
},
|
|
52
54
|
"gpt-4o-2024-11-20": {
|
|
53
55
|
"prompt": 0.000_002_5,
|
|
56
|
+
"cached": 0.000_001_25,
|
|
54
57
|
"completion": 0.000_01,
|
|
55
58
|
},
|
|
56
59
|
"gpt-4o-2024-08-06": {
|
|
57
60
|
"prompt": 0.000_002_5,
|
|
61
|
+
"cached": 0.000_001_25,
|
|
58
62
|
"completion": 0.000_01,
|
|
59
63
|
},
|
|
60
64
|
"gpt-4o-2024-05-13": {
|
|
61
65
|
"prompt": 0.000_005,
|
|
66
|
+
"cached": 0.000_002_5,
|
|
62
67
|
"completion": 0.000_015,
|
|
63
68
|
},
|
|
64
69
|
"gpt-4o-audio-preview": {
|
|
65
70
|
"prompt": 0.000_002_5,
|
|
71
|
+
"cached": 0.000_001_25,
|
|
66
72
|
"completion": 0.000_01,
|
|
67
73
|
},
|
|
68
74
|
"gpt-4o-audio-preview-2024-12-17": {
|
|
69
75
|
"prompt": 0.000_002_5,
|
|
76
|
+
"cached": 0.000_001_25,
|
|
70
77
|
"completion": 0.000_01,
|
|
71
78
|
},
|
|
72
79
|
"gpt-4o-audio-preview-2024-10-01": {
|
|
73
80
|
"prompt": 0.000_002_5,
|
|
81
|
+
"cached": 0.000_001_25,
|
|
74
82
|
"completion": 0.000_01,
|
|
75
83
|
},
|
|
76
84
|
"gpt-4o-realtime-preview": {
|
|
77
85
|
"prompt": 0.000_005,
|
|
86
|
+
"cached": 0.000_002_5,
|
|
78
87
|
"completion": 0.000_02,
|
|
79
88
|
},
|
|
80
89
|
"gpt-4o-realtime-preview-2024-12-17": {
|
|
81
90
|
"prompt": 0.000_005,
|
|
91
|
+
"cached": 0.000_002_5,
|
|
82
92
|
"completion": 0.000_02,
|
|
83
93
|
},
|
|
84
94
|
"gpt-4o-realtime-preview-2024-10-01": {
|
|
85
95
|
"prompt": 0.000_005,
|
|
96
|
+
"cached": 0.000_002_5,
|
|
86
97
|
"completion": 0.000_02,
|
|
87
98
|
},
|
|
88
99
|
"gpt-4o-mini": {
|
|
89
100
|
"prompt": 0.000_000_15,
|
|
101
|
+
"cached": 0.000_000_08,
|
|
90
102
|
"completion": 0.000_000_6,
|
|
91
103
|
},
|
|
92
104
|
"gpt-4o-mini-2024-07-18": {
|
|
93
105
|
"prompt": 0.000_000_15,
|
|
106
|
+
"cached": 0.000_000_08,
|
|
94
107
|
"completion": 0.000_000_6,
|
|
95
108
|
},
|
|
96
109
|
"gpt-4o-mini-audio-preview": {
|
|
97
110
|
"prompt": 0.000_000_15,
|
|
111
|
+
"cached": 0.000_000_08,
|
|
98
112
|
"completion": 0.000_000_6,
|
|
99
113
|
},
|
|
100
114
|
"gpt-4o-mini-audio-preview-2024-12-17": {
|
|
101
115
|
"prompt": 0.000_000_15,
|
|
116
|
+
"cached": 0.000_000_08,
|
|
102
117
|
"completion": 0.000_000_6,
|
|
103
118
|
},
|
|
104
119
|
"gpt-4o-mini-realtime-preview": {
|
|
105
120
|
"prompt": 0.000_000_6,
|
|
121
|
+
"cached": 0.000_000_3,
|
|
106
122
|
"completion": 0.000_002_4,
|
|
107
123
|
},
|
|
108
124
|
"gpt-4o-mini-realtime-preview-2024-12-17": {
|
|
109
125
|
"prompt": 0.000_000_6,
|
|
126
|
+
"cached": 0.000_000_3,
|
|
110
127
|
"completion": 0.000_002_4,
|
|
111
128
|
},
|
|
112
129
|
"o1": {
|
|
113
130
|
"prompt": 0.000_015,
|
|
131
|
+
"cached": 0.000_007_5,
|
|
114
132
|
"completion": 0.000_06,
|
|
115
133
|
},
|
|
116
134
|
"o1-2024-12-17": {
|
|
117
135
|
"prompt": 0.000_015,
|
|
136
|
+
"cached": 0.000_007_5,
|
|
118
137
|
"completion": 0.000_06,
|
|
119
138
|
},
|
|
120
139
|
"o1-preview-2024-09-12": {
|
|
121
140
|
"prompt": 0.000_015,
|
|
141
|
+
"cached": 0.000_007_5,
|
|
122
142
|
"completion": 0.000_06,
|
|
123
143
|
},
|
|
124
144
|
"o3-mini": {
|
|
125
145
|
"prompt": 0.000_001_1,
|
|
146
|
+
"cached": 0.000_000_55,
|
|
126
147
|
"completion": 0.000_004_4,
|
|
127
148
|
},
|
|
128
149
|
"o3-mini-2025-01-31": {
|
|
129
150
|
"prompt": 0.000_001_1,
|
|
151
|
+
"cached": 0.000_000_55,
|
|
130
152
|
"completion": 0.000_004_4,
|
|
131
153
|
},
|
|
132
154
|
"o1-mini": {
|
|
133
155
|
"prompt": 0.000_001_1,
|
|
156
|
+
"cached": 0.000_000_55,
|
|
134
157
|
"completion": 0.000_004_4,
|
|
135
158
|
},
|
|
136
159
|
"o1-mini-2024-09-12": {
|
|
137
160
|
"prompt": 0.000_001_1,
|
|
161
|
+
"cached": 0.000_000_55,
|
|
138
162
|
"completion": 0.000_004_4,
|
|
139
163
|
},
|
|
140
164
|
"gpt-4-turbo": {
|
|
141
165
|
"prompt": 0.000_01,
|
|
166
|
+
"cached": 0,
|
|
142
167
|
"completion": 0.000_03,
|
|
143
168
|
},
|
|
144
169
|
"gpt-4-turbo-2024-04-09": {
|
|
145
170
|
"prompt": 0.000_01,
|
|
171
|
+
"cached": 0,
|
|
146
172
|
"completion": 0.000_03,
|
|
147
173
|
},
|
|
148
174
|
"gpt-3.5-turbo-0125": {
|
|
149
175
|
"prompt": 0.000_000_5,
|
|
176
|
+
"cached": 0,
|
|
150
177
|
"completion": 0.000_001_5,
|
|
151
178
|
},
|
|
152
179
|
"gpt-3.5-turbo-1106": {
|
|
153
180
|
"prompt": 0.000_001,
|
|
181
|
+
"cached": 0,
|
|
154
182
|
"completion": 0.000_002,
|
|
155
183
|
},
|
|
156
184
|
"gpt-4-1106-preview": {
|
|
157
185
|
"prompt": 0.000_01,
|
|
186
|
+
"cached": 0,
|
|
158
187
|
"completion": 0.000_03,
|
|
159
188
|
},
|
|
160
189
|
"gpt-4": {
|
|
161
190
|
"prompt": 0.000_003,
|
|
191
|
+
"cached": 0,
|
|
162
192
|
"completion": 0.000_006,
|
|
163
193
|
},
|
|
164
194
|
"gpt-3.5-turbo-4k": {
|
|
165
195
|
"prompt": 0.000_015,
|
|
196
|
+
"cached": 0,
|
|
166
197
|
"completion": 0.000_02,
|
|
167
198
|
},
|
|
168
199
|
"gpt-3.5-turbo-16k": {
|
|
169
200
|
"prompt": 0.000_003,
|
|
201
|
+
"cached": 0,
|
|
170
202
|
"completion": 0.000_004,
|
|
171
203
|
},
|
|
172
204
|
"gpt-4-8k": {
|
|
173
205
|
"prompt": 0.000_003,
|
|
206
|
+
"cached": 0,
|
|
174
207
|
"completion": 0.000_006,
|
|
175
208
|
},
|
|
176
209
|
"gpt-4-32k": {
|
|
177
210
|
"prompt": 0.000_006,
|
|
211
|
+
"cached": 0,
|
|
178
212
|
"completion": 0.000_012,
|
|
179
213
|
},
|
|
180
214
|
"text-embedding-3-small": {
|
|
181
215
|
"prompt": 0.000_000_02,
|
|
182
|
-
"
|
|
216
|
+
"cached": 0,
|
|
217
|
+
"completion": 0,
|
|
183
218
|
},
|
|
184
219
|
"text-embedding-ada-002": {
|
|
185
220
|
"prompt": 0.000_000_1,
|
|
186
|
-
"
|
|
221
|
+
"cached": 0,
|
|
222
|
+
"completion": 0,
|
|
187
223
|
},
|
|
188
224
|
"text-embedding-3-large": {
|
|
189
225
|
"prompt": 0.000_000_13,
|
|
190
|
-
"
|
|
226
|
+
"cached": 0,
|
|
227
|
+
"completion": 0,
|
|
191
228
|
},
|
|
192
229
|
}
|
|
193
230
|
if input_tokens is None or output_tokens is None:
|
|
194
231
|
return None
|
|
195
232
|
|
|
233
|
+
if cached_tokens is None:
|
|
234
|
+
cached_tokens = 0
|
|
235
|
+
|
|
196
236
|
try:
|
|
197
237
|
model_pricing = pricing[model]
|
|
198
238
|
except KeyError:
|
|
199
239
|
return None
|
|
200
240
|
|
|
201
241
|
prompt_cost = input_tokens * model_pricing["prompt"]
|
|
242
|
+
cached_cost = cached_tokens * model_pricing["cached"]
|
|
202
243
|
completion_cost = output_tokens * model_pricing["completion"]
|
|
203
|
-
total_cost = prompt_cost + completion_cost
|
|
244
|
+
total_cost = prompt_cost + cached_cost + completion_cost
|
|
204
245
|
|
|
205
246
|
return total_cost
|
|
@@ -18,6 +18,9 @@ if TYPE_CHECKING:
|
|
|
18
18
|
ChatCompletionAudioParam,
|
|
19
19
|
ChatCompletionModality, # pyright: ignore [reportAttributeAccessIssue]
|
|
20
20
|
)
|
|
21
|
+
from openai.types.chat.chat_completion_reasoning_effort import ( # pyright: ignore [reportMissingImports]
|
|
22
|
+
ChatCompletionReasoningEffort, # pyright: ignore [reportAttributeAccessIssue]
|
|
23
|
+
)
|
|
21
24
|
else:
|
|
22
25
|
try:
|
|
23
26
|
from openai.types.chat.chat_completion_audio_param import ( # pyright: ignore [reportMissingImports]
|
|
@@ -30,6 +33,14 @@ else:
|
|
|
30
33
|
|
|
31
34
|
class ChatCompletionModality: ...
|
|
32
35
|
|
|
36
|
+
try:
|
|
37
|
+
from openai.types.chat.chat_completion_reasoning_effort import ( # pyright: ignore [reportMissingImports]
|
|
38
|
+
ChatCompletionReasoningEffort,
|
|
39
|
+
)
|
|
40
|
+
except ImportError:
|
|
41
|
+
|
|
42
|
+
class ChatCompletionReasoningEffort: ...
|
|
43
|
+
|
|
33
44
|
|
|
34
45
|
class OpenAICallParams(BaseCallParams):
|
|
35
46
|
"""The parameters to use when calling the OpenAI API.
|
|
@@ -46,6 +57,7 @@ class OpenAICallParams(BaseCallParams):
|
|
|
46
57
|
n: ...
|
|
47
58
|
parallel_tool_calls: ...
|
|
48
59
|
presence_penalty: ...
|
|
60
|
+
reasoning_effort: ...
|
|
49
61
|
response_format: ...
|
|
50
62
|
seed: ...
|
|
51
63
|
stop: ...
|
|
@@ -67,6 +79,7 @@ class OpenAICallParams(BaseCallParams):
|
|
|
67
79
|
n: NotRequired[int | None]
|
|
68
80
|
parallel_tool_calls: NotRequired[bool]
|
|
69
81
|
presence_penalty: NotRequired[float | None]
|
|
82
|
+
reasoning_effort: NotRequired[ChatCompletionReasoningEffort | None]
|
|
70
83
|
response_format: NotRequired[ResponseFormat]
|
|
71
84
|
seed: NotRequired[int | None]
|
|
72
85
|
stop: NotRequired[str | list[str] | None]
|
|
@@ -118,6 +118,17 @@ class OpenAICallResponse(
|
|
|
118
118
|
"""Returns the number of input tokens."""
|
|
119
119
|
return self.usage.prompt_tokens if self.usage else None
|
|
120
120
|
|
|
121
|
+
@computed_field
|
|
122
|
+
@property
|
|
123
|
+
def cached_tokens(self) -> int | None:
|
|
124
|
+
"""Returns the number of cached tokens."""
|
|
125
|
+
return (
|
|
126
|
+
details.cached_tokens
|
|
127
|
+
if self.usage
|
|
128
|
+
and (details := getattr(self.usage, "prompt_tokens_details", None))
|
|
129
|
+
else None
|
|
130
|
+
)
|
|
131
|
+
|
|
121
132
|
@computed_field
|
|
122
133
|
@property
|
|
123
134
|
def output_tokens(self) -> int | None:
|
|
@@ -128,7 +139,9 @@ class OpenAICallResponse(
|
|
|
128
139
|
@property
|
|
129
140
|
def cost(self) -> float | None:
|
|
130
141
|
"""Returns the cost of the call."""
|
|
131
|
-
return calculate_cost(
|
|
142
|
+
return calculate_cost(
|
|
143
|
+
self.input_tokens, self.cached_tokens, self.output_tokens, self.model
|
|
144
|
+
)
|
|
132
145
|
|
|
133
146
|
@computed_field
|
|
134
147
|
@cached_property
|
|
@@ -79,6 +79,18 @@ class OpenAICallResponseChunk(BaseCallResponseChunk[ChatCompletionChunk, FinishR
|
|
|
79
79
|
return self.chunk.usage
|
|
80
80
|
return None
|
|
81
81
|
|
|
82
|
+
@computed_field
|
|
83
|
+
@property
|
|
84
|
+
def cached_tokens(self) -> int | None:
|
|
85
|
+
"""Returns the number of cached tokens."""
|
|
86
|
+
return (
|
|
87
|
+
details.cached_tokens
|
|
88
|
+
if hasattr(self.chunk, "usage")
|
|
89
|
+
and self.usage
|
|
90
|
+
and (details := getattr(self.usage, "prompt_tokens_details", None))
|
|
91
|
+
else None
|
|
92
|
+
)
|
|
93
|
+
|
|
82
94
|
@property
|
|
83
95
|
def input_tokens(self) -> int | None:
|
|
84
96
|
"""Returns the number of input tokens."""
|
mirascope/core/openai/stream.py
CHANGED
|
@@ -87,9 +87,9 @@ class OpenAIStream(
|
|
|
87
87
|
) -> AsyncGenerator[tuple[OpenAICallResponseChunk, OpenAITool | None], None]:
|
|
88
88
|
aiter = super().__aiter__()
|
|
89
89
|
|
|
90
|
-
async def generator() ->
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
async def generator() -> AsyncGenerator[
|
|
91
|
+
tuple[OpenAICallResponseChunk, OpenAITool | None], None
|
|
92
|
+
]:
|
|
93
93
|
async for chunk, tool in aiter:
|
|
94
94
|
if (
|
|
95
95
|
(choices := chunk.chunk.choices)
|
|
@@ -104,7 +104,9 @@ class OpenAIStream(
|
|
|
104
104
|
@property
|
|
105
105
|
def cost(self) -> float | None:
|
|
106
106
|
"""Returns the cost of the call."""
|
|
107
|
-
return calculate_cost(
|
|
107
|
+
return calculate_cost(
|
|
108
|
+
self.input_tokens, self.cached_tokens, self.output_tokens, self.model
|
|
109
|
+
)
|
|
108
110
|
|
|
109
111
|
def _construct_message_param(
|
|
110
112
|
self,
|
|
@@ -33,7 +33,6 @@ warnings.warn(
|
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
__all__ = [
|
|
36
|
-
"call",
|
|
37
36
|
"VertexCallParams",
|
|
38
37
|
"VertexCallResponse",
|
|
39
38
|
"VertexCallResponseChunk",
|
|
@@ -41,5 +40,6 @@ __all__ = [
|
|
|
41
40
|
"VertexMessageParam",
|
|
42
41
|
"VertexStream",
|
|
43
42
|
"VertexTool",
|
|
43
|
+
"call",
|
|
44
44
|
"vertex_call",
|
|
45
45
|
]
|
|
@@ -106,7 +106,7 @@ def convert_message_params(
|
|
|
106
106
|
elif part.type == "audio_url":
|
|
107
107
|
# Should download the audio to determine the media type
|
|
108
108
|
audio = _load_media(part.url)
|
|
109
|
-
audio_type = get_audio_type(audio)
|
|
109
|
+
audio_type = f"audio/{get_audio_type(audio)}"
|
|
110
110
|
if audio_type not in [
|
|
111
111
|
"audio/wav",
|
|
112
112
|
"audio/mp3",
|
|
@@ -112,6 +112,12 @@ class VertexCallResponse(
|
|
|
112
112
|
"""Returns the number of input tokens."""
|
|
113
113
|
return self.usage.prompt_token_count
|
|
114
114
|
|
|
115
|
+
@computed_field
|
|
116
|
+
@property
|
|
117
|
+
def cached_tokens(self) -> int:
|
|
118
|
+
"""Returns the number of cached tokens."""
|
|
119
|
+
return 0
|
|
120
|
+
|
|
115
121
|
@computed_field
|
|
116
122
|
@property
|
|
117
123
|
def output_tokens(self) -> int:
|
|
@@ -122,7 +128,9 @@ class VertexCallResponse(
|
|
|
122
128
|
@property
|
|
123
129
|
def cost(self) -> float | None:
|
|
124
130
|
"""Returns the cost of the call."""
|
|
125
|
-
return calculate_cost(
|
|
131
|
+
return calculate_cost(
|
|
132
|
+
self.input_tokens, self.cached_tokens, self.output_tokens, self.model
|
|
133
|
+
)
|
|
126
134
|
|
|
127
135
|
@computed_field
|
|
128
136
|
@cached_property
|
|
@@ -76,6 +76,11 @@ class VertexCallResponseChunk(
|
|
|
76
76
|
"""Returns the number of input tokens."""
|
|
77
77
|
return None
|
|
78
78
|
|
|
79
|
+
@property
|
|
80
|
+
def cached_tokens(self) -> None:
|
|
81
|
+
"""Returns the number of cached tokens."""
|
|
82
|
+
return None
|
|
83
|
+
|
|
79
84
|
@property
|
|
80
85
|
def output_tokens(self) -> None:
|
|
81
86
|
"""Returns the number of output tokens."""
|
mirascope/core/vertex/stream.py
CHANGED
|
@@ -64,7 +64,9 @@ class VertexStream(
|
|
|
64
64
|
@property
|
|
65
65
|
def cost(self) -> float | None:
|
|
66
66
|
"""Returns the cost of the call."""
|
|
67
|
-
return calculate_cost(
|
|
67
|
+
return calculate_cost(
|
|
68
|
+
self.input_tokens, self.cached_tokens, self.output_tokens, self.model
|
|
69
|
+
)
|
|
68
70
|
|
|
69
71
|
def _construct_message_param(
|
|
70
72
|
self,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""The Mirascope xAI Module."""
|
|
2
|
+
|
|
3
|
+
from typing import TypeAlias
|
|
4
|
+
|
|
5
|
+
from ..openai import OpenAIMessageParam
|
|
6
|
+
from ._call import xai_call
|
|
7
|
+
from ._call import xai_call as call
|
|
8
|
+
from .call_params import XAICallParams
|
|
9
|
+
from .call_response import XAICallResponse
|
|
10
|
+
from .call_response_chunk import XAICallResponseChunk
|
|
11
|
+
from .dynamic_config import AsyncXAIDynamicConfig, XAIDynamicConfig
|
|
12
|
+
from .stream import XAIStream
|
|
13
|
+
from .tool import XAITool
|
|
14
|
+
|
|
15
|
+
XAIMessageParam: TypeAlias = OpenAIMessageParam
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"AsyncXAIDynamicConfig",
|
|
19
|
+
"XAICallParams",
|
|
20
|
+
"XAICallResponse",
|
|
21
|
+
"XAICallResponseChunk",
|
|
22
|
+
"XAIDynamicConfig",
|
|
23
|
+
"XAIMessageParam",
|
|
24
|
+
"XAIStream",
|
|
25
|
+
"XAITool",
|
|
26
|
+
"call",
|
|
27
|
+
"xai_call",
|
|
28
|
+
]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""The `xai_call` decorator for functions as LLM calls."""
|
|
2
|
+
|
|
3
|
+
from ..base import call_factory
|
|
4
|
+
from ..openai._utils import (
|
|
5
|
+
get_json_output,
|
|
6
|
+
handle_stream,
|
|
7
|
+
handle_stream_async,
|
|
8
|
+
)
|
|
9
|
+
from ._utils import setup_call
|
|
10
|
+
from .call_params import XAICallParams
|
|
11
|
+
from .call_response import XAICallResponse
|
|
12
|
+
from .call_response_chunk import XAICallResponseChunk
|
|
13
|
+
from .stream import XAIStream
|
|
14
|
+
from .tool import XAITool
|
|
15
|
+
|
|
16
|
+
xai_call = call_factory(
|
|
17
|
+
TCallResponse=XAICallResponse,
|
|
18
|
+
TCallResponseChunk=XAICallResponseChunk,
|
|
19
|
+
TToolType=XAITool,
|
|
20
|
+
TStream=XAIStream,
|
|
21
|
+
default_call_params=XAICallParams(),
|
|
22
|
+
setup_call=setup_call, # pyright: ignore [reportArgumentType]
|
|
23
|
+
get_json_output=get_json_output,
|
|
24
|
+
handle_stream=handle_stream, # pyright: ignore [reportArgumentType]
|
|
25
|
+
handle_stream_async=handle_stream_async, # pyright: ignore [reportArgumentType]
|
|
26
|
+
)
|
|
27
|
+
"""A decorator for calling the xAI API with a typed function.
|
|
28
|
+
|
|
29
|
+
usage docs: learn/calls.md
|
|
30
|
+
|
|
31
|
+
This decorator is used to wrap a typed function that calls the xAI API. It parses
|
|
32
|
+
the prompt template of the wrapped function as the messages array and templates the input
|
|
33
|
+
arguments for the function into each message's template.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from mirascope.core import prompt_template
|
|
39
|
+
from mirascope.core.xai import xai_call
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@xai_call("grok-2-latest")
|
|
43
|
+
def recommend_book(genre: str) -> str:
|
|
44
|
+
return f"Recommend a {genre} book"
|
|
45
|
+
|
|
46
|
+
response = recommend_book("fantasy")
|
|
47
|
+
print(response.content)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
model (str): The model to use in the API call.
|
|
52
|
+
stream (bool): Whether to stream the response from the API call.
|
|
53
|
+
tools (list[BaseTool | Callable]): The tools to use in the API call.
|
|
54
|
+
response_model (BaseModel | BaseType): The response model into which the response
|
|
55
|
+
should be structured.
|
|
56
|
+
output_parser (Callable[[OpenAICallResponse | ResponseModelT], Any]): A function for
|
|
57
|
+
parsing the call response whose value will be returned in place of the original
|
|
58
|
+
call response.
|
|
59
|
+
json_mode (bool): Whether to use JSON Mode.
|
|
60
|
+
client (None): xAI does not support a custom client.
|
|
61
|
+
call_params (OpenAICallParams): The `OpenAICallParams` call parameters to use in the
|
|
62
|
+
API call.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
decorator (Callable): The decorator for turning a typed function into a xAI
|
|
66
|
+
routed LLM API call.
|
|
67
|
+
"""
|