11
11
else :
12
12
GenerateContentContentListUnionDict = Any
13
13
14
+
14
15
class GoogleAIStudioTokenCounter :
16
+ def _clean_contents_for_gemini_api (self , contents : Any ) -> Any :
17
+ """
18
+ Clean up contents to remove unsupported fields for the Gemini API.
19
+
20
+ The Google Gemini API doesn't recognize the 'id' field in function responses,
21
+ so we need to remove it to prevent 400 Bad Request errors.
22
+
23
+ Args:
24
+ contents: The contents to clean up
25
+
26
+ Returns:
27
+ Cleaned contents with unsupported fields removed
28
+ """
29
+ import copy
30
+
31
+ from google .genai .types import FunctionResponse
32
+
33
+ cleaned_contents = copy .deepcopy (contents )
34
+
35
+ for content in cleaned_contents :
36
+ parts = content ["parts" ]
37
+ for part in parts :
38
+ if "functionResponse" in part :
39
+ function_response_data = part ["functionResponse" ]
40
+ function_response_part = FunctionResponse (** function_response_data )
41
+ function_response_part .id = None
42
+ part ["functionResponse" ] = function_response_part .model_dump (
43
+ exclude_none = True
44
+ )
45
+
46
+ return cleaned_contents
15
47
16
48
def _construct_url (self , model : str , api_base : Optional [str ] = None ) -> str :
17
49
"""
@@ -20,7 +52,6 @@ def _construct_url(self, model: str, api_base: Optional[str] = None) -> str:
20
52
base_url = api_base or "https://generativelanguage.googleapis.com"
21
53
return f"{ base_url } /v1beta/models/{ model } :countTokens"
22
54
23
-
24
55
async def validate_environment (
25
56
self ,
26
57
api_base : Optional [str ] = None ,
@@ -33,7 +64,8 @@ async def validate_environment(
33
64
Returns a Tuple of headers and url for the Google Gen AI Studio countTokens endpoint.
34
65
"""
35
66
from litellm .llms .gemini .google_genai .transformation import GoogleGenAIConfig
36
- headers = GoogleGenAIConfig ().validate_environment (
67
+
68
+ headers = GoogleGenAIConfig ().validate_environment (
37
69
api_key = api_key ,
38
70
headers = headers ,
39
71
model = model ,
@@ -54,7 +86,7 @@ async def acount_tokens(
54
86
) -> Dict [str , Any ]:
55
87
"""
56
88
Count tokens using Google Gen AI Studio countTokens endpoint.
57
-
89
+
58
90
Args:
59
91
contents: The content to count tokens for (Google Gen AI format)
60
92
Example: [{"parts": [{"text": "Hello world"}]}]
@@ -63,7 +95,7 @@ async def acount_tokens(
63
95
api_base: Optional API base URL (defaults to Google Gen AI Studio)
64
96
timeout: Optional timeout for the request
65
97
**kwargs: Additional parameters
66
-
98
+
67
99
Returns:
68
100
Dict containing token count information from Google Gen AI Studio API.
69
101
Example response:
@@ -77,14 +109,13 @@ async def acount_tokens(
77
109
}
78
110
]
79
111
}
80
-
112
+
81
113
Raises:
82
114
ValueError: If API key is missing
83
115
litellm.APIError: If the API call fails
84
116
litellm.APIConnectionError: If the connection fails
85
117
Exception: For any other unexpected errors
86
118
"""
87
- # Set up API base URL
88
119
89
120
# Prepare headers
90
121
headers , url = await self .validate_environment (
@@ -94,44 +125,39 @@ async def acount_tokens(
94
125
model = model ,
95
126
litellm_params = kwargs ,
96
127
)
97
-
98
- # Prepare request body
99
- request_body = {
100
- "contents" : contents
101
- }
102
-
128
+
129
+ # Prepare request body - clean up contents to remove unsupported fields
130
+ cleaned_contents = self ._clean_contents_for_gemini_api (contents )
131
+ request_body = {"contents" : cleaned_contents }
132
+
103
133
async_httpx_client = get_async_httpx_client (
104
134
llm_provider = LlmProviders .GEMINI ,
105
135
)
106
136
107
137
try :
108
138
response = await async_httpx_client .post (
109
- url = url ,
110
- headers = headers ,
111
- json = request_body
139
+ url = url , headers = headers , json = request_body
112
140
)
113
-
141
+
114
142
# Check for HTTP errors
115
143
response .raise_for_status ()
116
-
144
+
117
145
# Parse response
118
146
result = response .json ()
119
147
return result
120
-
148
+
121
149
except httpx .HTTPStatusError as e :
122
150
error_msg = f"Google Gen AI Studio API error: { e .response .status_code } - { e .response .text } "
123
151
raise litellm .APIError (
124
152
message = error_msg ,
125
153
llm_provider = "gemini" ,
126
154
model = model ,
127
- status_code = e .response .status_code
155
+ status_code = e .response .status_code ,
128
156
) from e
129
157
except httpx .RequestError as e :
130
158
error_msg = f"Request to Google Gen AI Studio failed: { str (e )} "
131
159
raise litellm .APIConnectionError (
132
- message = error_msg ,
133
- llm_provider = "gemini" ,
134
- model = model
160
+ message = error_msg , llm_provider = "gemini" , model = model
135
161
) from e
136
162
except Exception as e :
137
163
error_msg = f"Unexpected error during token counting: { str (e )} "
0 commit comments