mirascope 1.18.2__py3-none-any.whl → 1.18.4__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.
Files changed (89) hide show
  1. mirascope/__init__.py +20 -1
  2. mirascope/beta/openai/__init__.py +1 -1
  3. mirascope/beta/openai/realtime/__init__.py +1 -1
  4. mirascope/beta/openai/realtime/tool.py +1 -1
  5. mirascope/beta/rag/__init__.py +2 -2
  6. mirascope/beta/rag/base/__init__.py +2 -2
  7. mirascope/beta/rag/weaviate/__init__.py +1 -1
  8. mirascope/core/__init__.py +29 -6
  9. mirascope/core/anthropic/__init__.py +3 -3
  10. mirascope/core/anthropic/_utils/_calculate_cost.py +114 -47
  11. mirascope/core/anthropic/call_response.py +9 -3
  12. mirascope/core/anthropic/call_response_chunk.py +7 -0
  13. mirascope/core/anthropic/stream.py +3 -1
  14. mirascope/core/azure/__init__.py +2 -2
  15. mirascope/core/azure/_utils/_calculate_cost.py +4 -1
  16. mirascope/core/azure/call_response.py +9 -3
  17. mirascope/core/azure/call_response_chunk.py +5 -0
  18. mirascope/core/azure/stream.py +3 -1
  19. mirascope/core/base/__init__.py +11 -9
  20. mirascope/core/base/_utils/__init__.py +10 -10
  21. mirascope/core/base/_utils/_get_common_usage.py +8 -4
  22. mirascope/core/base/_utils/_get_create_fn_or_async_create_fn.py +2 -2
  23. mirascope/core/base/_utils/_protocols.py +9 -8
  24. mirascope/core/base/call_response.py +22 -22
  25. mirascope/core/base/call_response_chunk.py +12 -1
  26. mirascope/core/base/stream.py +24 -21
  27. mirascope/core/base/tool.py +7 -5
  28. mirascope/core/base/types.py +22 -5
  29. mirascope/core/bedrock/__init__.py +3 -3
  30. mirascope/core/bedrock/_utils/_calculate_cost.py +4 -1
  31. mirascope/core/bedrock/call_response.py +8 -3
  32. mirascope/core/bedrock/call_response_chunk.py +5 -0
  33. mirascope/core/bedrock/stream.py +3 -1
  34. mirascope/core/cohere/__init__.py +2 -2
  35. mirascope/core/cohere/_utils/_calculate_cost.py +4 -3
  36. mirascope/core/cohere/call_response.py +9 -3
  37. mirascope/core/cohere/call_response_chunk.py +5 -0
  38. mirascope/core/cohere/stream.py +3 -1
  39. mirascope/core/gemini/__init__.py +2 -2
  40. mirascope/core/gemini/_utils/_calculate_cost.py +4 -1
  41. mirascope/core/gemini/_utils/_convert_message_params.py +1 -1
  42. mirascope/core/gemini/call_response.py +9 -3
  43. mirascope/core/gemini/call_response_chunk.py +5 -0
  44. mirascope/core/gemini/stream.py +3 -1
  45. mirascope/core/google/__init__.py +2 -2
  46. mirascope/core/google/_utils/_calculate_cost.py +141 -14
  47. mirascope/core/google/_utils/_convert_message_params.py +120 -115
  48. mirascope/core/google/_utils/_message_param_converter.py +34 -33
  49. mirascope/core/google/_utils/_validate_media_type.py +34 -0
  50. mirascope/core/google/call_response.py +38 -10
  51. mirascope/core/google/call_response_chunk.py +17 -9
  52. mirascope/core/google/stream.py +20 -2
  53. mirascope/core/groq/__init__.py +2 -2
  54. mirascope/core/groq/_utils/_calculate_cost.py +12 -11
  55. mirascope/core/groq/call_response.py +9 -3
  56. mirascope/core/groq/call_response_chunk.py +5 -0
  57. mirascope/core/groq/stream.py +3 -1
  58. mirascope/core/litellm/__init__.py +1 -1
  59. mirascope/core/litellm/_utils/_setup_call.py +7 -3
  60. mirascope/core/mistral/__init__.py +2 -2
  61. mirascope/core/mistral/_utils/_calculate_cost.py +10 -9
  62. mirascope/core/mistral/call_response.py +9 -3
  63. mirascope/core/mistral/call_response_chunk.py +5 -0
  64. mirascope/core/mistral/stream.py +3 -1
  65. mirascope/core/openai/__init__.py +2 -2
  66. mirascope/core/openai/_utils/_calculate_cost.py +78 -37
  67. mirascope/core/openai/call_params.py +13 -0
  68. mirascope/core/openai/call_response.py +14 -3
  69. mirascope/core/openai/call_response_chunk.py +12 -0
  70. mirascope/core/openai/stream.py +6 -4
  71. mirascope/core/vertex/__init__.py +1 -1
  72. mirascope/core/vertex/_utils/_calculate_cost.py +1 -0
  73. mirascope/core/vertex/_utils/_convert_message_params.py +1 -1
  74. mirascope/core/vertex/call_response.py +9 -3
  75. mirascope/core/vertex/call_response_chunk.py +5 -0
  76. mirascope/core/vertex/stream.py +3 -1
  77. mirascope/integrations/_middleware_factory.py +6 -6
  78. mirascope/integrations/logfire/_utils.py +1 -1
  79. mirascope/llm/__init__.py +3 -1
  80. mirascope/llm/_protocols.py +5 -5
  81. mirascope/llm/call_response.py +16 -9
  82. mirascope/llm/llm_call.py +53 -25
  83. mirascope/llm/stream.py +43 -31
  84. mirascope/retries/__init__.py +1 -1
  85. mirascope/tools/__init__.py +2 -2
  86. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/METADATA +2 -2
  87. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/RECORD +89 -88
  88. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/WHEEL +0 -0
  89. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/licenses/LICENSE +0 -0
mirascope/__init__.py CHANGED
@@ -7,11 +7,20 @@ with suppress(ImportError):
7
7
  from . import core as core
8
8
 
9
9
  from .core import (
10
+ AudioPart,
11
+ AudioURLPart,
10
12
  BaseDynamicConfig,
11
13
  BaseMessageParam,
12
14
  BaseTool,
13
15
  BaseToolKit,
16
+ CacheControlPart,
17
+ DocumentPart,
18
+ ImagePart,
19
+ ImageURLPart,
14
20
  Messages,
21
+ TextPart,
22
+ ToolCallPart,
23
+ ToolResultPart,
15
24
  prompt_template,
16
25
  )
17
26
 
@@ -24,13 +33,23 @@ with suppress(ImportError):
24
33
  __version__ = importlib.metadata.version("mirascope")
25
34
 
26
35
  __all__ = [
36
+ "AudioPart",
37
+ "AudioURLPart",
27
38
  "BaseDynamicConfig",
28
39
  "BaseMessageParam",
29
40
  "BaseTool",
30
41
  "BaseToolKit",
42
+ "CacheControlPart",
43
+ "DocumentPart",
44
+ "ImagePart",
45
+ "ImageURLPart",
46
+ "Messages",
47
+ "TextPart",
48
+ "ToolCallPart",
49
+ "ToolResultPart",
50
+ "__version__",
31
51
  "core",
32
52
  "integrations",
33
53
  "prompt_template",
34
54
  "retries",
35
- "__version__",
36
55
  ]
@@ -8,10 +8,10 @@ from .realtime import (
8
8
  )
9
9
 
10
10
  __all__ = [
11
- "async_input",
12
11
  "Context",
13
12
  "OpenAIRealtimeTool",
14
13
  "Realtime",
14
+ "async_input",
15
15
  "record",
16
16
  "record_as_stream",
17
17
  ]
@@ -4,10 +4,10 @@ from .recording import async_input, record, record_as_stream
4
4
  from .tool import OpenAIRealtimeTool
5
5
 
6
6
  __all__ = [
7
- "async_input",
8
7
  "Context",
9
8
  "OpenAIRealtimeTool",
10
9
  "Realtime",
10
+ "async_input",
11
11
  "record",
12
12
  "record_as_stream",
13
13
  ]
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import Any, Literal
4
4
 
5
- from jiter import jiter
5
+ import jiter
6
6
  from pydantic.json_schema import SkipJsonSchema
7
7
  from typing_extensions import NotRequired, TypedDict
8
8
 
@@ -13,12 +13,12 @@ from .base import (
13
13
 
14
14
  __all__ = [
15
15
  "BaseChunker",
16
- "TextChunker",
17
16
  "BaseEmbedder",
18
17
  "BaseEmbeddingParams",
19
18
  "BaseEmbeddingResponse",
20
19
  "BaseQueryResults",
21
- "BaseVectorStoreParams",
22
20
  "BaseVectorStore",
21
+ "BaseVectorStoreParams",
23
22
  "Document",
23
+ "TextChunker",
24
24
  ]
@@ -11,12 +11,12 @@ from .vectorstores import BaseVectorStore
11
11
 
12
12
  __all__ = [
13
13
  "BaseChunker",
14
- "TextChunker",
15
14
  "BaseEmbedder",
16
15
  "BaseEmbeddingParams",
17
16
  "BaseEmbeddingResponse",
18
17
  "BaseQueryResults",
19
- "BaseVectorStoreParams",
20
18
  "BaseVectorStore",
19
+ "BaseVectorStoreParams",
21
20
  "Document",
21
+ "TextChunker",
22
22
  ]
@@ -3,4 +3,4 @@
3
3
  from .types import WeaviateParams, WeaviateSettings
4
4
  from .vectorstores import WeaviateVectorStore
5
5
 
6
- __all__ = ["WeaviateSettings", "WeaviateParams", "WeaviateVectorStore"]
6
+ __all__ = ["WeaviateParams", "WeaviateSettings", "WeaviateVectorStore"]
@@ -4,14 +4,25 @@ from contextlib import suppress
4
4
 
5
5
  from . import base
6
6
  from .base import (
7
+ AudioPart,
8
+ AudioURLPart,
9
+ BaseCallResponse,
7
10
  BaseDynamicConfig,
8
11
  BaseMessageParam,
9
12
  BasePrompt,
13
+ BaseStream,
10
14
  BaseTool,
11
15
  BaseToolKit,
16
+ CacheControlPart,
17
+ DocumentPart,
12
18
  FromCallArgs,
19
+ ImagePart,
20
+ ImageURLPart,
13
21
  Messages,
14
22
  ResponseModelConfigDict,
23
+ TextPart,
24
+ ToolCallPart,
25
+ ToolResultPart,
15
26
  merge_decorators,
16
27
  metadata,
17
28
  prompt_template,
@@ -49,27 +60,39 @@ with suppress(ImportError):
49
60
  from . import azure as azure
50
61
 
51
62
  __all__ = [
52
- "anthropic",
53
- "azure",
54
- "base",
63
+ "AudioPart",
64
+ "AudioURLPart",
65
+ "BaseCallResponse",
66
+ "BaseCallResponse",
55
67
  "BaseDynamicConfig",
56
68
  "BaseMessageParam",
57
69
  "BasePrompt",
70
+ "BaseStream",
58
71
  "BaseTool",
59
72
  "BaseToolKit",
60
- "cohere",
73
+ "CacheControlPart",
74
+ "DocumentPart",
61
75
  "FromCallArgs",
76
+ "ImagePart",
77
+ "ImageURLPart",
78
+ "Messages",
79
+ "ResponseModelConfigDict",
80
+ "TextPart",
81
+ "ToolCallPart",
82
+ "ToolResultPart",
83
+ "anthropic",
84
+ "azure",
85
+ "base",
86
+ "cohere",
62
87
  "gemini",
63
88
  "google",
64
89
  "groq",
65
90
  "litellm",
66
91
  "merge_decorators",
67
- "Messages",
68
92
  "metadata",
69
93
  "mistral",
70
94
  "openai",
71
95
  "prompt_template",
72
- "ResponseModelConfigDict",
73
96
  "toolkit_tool",
74
97
  "vertex",
75
98
  ]
@@ -17,15 +17,15 @@ from .tool import AnthropicTool, AnthropicToolConfig
17
17
  AnthropicMessageParam: TypeAlias = MessageParam | BaseMessageParam
18
18
 
19
19
  __all__ = [
20
- "call",
21
- "AsyncAnthropicDynamicConfig",
22
- "AnthropicDynamicConfig",
23
20
  "AnthropicCallParams",
24
21
  "AnthropicCallResponse",
25
22
  "AnthropicCallResponseChunk",
23
+ "AnthropicDynamicConfig",
26
24
  "AnthropicMessageParam",
27
25
  "AnthropicStream",
28
26
  "AnthropicTool",
29
27
  "AnthropicToolConfig",
28
+ "AsyncAnthropicDynamicConfig",
30
29
  "anthropic_call",
30
+ "call",
31
31
  ]
@@ -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 = "claude-3-haiku-20240229",
8
9
  ) -> float | None:
@@ -10,112 +11,178 @@ def calculate_cost(
10
11
 
11
12
  https://www.anthropic.com/api
12
13
 
13
- claude-instant-1.2 $0.80 / 1M tokens $2.40 / 1M tokens
14
- claude-2.0 $8.00 / 1M tokens $24.00 / 1M tokens
15
- claude-2.1 $8.00 / 1M tokens $24.00 / 1M tokens
16
- claude-3-haiku $0.25 / 1M tokens $1.25 / 1M tokens
17
- claude-3-sonnet $3.00 / 1M tokens $15.00 / 1M tokens
18
- claude-3-opus $15.00 / 1M tokens $75.00 / 1M tokens
14
+ Model Input Cached Output
15
+ claude-3-5-haiku $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
16
+ claude-3-5-haiku-20241022 $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
17
+ claude-3-5-sonnet $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
18
+ claude-3-5-sonnet-20241022 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
19
+ claude-3-5-sonnet-20240620 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
20
+ claude-3-haiku $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
21
+ claude-3-haiku-20240307 $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
22
+ claude-3-sonnet $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
23
+ claude-3-sonnet-20240620 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
24
+ claude-3-opus $15.00 / 1M tokens $1.50 / 1M tokens $75.00 / 1M tokens
25
+ claude-3-opus-20240229 $15.00 / 1M tokens $1.50 / 1M tokens $75.00 / 1M tokens
26
+ claude-2.1 $8.00 / 1M tokens $24.00 / 1M tokens
27
+ claude-2.0 $8.00 / 1M tokens $24.00 / 1M tokens
28
+ claude-instant-1.2 $0.80 / 1M tokens $2.40 / 1M tokens
29
+ anthropic.claude-3-5-sonnet-20241022-v2:0 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
30
+ anthropic.claude-3-5-sonnet-20241022-v1:0 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
31
+ anthropic.claude-3-5-haiku-20241022-v1:0 $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
32
+ anthropic.claude-3-sonnet-20240620-v1:0 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
33
+ anthropic.claude-3-haiku-20240307-v1:0 $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
34
+ anthropic.claude-3-opus-20240229-v1:0 $15.00 / 1M tokens $1.50 / 1M tokens $75.00 / 1M tokens
35
+ claude-3-5-sonnet@20241022 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
36
+ claude-3-5-haiku@20241022 $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
37
+ claude-3-sonnet@20240620 $3.00 / 1M tokens $0.30 / 1M tokens $15.00 / 1M tokens
38
+ claude-3-haiku@20240307 $0.80 / 1M tokens $0.08 / 1M tokens $4.00 / 1M tokens
39
+ claude-3-opus@20240229 $15.00 / 1M tokens $1.50 / 1M tokens $75.00 / 1M tokens
19
40
  """
20
41
  pricing = {
21
- "claude-instant-1.2": {
42
+ # Anthropic models
43
+ "claude-3-5-haiku": {
22
44
  "prompt": 0.000_000_8,
23
- "completion": 0.000_002_4,
24
- },
25
- "claude-2.0": {
26
- "prompt": 0.000_008,
27
- "completion": 0.000_024,
28
- },
29
- "claude-2.1": {
30
- "prompt": 0.000_008,
31
- "completion": 0.000_024,
32
- },
33
- "claude-3-haiku-20240307": {
34
- "prompt": 0.000_002_5,
35
- "completion": 0.000_012_5,
45
+ "completion": 0.000_004,
46
+ "cached": 0.000_000_08,
36
47
  },
37
48
  "claude-3-5-haiku-20241022": {
38
- "prompt": 0.000_008,
49
+ "prompt": 0.000_000_8,
39
50
  "completion": 0.000_004,
51
+ "cached": 0.000_000_08,
40
52
  },
41
- "claude-3-sonnet-20240229": {
53
+ "claude-3-5-sonnet": {
42
54
  "prompt": 0.000_003,
43
55
  "completion": 0.000_015,
44
- },
45
- "claude-3-opus-20240229": {
46
- "prompt": 0.000_015,
47
- "completion": 0.000_075,
56
+ "cached": 0.000_000_3,
48
57
  },
49
58
  "claude-3-5-sonnet-20241022": {
50
59
  "prompt": 0.000_003,
51
60
  "completion": 0.000_015,
61
+ "cached": 0.000_000_3,
52
62
  },
53
63
  "claude-3-5-sonnet-20240620": {
54
64
  "prompt": 0.000_003,
55
65
  "completion": 0.000_015,
66
+ "cached": 0.000_000_3,
56
67
  },
57
- # Bedrock models
58
- "anthropic.claude-3-haiku-20240307-v1:0": {
59
- "prompt": 0.000_002_5,
60
- "completion": 0.000_012_5,
68
+ "claude-3-haiku": {
69
+ "prompt": 0.000_000_8,
70
+ "completion": 0.000_004,
71
+ "cached": 0.000_000_08,
61
72
  },
62
- "anthropic.claude-3-5-haiku-20241022-v1:0": {
63
- "prompt": 0.000_008,
73
+ "claude-3-haiku-20240307": {
74
+ "prompt": 0.000_000_8,
64
75
  "completion": 0.000_004,
76
+ "cached": 0.000_000_08,
65
77
  },
66
- "anthropic.claude-3-sonnet-20240229-v1:0": {
78
+ "claude-3-sonnet": {
67
79
  "prompt": 0.000_003,
68
80
  "completion": 0.000_015,
81
+ "cached": 0.000_000_3,
69
82
  },
70
- "anthropic.claude-3-opus-20240229-v1:0": {
83
+ "claude-3-sonnet-20240620": {
84
+ "prompt": 0.000_003,
85
+ "completion": 0.000_015,
86
+ "cached": 0.000_000_3,
87
+ },
88
+ "claude-3-opus": {
89
+ "prompt": 0.000_015,
90
+ "completion": 0.000_075,
91
+ "cached": 0.000_001_5,
92
+ },
93
+ "claude-3-opus-20240229": {
71
94
  "prompt": 0.000_015,
72
95
  "completion": 0.000_075,
96
+ "cached": 0.000_001_5,
97
+ },
98
+ "claude-2.1": {
99
+ "prompt": 0.000_008,
100
+ "completion": 0.000_024,
101
+ "cached": 0,
73
102
  },
74
- "anthropic.claude-3-5-sonnet-20240620-v1:0": {
103
+ "claude-2.0": {
104
+ "prompt": 0.000_008,
105
+ "completion": 0.000_024,
106
+ "cached": 0,
107
+ },
108
+ "claude-instant-1.2": {
109
+ "prompt": 0.000_000_8,
110
+ "completion": 0.000_002_4,
111
+ "cached": 0,
112
+ },
113
+ # Bedrock models
114
+ "anthropic.claude-3-5-sonnet-20241022-v2:0": {
75
115
  "prompt": 0.000_003,
76
116
  "completion": 0.000_015,
117
+ "cached": 0.000_000_3,
77
118
  },
78
119
  "anthropic.claude-3-5-sonnet-20241022-v1:0": {
79
120
  "prompt": 0.000_003,
80
121
  "completion": 0.000_015,
122
+ "cached": 0.000_000_3,
81
123
  },
82
- # Vertex AI models
83
- "claude-3-haiku@20240307": {
84
- "prompt": 0.000_002_5,
85
- "completion": 0.000_012_5,
86
- },
87
- "claude-3-5-haiku@20241022": {
88
- "prompt": 0.000_008,
124
+ "anthropic.claude-3-5-haiku-20241022-v1:0": {
125
+ "prompt": 0.000_000_8,
89
126
  "completion": 0.000_004,
127
+ "cached": 0.000_000_08,
90
128
  },
91
- "claude-3-sonnet@20240229": {
129
+ "anthropic.claude-3-sonnet-20240620-v1:0": {
92
130
  "prompt": 0.000_003,
93
131
  "completion": 0.000_015,
132
+ "cached": 0.000_000_3,
94
133
  },
95
- "claude-3-opus@20240229": {
134
+ "anthropic.claude-3-haiku-20240307-v1:0": {
135
+ "prompt": 0.000_000_8,
136
+ "completion": 0.000_004,
137
+ "cached": 0.000_000_08,
138
+ },
139
+ "anthropic.claude-3-opus-20240229-v1:0": {
96
140
  "prompt": 0.000_015,
97
141
  "completion": 0.000_075,
142
+ "cached": 0.000_001_5,
98
143
  },
99
- "claude-3-5-sonnet@20240620": {
144
+ # Vertex AI models
145
+ "claude-3-5-sonnet@20241022": {
100
146
  "prompt": 0.000_003,
101
147
  "completion": 0.000_015,
148
+ "cached": 0.000_000_3,
102
149
  },
103
- "claude-3-5-sonnet@20241022": {
150
+ "claude-3-5-haiku@20241022": {
151
+ "prompt": 0.000_000_8,
152
+ "completion": 0.000_004,
153
+ "cached": 0.000_000_08,
154
+ },
155
+ "claude-3-sonnet@20240620": {
104
156
  "prompt": 0.000_003,
105
157
  "completion": 0.000_015,
158
+ "cached": 0.000_000_3,
159
+ },
160
+ "claude-3-haiku@20240307": {
161
+ "prompt": 0.000_000_8,
162
+ "completion": 0.000_004,
163
+ "cached": 0.000_000_08,
164
+ },
165
+ "claude-3-opus@20240229": {
166
+ "prompt": 0.000_015,
167
+ "completion": 0.000_075,
168
+ "cached": 0.000_001_5,
106
169
  },
107
170
  }
108
171
 
109
172
  if input_tokens is None or output_tokens is None:
110
173
  return None
111
174
 
175
+ if cached_tokens is None:
176
+ cached_tokens = 0
177
+
112
178
  try:
113
179
  model_pricing = pricing[model]
114
180
  except KeyError:
115
181
  return None
116
182
 
117
183
  prompt_cost = input_tokens * model_pricing["prompt"]
184
+ cached_cost = cached_tokens * model_pricing["cached"]
118
185
  completion_cost = output_tokens * model_pricing["completion"]
119
- total_cost = prompt_cost + completion_cost
186
+ total_cost = prompt_cost + cached_cost + completion_cost
120
187
 
121
188
  return total_cost
@@ -100,6 +100,12 @@ class AnthropicCallResponse(
100
100
  """Returns the number of input tokens."""
101
101
  return self.usage.input_tokens
102
102
 
103
+ @computed_field
104
+ @property
105
+ def cached_tokens(self) -> int:
106
+ """Returns the number of cached tokens."""
107
+ return getattr(self.usage, "cache_read_input_tokens", 0)
108
+
103
109
  @computed_field
104
110
  @property
105
111
  def output_tokens(self) -> int:
@@ -110,7 +116,9 @@ class AnthropicCallResponse(
110
116
  @property
111
117
  def cost(self) -> float | None:
112
118
  """Returns the cost of the call."""
113
- return calculate_cost(self.input_tokens, self.output_tokens, self.model)
119
+ return calculate_cost(
120
+ self.input_tokens, self.cached_tokens, self.output_tokens, self.model
121
+ )
114
122
 
115
123
  @computed_field
116
124
  @cached_property
@@ -118,7 +126,6 @@ class AnthropicCallResponse(
118
126
  """Returns the assistants's response as a message parameter."""
119
127
  return MessageParam(**self.response.model_dump(include={"content", "role"}))
120
128
 
121
- @computed_field
122
129
  @cached_property
123
130
  def tools(self) -> list[AnthropicTool] | None:
124
131
  """Returns any available tool calls as their `AnthropicTool` definition.
@@ -140,7 +147,6 @@ class AnthropicCallResponse(
140
147
 
141
148
  return extracted_tools
142
149
 
143
- @computed_field
144
150
  @cached_property
145
151
  def tool(self) -> AnthropicTool | None:
146
152
  """Returns the 0th tool for the 0th choice message.
@@ -100,6 +100,13 @@ class AnthropicCallResponseChunk(
100
100
  return usage.input_tokens
101
101
  return None
102
102
 
103
+ @property
104
+ def cached_tokens(self) -> int | None:
105
+ """Returns the number of cached tokens."""
106
+ if (usage := self.usage) and isinstance(usage, Usage):
107
+ return getattr(usage, "cache_read_input_tokens", 0)
108
+ return None
109
+
103
110
  @property
104
111
  def output_tokens(self) -> int | None:
105
112
  """Returns the number of output tokens."""
@@ -67,7 +67,9 @@ class AnthropicStream(
67
67
  @property
68
68
  def cost(self) -> float | None:
69
69
  """Returns the cost of the call."""
70
- return calculate_cost(self.input_tokens, self.output_tokens, self.model)
70
+ return calculate_cost(
71
+ self.input_tokens, self.cached_tokens, self.output_tokens, self.model
72
+ )
71
73
 
72
74
  def _construct_message_param(
73
75
  self, tool_calls: list[ToolUseBlock] | None = None, content: str | None = None
@@ -18,14 +18,14 @@ AzureMessageParam: TypeAlias = ChatRequestMessage | BaseMessageParam
18
18
 
19
19
  __all__ = [
20
20
  "AsyncAzureDynamicConfig",
21
- "call",
22
- "AzureDynamicConfig",
23
21
  "AzureCallParams",
24
22
  "AzureCallResponse",
25
23
  "AzureCallResponseChunk",
24
+ "AzureDynamicConfig",
26
25
  "AzureMessageParam",
27
26
  "AzureStream",
28
27
  "AzureTool",
29
28
  "AzureToolConfig",
30
29
  "azure_call",
30
+ "call",
31
31
  ]
@@ -2,7 +2,10 @@
2
2
 
3
3
 
4
4
  def calculate_cost(
5
- input_tokens: int | float | None, output_tokens: int | float | None, model: str
5
+ input_tokens: int | float | None,
6
+ cached_tokens: int | float | None,
7
+ output_tokens: int | float | None,
8
+ model: str,
6
9
  ) -> float | None:
7
10
  """Calculate the cost of a completion using the Azure API."""
8
11
  return None
@@ -104,6 +104,12 @@ class AzureCallResponse(
104
104
  """Returns the number of input tokens."""
105
105
  return self.usage.prompt_tokens if self.usage else None
106
106
 
107
+ @computed_field
108
+ @property
109
+ def cached_tokens(self) -> int | None:
110
+ """Returns the number of cached tokens."""
111
+ return None
112
+
107
113
  @computed_field
108
114
  @property
109
115
  def output_tokens(self) -> int | None:
@@ -114,7 +120,9 @@ class AzureCallResponse(
114
120
  @property
115
121
  def cost(self) -> float | None:
116
122
  """Returns the cost of the call."""
117
- return calculate_cost(self.input_tokens, self.output_tokens, self.model)
123
+ return calculate_cost(
124
+ self.input_tokens, self.cached_tokens, self.output_tokens, self.model
125
+ )
118
126
 
119
127
  @computed_field
120
128
  @cached_property
@@ -125,7 +133,6 @@ class AzureCallResponse(
125
133
  content=message_param.content, tool_calls=message_param.tool_calls
126
134
  )
127
135
 
128
- @computed_field
129
136
  @cached_property
130
137
  def tools(self) -> list[AzureTool] | None:
131
138
  """Returns any available tool calls as their `AzureTool` definition.
@@ -149,7 +156,6 @@ class AzureCallResponse(
149
156
 
150
157
  return extracted_tools
151
158
 
152
- @computed_field
153
159
  @cached_property
154
160
  def tool(self) -> AzureTool | None:
155
161
  """Returns the 0th tool for the 0th choice message.
@@ -84,6 +84,11 @@ class AzureCallResponseChunk(
84
84
  """Returns the number of input tokens."""
85
85
  return self.usage.prompt_tokens
86
86
 
87
+ @property
88
+ def cached_tokens(self) -> int:
89
+ """Returns the number of cached tokens."""
90
+ return 0
91
+
87
92
  @property
88
93
  def output_tokens(self) -> int:
89
94
  """Returns the number of output tokens."""
@@ -69,7 +69,9 @@ class AzureStream(
69
69
  @property
70
70
  def cost(self) -> float | None:
71
71
  """Returns the cost of the call."""
72
- return calculate_cost(self.input_tokens, self.output_tokens, self.model)
72
+ return calculate_cost(
73
+ self.input_tokens, self.cached_tokens, self.output_tokens, self.model
74
+ )
73
75
 
74
76
  def _construct_message_param(
75
77
  self,
@@ -30,12 +30,12 @@ from .stream import BaseStream
30
30
  from .structured_stream import BaseStructuredStream
31
31
  from .tool import BaseTool, GenerateJsonSchemaNoTitles, ToolConfig
32
32
  from .toolkit import BaseToolKit, toolkit_tool
33
- from .types import AudioSegment
33
+ from .types import AudioSegment, JsonableType, Usage
34
34
 
35
35
  __all__ = [
36
36
  "AudioPart",
37
- "AudioURLPart",
38
37
  "AudioSegment",
38
+ "AudioURLPart",
39
39
  "BaseCallKwargs",
40
40
  "BaseCallParams",
41
41
  "BaseCallResponse",
@@ -49,25 +49,27 @@ __all__ = [
49
49
  "BaseToolKit",
50
50
  "BaseType",
51
51
  "CacheControlPart",
52
- "call_factory",
53
52
  "CommonCallParams",
54
53
  "DocumentPart",
55
54
  "FromCallArgs",
56
55
  "GenerateJsonSchemaNoTitles",
57
56
  "ImagePart",
58
57
  "ImageURLPart",
59
- "merge_decorators",
60
- "metadata",
58
+ "JsonableType",
61
59
  "Messages",
62
60
  "Metadata",
63
- "prompt_template",
64
61
  "ResponseModelConfigDict",
65
62
  "TextPart",
66
- "ToolConfig",
67
63
  "ToolCallPart",
64
+ "ToolConfig",
68
65
  "ToolResultPart",
69
- "toolkit_tool",
70
- "transform_tool_outputs",
66
+ "Usage",
71
67
  "_partial",
72
68
  "_utils",
69
+ "call_factory",
70
+ "merge_decorators",
71
+ "metadata",
72
+ "prompt_template",
73
+ "toolkit_tool",
74
+ "transform_tool_outputs",
73
75
  ]