google-genai 0.7.0__tar.gz → 1.0.0__tar.gz
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.
- {google_genai-0.7.0/google_genai.egg-info → google_genai-1.0.0}/PKG-INFO +90 -48
- {google_genai-0.7.0 → google_genai-1.0.0}/README.md +89 -47
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_api_client.py +26 -25
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_automatic_function_calling_util.py +19 -20
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_common.py +33 -2
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_extra_utils.py +12 -6
- google_genai-1.0.0/google/genai/_operations.py +365 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_replay_api_client.py +7 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_transformers.py +32 -14
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/errors.py +4 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/files.py +79 -71
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/live.py +5 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/models.py +344 -35
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/tunings.py +288 -61
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/types.py +191 -20
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/version.py +1 -1
- {google_genai-0.7.0 → google_genai-1.0.0/google_genai.egg-info}/PKG-INFO +90 -48
- {google_genai-0.7.0 → google_genai-1.0.0}/google_genai.egg-info/SOURCES.txt +1 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/pyproject.toml +1 -1
- {google_genai-0.7.0 → google_genai-1.0.0}/LICENSE +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/__init__.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_api_module.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/_test_api_client.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/batches.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/caches.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/chats.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/client.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google/genai/pagers.py +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google_genai.egg-info/dependency_links.txt +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google_genai.egg-info/requires.txt +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/google_genai.egg-info/top_level.txt +0 -0
- {google_genai-0.7.0 → google_genai-1.0.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: google-genai
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0
|
4
4
|
Summary: GenAI Python SDK
|
5
5
|
Author-email: Google LLC <googleapis-packages@google.com>
|
6
6
|
License: Apache-2.0
|
@@ -34,7 +34,7 @@ Requires-Dist: websockets<15.0dev,>=13.0
|
|
34
34
|
|
35
35
|
-----
|
36
36
|
|
37
|
-
Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) APIs.
|
37
|
+
Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) APIs.
|
38
38
|
|
39
39
|
## Installation
|
40
40
|
|
@@ -66,6 +66,23 @@ client = genai.Client(
|
|
66
66
|
)
|
67
67
|
```
|
68
68
|
|
69
|
+
To set the API version use `http_options`. For example, to set the API version
|
70
|
+
to `v1` for Vertex AI:
|
71
|
+
|
72
|
+
```python
|
73
|
+
client = genai.Client(
|
74
|
+
vertexai=True, project='your-project-id', location='us-central1',
|
75
|
+
http_options={'api_version': 'v1'}
|
76
|
+
)
|
77
|
+
```
|
78
|
+
|
79
|
+
To set the API version to `v1alpha` for the Gemini API:
|
80
|
+
|
81
|
+
```python
|
82
|
+
client = genai.Client(api_key='GEMINI_API_KEY',
|
83
|
+
http_options={'api_version': 'v1alpha'})
|
84
|
+
```
|
85
|
+
|
69
86
|
## Types
|
70
87
|
|
71
88
|
Parameter types can be specified as either dictionaries(`TypedDict`) or
|
@@ -97,9 +114,10 @@ download the file in console.
|
|
97
114
|
python code.
|
98
115
|
|
99
116
|
```python
|
100
|
-
file = client.files.upload(path="a11.
|
117
|
+
file = client.files.upload(path="a11.txt")
|
101
118
|
response = client.models.generate_content(
|
102
|
-
model="gemini-2.0-flash-exp",
|
119
|
+
model="gemini-2.0-flash-exp",
|
120
|
+
contents=["Could you summarize this file?", file]
|
103
121
|
)
|
104
122
|
print(response.text)
|
105
123
|
```
|
@@ -143,53 +161,17 @@ response = client.models.generate_content(
|
|
143
161
|
print(response.text)
|
144
162
|
```
|
145
163
|
|
146
|
-
### Thinking
|
147
|
-
|
148
|
-
The Gemini 2.0 Flash Thinking model is an experimental model that could return
|
149
|
-
"thoughts" as part of its response.
|
150
|
-
|
151
|
-
#### Gemini Developer API
|
152
|
-
|
153
|
-
Thinking config is only available in v1alpha for Gemini AI API.
|
154
|
-
|
155
|
-
```python
|
156
|
-
response = client.models.generate_content(
|
157
|
-
model='gemini-2.0-flash-thinking-exp',
|
158
|
-
contents='What is the sum of natural numbers from 1 to 100?',
|
159
|
-
config=types.GenerateContentConfig(
|
160
|
-
thinking_config=types.ThinkingConfig(include_thoughts=True),
|
161
|
-
http_options=types.HttpOptions(api_version='v1alpha'),
|
162
|
-
)
|
163
|
-
)
|
164
|
-
for part in response.candidates[0].content.parts:
|
165
|
-
print(part)
|
166
|
-
```
|
167
|
-
|
168
|
-
#### Vertex AI API
|
169
|
-
|
170
|
-
```python
|
171
|
-
response = client.models.generate_content(
|
172
|
-
model='gemini-2.0-flash-thinking-exp-01-21',
|
173
|
-
contents='What is the sum of natural numbers from 1 to 100?',
|
174
|
-
config=types.GenerateContentConfig(
|
175
|
-
thinking_config=types.ThinkingConfig(include_thoughts=True),
|
176
|
-
)
|
177
|
-
)
|
178
|
-
for part in response.candidates[0].content.parts:
|
179
|
-
print(part)
|
180
|
-
```
|
181
|
-
|
182
164
|
### List Base Models
|
183
165
|
|
184
166
|
To retrieve tuned models, see [list tuned models](#list-tuned-models).
|
185
167
|
|
186
168
|
```python
|
187
|
-
for model in client.models.list(
|
169
|
+
for model in client.models.list():
|
188
170
|
print(model)
|
189
171
|
```
|
190
172
|
|
191
173
|
```python
|
192
|
-
pager = client.models.list(config={"page_size": 10
|
174
|
+
pager = client.models.list(config={"page_size": 10})
|
193
175
|
print(pager.page_size)
|
194
176
|
print(pager[0])
|
195
177
|
pager.next_page()
|
@@ -199,12 +181,12 @@ print(pager[0])
|
|
199
181
|
#### Async
|
200
182
|
|
201
183
|
```python
|
202
|
-
async for job in await client.aio.models.list(
|
184
|
+
async for job in await client.aio.models.list():
|
203
185
|
print(job)
|
204
186
|
```
|
205
187
|
|
206
188
|
```python
|
207
|
-
async_pager = await client.aio.models.list(config={"page_size": 10
|
189
|
+
async_pager = await client.aio.models.list(config={"page_size": 10})
|
208
190
|
print(async_pager.page_size)
|
209
191
|
print(async_pager[0])
|
210
192
|
await async_pager.next_page()
|
@@ -337,6 +319,66 @@ response = client.models.generate_content(
|
|
337
319
|
print(response.text)
|
338
320
|
```
|
339
321
|
|
322
|
+
#### Function calling with `ANY` tools config mode
|
323
|
+
|
324
|
+
If you configure function calling mode to be `ANY`, then the model will always
|
325
|
+
return function call parts. If you also pass a python function as a tool, by
|
326
|
+
default the SDK will perform automatic function calling until the remote calls exceed the
|
327
|
+
maximum remote call for automatic function calling (default to 10 times).
|
328
|
+
|
329
|
+
If you'd like to disable automatic function calling in `ANY` mode:
|
330
|
+
|
331
|
+
```python
|
332
|
+
def get_current_weather(location: str) -> str:
|
333
|
+
"""Returns the current weather.
|
334
|
+
|
335
|
+
Args:
|
336
|
+
location: The city and state, e.g. San Francisco, CA
|
337
|
+
"""
|
338
|
+
return "sunny"
|
339
|
+
|
340
|
+
response = client.models.generate_content(
|
341
|
+
model="gemini-2.0-flash-exp",
|
342
|
+
contents="What is the weather like in Boston?",
|
343
|
+
config=types.GenerateContentConfig(
|
344
|
+
tools=[get_current_weather],
|
345
|
+
automatic_function_calling=types.AutomaticFunctionCallingConfig(
|
346
|
+
disable=True
|
347
|
+
),
|
348
|
+
tool_config=types.ToolConfig(
|
349
|
+
function_calling_config=types.FunctionCallingConfig(mode='ANY')
|
350
|
+
),
|
351
|
+
),
|
352
|
+
)
|
353
|
+
```
|
354
|
+
|
355
|
+
If you'd like to set `x` number of automatic function call turns, you can
|
356
|
+
configure the maximum remote calls to be `x + 1`.
|
357
|
+
Assuming you prefer `1` turn for automatic function calling.
|
358
|
+
|
359
|
+
```python
|
360
|
+
def get_current_weather(location: str) -> str:
|
361
|
+
"""Returns the current weather.
|
362
|
+
|
363
|
+
Args:
|
364
|
+
location: The city and state, e.g. San Francisco, CA
|
365
|
+
"""
|
366
|
+
return "sunny"
|
367
|
+
|
368
|
+
response = client.models.generate_content(
|
369
|
+
model="gemini-2.0-flash-exp",
|
370
|
+
contents="What is the weather like in Boston?",
|
371
|
+
config=types.GenerateContentConfig(
|
372
|
+
tools=[get_current_weather],
|
373
|
+
automatic_function_calling=types.AutomaticFunctionCallingConfig(
|
374
|
+
maximum_remote_calls=2
|
375
|
+
),
|
376
|
+
tool_config=types.ToolConfig(
|
377
|
+
function_calling_config=types.FunctionCallingConfig(mode='ANY')
|
378
|
+
),
|
379
|
+
),
|
380
|
+
)
|
381
|
+
```
|
340
382
|
### JSON Response Schema
|
341
383
|
|
342
384
|
#### Pydantic Model Schema support
|
@@ -863,12 +905,12 @@ print(tuned_model)
|
|
863
905
|
To retrieve base models, see [list base models](#list-base-models).
|
864
906
|
|
865
907
|
```python
|
866
|
-
for model in client.models.list(config={"page_size": 10}):
|
908
|
+
for model in client.models.list(config={"page_size": 10, "query_base": False}):
|
867
909
|
print(model)
|
868
910
|
```
|
869
911
|
|
870
912
|
```python
|
871
|
-
pager = client.models.list(config={"page_size": 10})
|
913
|
+
pager = client.models.list(config={"page_size": 10, "query_base": False})
|
872
914
|
print(pager.page_size)
|
873
915
|
print(pager[0])
|
874
916
|
pager.next_page()
|
@@ -878,12 +920,12 @@ print(pager[0])
|
|
878
920
|
#### Async
|
879
921
|
|
880
922
|
```python
|
881
|
-
async for job in await client.aio.models.list(config={"page_size": 10}):
|
923
|
+
async for job in await client.aio.models.list(config={"page_size": 10, "query_base": False}):
|
882
924
|
print(job)
|
883
925
|
```
|
884
926
|
|
885
927
|
```python
|
886
|
-
async_pager = await client.aio.models.list(config={"page_size": 10})
|
928
|
+
async_pager = await client.aio.models.list(config={"page_size": 10, "query_base": False})
|
887
929
|
print(async_pager.page_size)
|
888
930
|
print(async_pager[0])
|
889
931
|
await async_pager.next_page()
|
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
-----
|
9
9
|
|
10
|
-
Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) APIs.
|
10
|
+
Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) APIs.
|
11
11
|
|
12
12
|
## Installation
|
13
13
|
|
@@ -39,6 +39,23 @@ client = genai.Client(
|
|
39
39
|
)
|
40
40
|
```
|
41
41
|
|
42
|
+
To set the API version use `http_options`. For example, to set the API version
|
43
|
+
to `v1` for Vertex AI:
|
44
|
+
|
45
|
+
```python
|
46
|
+
client = genai.Client(
|
47
|
+
vertexai=True, project='your-project-id', location='us-central1',
|
48
|
+
http_options={'api_version': 'v1'}
|
49
|
+
)
|
50
|
+
```
|
51
|
+
|
52
|
+
To set the API version to `v1alpha` for the Gemini API:
|
53
|
+
|
54
|
+
```python
|
55
|
+
client = genai.Client(api_key='GEMINI_API_KEY',
|
56
|
+
http_options={'api_version': 'v1alpha'})
|
57
|
+
```
|
58
|
+
|
42
59
|
## Types
|
43
60
|
|
44
61
|
Parameter types can be specified as either dictionaries(`TypedDict`) or
|
@@ -70,9 +87,10 @@ download the file in console.
|
|
70
87
|
python code.
|
71
88
|
|
72
89
|
```python
|
73
|
-
file = client.files.upload(path="a11.
|
90
|
+
file = client.files.upload(path="a11.txt")
|
74
91
|
response = client.models.generate_content(
|
75
|
-
model="gemini-2.0-flash-exp",
|
92
|
+
model="gemini-2.0-flash-exp",
|
93
|
+
contents=["Could you summarize this file?", file]
|
76
94
|
)
|
77
95
|
print(response.text)
|
78
96
|
```
|
@@ -116,53 +134,17 @@ response = client.models.generate_content(
|
|
116
134
|
print(response.text)
|
117
135
|
```
|
118
136
|
|
119
|
-
### Thinking
|
120
|
-
|
121
|
-
The Gemini 2.0 Flash Thinking model is an experimental model that could return
|
122
|
-
"thoughts" as part of its response.
|
123
|
-
|
124
|
-
#### Gemini Developer API
|
125
|
-
|
126
|
-
Thinking config is only available in v1alpha for Gemini AI API.
|
127
|
-
|
128
|
-
```python
|
129
|
-
response = client.models.generate_content(
|
130
|
-
model='gemini-2.0-flash-thinking-exp',
|
131
|
-
contents='What is the sum of natural numbers from 1 to 100?',
|
132
|
-
config=types.GenerateContentConfig(
|
133
|
-
thinking_config=types.ThinkingConfig(include_thoughts=True),
|
134
|
-
http_options=types.HttpOptions(api_version='v1alpha'),
|
135
|
-
)
|
136
|
-
)
|
137
|
-
for part in response.candidates[0].content.parts:
|
138
|
-
print(part)
|
139
|
-
```
|
140
|
-
|
141
|
-
#### Vertex AI API
|
142
|
-
|
143
|
-
```python
|
144
|
-
response = client.models.generate_content(
|
145
|
-
model='gemini-2.0-flash-thinking-exp-01-21',
|
146
|
-
contents='What is the sum of natural numbers from 1 to 100?',
|
147
|
-
config=types.GenerateContentConfig(
|
148
|
-
thinking_config=types.ThinkingConfig(include_thoughts=True),
|
149
|
-
)
|
150
|
-
)
|
151
|
-
for part in response.candidates[0].content.parts:
|
152
|
-
print(part)
|
153
|
-
```
|
154
|
-
|
155
137
|
### List Base Models
|
156
138
|
|
157
139
|
To retrieve tuned models, see [list tuned models](#list-tuned-models).
|
158
140
|
|
159
141
|
```python
|
160
|
-
for model in client.models.list(
|
142
|
+
for model in client.models.list():
|
161
143
|
print(model)
|
162
144
|
```
|
163
145
|
|
164
146
|
```python
|
165
|
-
pager = client.models.list(config={"page_size": 10
|
147
|
+
pager = client.models.list(config={"page_size": 10})
|
166
148
|
print(pager.page_size)
|
167
149
|
print(pager[0])
|
168
150
|
pager.next_page()
|
@@ -172,12 +154,12 @@ print(pager[0])
|
|
172
154
|
#### Async
|
173
155
|
|
174
156
|
```python
|
175
|
-
async for job in await client.aio.models.list(
|
157
|
+
async for job in await client.aio.models.list():
|
176
158
|
print(job)
|
177
159
|
```
|
178
160
|
|
179
161
|
```python
|
180
|
-
async_pager = await client.aio.models.list(config={"page_size": 10
|
162
|
+
async_pager = await client.aio.models.list(config={"page_size": 10})
|
181
163
|
print(async_pager.page_size)
|
182
164
|
print(async_pager[0])
|
183
165
|
await async_pager.next_page()
|
@@ -310,6 +292,66 @@ response = client.models.generate_content(
|
|
310
292
|
print(response.text)
|
311
293
|
```
|
312
294
|
|
295
|
+
#### Function calling with `ANY` tools config mode
|
296
|
+
|
297
|
+
If you configure function calling mode to be `ANY`, then the model will always
|
298
|
+
return function call parts. If you also pass a python function as a tool, by
|
299
|
+
default the SDK will perform automatic function calling until the remote calls exceed the
|
300
|
+
maximum remote call for automatic function calling (default to 10 times).
|
301
|
+
|
302
|
+
If you'd like to disable automatic function calling in `ANY` mode:
|
303
|
+
|
304
|
+
```python
|
305
|
+
def get_current_weather(location: str) -> str:
|
306
|
+
"""Returns the current weather.
|
307
|
+
|
308
|
+
Args:
|
309
|
+
location: The city and state, e.g. San Francisco, CA
|
310
|
+
"""
|
311
|
+
return "sunny"
|
312
|
+
|
313
|
+
response = client.models.generate_content(
|
314
|
+
model="gemini-2.0-flash-exp",
|
315
|
+
contents="What is the weather like in Boston?",
|
316
|
+
config=types.GenerateContentConfig(
|
317
|
+
tools=[get_current_weather],
|
318
|
+
automatic_function_calling=types.AutomaticFunctionCallingConfig(
|
319
|
+
disable=True
|
320
|
+
),
|
321
|
+
tool_config=types.ToolConfig(
|
322
|
+
function_calling_config=types.FunctionCallingConfig(mode='ANY')
|
323
|
+
),
|
324
|
+
),
|
325
|
+
)
|
326
|
+
```
|
327
|
+
|
328
|
+
If you'd like to set `x` number of automatic function call turns, you can
|
329
|
+
configure the maximum remote calls to be `x + 1`.
|
330
|
+
Assuming you prefer `1` turn for automatic function calling.
|
331
|
+
|
332
|
+
```python
|
333
|
+
def get_current_weather(location: str) -> str:
|
334
|
+
"""Returns the current weather.
|
335
|
+
|
336
|
+
Args:
|
337
|
+
location: The city and state, e.g. San Francisco, CA
|
338
|
+
"""
|
339
|
+
return "sunny"
|
340
|
+
|
341
|
+
response = client.models.generate_content(
|
342
|
+
model="gemini-2.0-flash-exp",
|
343
|
+
contents="What is the weather like in Boston?",
|
344
|
+
config=types.GenerateContentConfig(
|
345
|
+
tools=[get_current_weather],
|
346
|
+
automatic_function_calling=types.AutomaticFunctionCallingConfig(
|
347
|
+
maximum_remote_calls=2
|
348
|
+
),
|
349
|
+
tool_config=types.ToolConfig(
|
350
|
+
function_calling_config=types.FunctionCallingConfig(mode='ANY')
|
351
|
+
),
|
352
|
+
),
|
353
|
+
)
|
354
|
+
```
|
313
355
|
### JSON Response Schema
|
314
356
|
|
315
357
|
#### Pydantic Model Schema support
|
@@ -836,12 +878,12 @@ print(tuned_model)
|
|
836
878
|
To retrieve base models, see [list base models](#list-base-models).
|
837
879
|
|
838
880
|
```python
|
839
|
-
for model in client.models.list(config={"page_size": 10}):
|
881
|
+
for model in client.models.list(config={"page_size": 10, "query_base": False}):
|
840
882
|
print(model)
|
841
883
|
```
|
842
884
|
|
843
885
|
```python
|
844
|
-
pager = client.models.list(config={"page_size": 10})
|
886
|
+
pager = client.models.list(config={"page_size": 10, "query_base": False})
|
845
887
|
print(pager.page_size)
|
846
888
|
print(pager[0])
|
847
889
|
pager.next_page()
|
@@ -851,12 +893,12 @@ print(pager[0])
|
|
851
893
|
#### Async
|
852
894
|
|
853
895
|
```python
|
854
|
-
async for job in await client.aio.models.list(config={"page_size": 10}):
|
896
|
+
async for job in await client.aio.models.list(config={"page_size": 10, "query_base": False}):
|
855
897
|
print(job)
|
856
898
|
```
|
857
899
|
|
858
900
|
```python
|
859
|
-
async_pager = await client.aio.models.list(config={"page_size": 10})
|
901
|
+
async_pager = await client.aio.models.list(config={"page_size": 10, "query_base": False})
|
860
902
|
print(async_pager.page_size)
|
861
903
|
print(async_pager[0])
|
862
904
|
await async_pager.next_page()
|
@@ -99,6 +99,19 @@ class HttpRequest:
|
|
99
99
|
timeout: Optional[float] = None
|
100
100
|
|
101
101
|
|
102
|
+
# TODO(b/394358912): Update this class to use a SDKResponse class that can be
|
103
|
+
# generated and used for all languages.
|
104
|
+
@dataclass
|
105
|
+
class BaseResponse:
|
106
|
+
http_headers: dict[str, str]
|
107
|
+
|
108
|
+
@property
|
109
|
+
def dict(self) -> dict[str, Any]:
|
110
|
+
if isinstance(self, dict):
|
111
|
+
return self
|
112
|
+
return {'httpHeaders': self.http_headers}
|
113
|
+
|
114
|
+
|
102
115
|
class HttpResponse:
|
103
116
|
|
104
117
|
def __init__(
|
@@ -255,7 +268,7 @@ class ApiClient:
|
|
255
268
|
'Project and location or API key must be set when using the Vertex '
|
256
269
|
'AI API.'
|
257
270
|
)
|
258
|
-
if self.api_key:
|
271
|
+
if self.api_key or self.location == 'global':
|
259
272
|
self._http_options['base_url'] = (
|
260
273
|
f'https://aiplatform.googleapis.com/'
|
261
274
|
)
|
@@ -273,7 +286,7 @@ class ApiClient:
|
|
273
286
|
self._http_options['api_version'] = 'v1beta'
|
274
287
|
# Default options for both clients.
|
275
288
|
self._http_options['headers'] = {'Content-Type': 'application/json'}
|
276
|
-
if self.api_key
|
289
|
+
if self.api_key:
|
277
290
|
self._http_options['headers']['x-goog-api-key'] = self.api_key
|
278
291
|
# Update the http options with the user provided http options.
|
279
292
|
if http_options:
|
@@ -323,8 +336,6 @@ class ApiClient:
|
|
323
336
|
and not self.api_key
|
324
337
|
):
|
325
338
|
path = f'projects/{self.project}/locations/{self.location}/' + path
|
326
|
-
elif self.vertexai and self.api_key:
|
327
|
-
path = f'{path}?key={self.api_key}'
|
328
339
|
url = _join_url_path(
|
329
340
|
patched_http_options['base_url'],
|
330
341
|
patched_http_options['api_version'] + '/' + path,
|
@@ -436,18 +447,12 @@ class ApiClient:
|
|
436
447
|
http_method, path, request_dict, http_options
|
437
448
|
)
|
438
449
|
response = self._request(http_request, stream=False)
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
elif (
|
446
|
-
isinstance(http_options, dict)
|
447
|
-
and 'deprecated_response_payload' in http_options
|
448
|
-
):
|
449
|
-
response._copy_to_dict(http_options['deprecated_response_payload'])
|
450
|
-
return response.json
|
450
|
+
json_response = response.json
|
451
|
+
if not json_response:
|
452
|
+
base_response = BaseResponse(response.headers).dict
|
453
|
+
return base_response
|
454
|
+
|
455
|
+
return json_response
|
451
456
|
|
452
457
|
def request_streamed(
|
453
458
|
self,
|
@@ -461,10 +466,6 @@ class ApiClient:
|
|
461
466
|
)
|
462
467
|
|
463
468
|
session_response = self._request(http_request, stream=True)
|
464
|
-
if http_options and 'deprecated_response_payload' in http_options:
|
465
|
-
session_response._copy_to_dict(
|
466
|
-
http_options['deprecated_response_payload']
|
467
|
-
)
|
468
469
|
for chunk in session_response.segments():
|
469
470
|
yield chunk
|
470
471
|
|
@@ -480,9 +481,11 @@ class ApiClient:
|
|
480
481
|
)
|
481
482
|
|
482
483
|
result = await self._async_request(http_request=http_request, stream=False)
|
483
|
-
|
484
|
-
|
485
|
-
|
484
|
+
json_response = result.json
|
485
|
+
if not json_response:
|
486
|
+
base_response = BaseResponse(result.headers).dict
|
487
|
+
return base_response
|
488
|
+
return json_response
|
486
489
|
|
487
490
|
async def async_request_streamed(
|
488
491
|
self,
|
@@ -497,8 +500,6 @@ class ApiClient:
|
|
497
500
|
|
498
501
|
response = await self._async_request(http_request=http_request, stream=True)
|
499
502
|
|
500
|
-
if http_options and 'deprecated_response_payload' in http_options:
|
501
|
-
response._copy_to_dict(http_options['deprecated_response_payload'])
|
502
503
|
async def async_generator():
|
503
504
|
async for chunk in response:
|
504
505
|
yield chunk
|
@@ -17,14 +17,18 @@ import inspect
|
|
17
17
|
import sys
|
18
18
|
import types as builtin_types
|
19
19
|
import typing
|
20
|
-
from typing import Any, Callable,
|
20
|
+
from typing import _GenericAlias, Any, Callable, get_args, get_origin, Literal, Union
|
21
|
+
|
21
22
|
import pydantic
|
23
|
+
|
24
|
+
from . import _extra_utils
|
22
25
|
from . import types
|
23
26
|
|
27
|
+
|
24
28
|
if sys.version_info >= (3, 10):
|
25
|
-
|
29
|
+
VersionedUnionType = builtin_types.UnionType
|
26
30
|
else:
|
27
|
-
|
31
|
+
VersionedUnionType = typing._UnionGenericAlias
|
28
32
|
|
29
33
|
_py_builtin_type_to_schema_type = {
|
30
34
|
str: 'STRING',
|
@@ -45,7 +49,8 @@ def _is_builtin_primitive_or_compound(
|
|
45
49
|
def _raise_for_any_of_if_mldev(schema: types.Schema):
|
46
50
|
if schema.any_of:
|
47
51
|
raise ValueError(
|
48
|
-
'AnyOf is not supported in function declaration schema for
|
52
|
+
'AnyOf is not supported in function declaration schema for'
|
53
|
+
' the Gemini API.'
|
49
54
|
)
|
50
55
|
|
51
56
|
|
@@ -53,15 +58,7 @@ def _raise_for_default_if_mldev(schema: types.Schema):
|
|
53
58
|
if schema.default is not None:
|
54
59
|
raise ValueError(
|
55
60
|
'Default value is not supported in function declaration schema for'
|
56
|
-
'
|
57
|
-
)
|
58
|
-
|
59
|
-
|
60
|
-
def _raise_for_nullable_if_mldev(schema: types.Schema):
|
61
|
-
if schema.nullable:
|
62
|
-
raise ValueError(
|
63
|
-
'Nullable is not supported in function declaration schema for'
|
64
|
-
' Google AI.'
|
61
|
+
' the Gemini API.'
|
65
62
|
)
|
66
63
|
|
67
64
|
|
@@ -69,7 +66,6 @@ def _raise_if_schema_unsupported(client, schema: types.Schema):
|
|
69
66
|
if not client.vertexai:
|
70
67
|
_raise_for_any_of_if_mldev(schema)
|
71
68
|
_raise_for_default_if_mldev(schema)
|
72
|
-
_raise_for_nullable_if_mldev(schema)
|
73
69
|
|
74
70
|
|
75
71
|
def _is_default_value_compatible(
|
@@ -82,10 +78,10 @@ def _is_default_value_compatible(
|
|
82
78
|
if (
|
83
79
|
isinstance(annotation, _GenericAlias)
|
84
80
|
or isinstance(annotation, builtin_types.GenericAlias)
|
85
|
-
or isinstance(annotation,
|
81
|
+
or isinstance(annotation, VersionedUnionType)
|
86
82
|
):
|
87
83
|
origin = get_origin(annotation)
|
88
|
-
if origin in (Union,
|
84
|
+
if origin in (Union, VersionedUnionType):
|
89
85
|
return any(
|
90
86
|
_is_default_value_compatible(default_value, arg)
|
91
87
|
for arg in get_args(annotation)
|
@@ -141,7 +137,7 @@ def _parse_schema_from_parameter(
|
|
141
137
|
_raise_if_schema_unsupported(client, schema)
|
142
138
|
return schema
|
143
139
|
if (
|
144
|
-
isinstance(param.annotation,
|
140
|
+
isinstance(param.annotation, VersionedUnionType)
|
145
141
|
# only parse simple UnionType, example int | str | float | bool
|
146
142
|
# complex UnionType will be invoked in raise branch
|
147
143
|
and all(
|
@@ -229,7 +225,11 @@ def _parse_schema_from_parameter(
|
|
229
225
|
schema.type = 'OBJECT'
|
230
226
|
unique_types = set()
|
231
227
|
for arg in args:
|
232
|
-
|
228
|
+
# The first check is for NoneType in Python 3.9, since the __name__
|
229
|
+
# attribute is not available in Python 3.9
|
230
|
+
if type(arg) is type(None) or (
|
231
|
+
hasattr(arg, '__name__') and arg.__name__ == 'NoneType'
|
232
|
+
): # Optional type
|
233
233
|
schema.nullable = True
|
234
234
|
continue
|
235
235
|
schema_in_any_of = _parse_schema_from_parameter(
|
@@ -272,9 +272,8 @@ def _parse_schema_from_parameter(
|
|
272
272
|
return schema
|
273
273
|
# all other generic alias will be invoked in raise branch
|
274
274
|
if (
|
275
|
-
inspect.isclass(param.annotation)
|
276
275
|
# for user defined class, we only support pydantic model
|
277
|
-
|
276
|
+
_extra_utils.is_annotation_pydantic_model(param.annotation)
|
278
277
|
):
|
279
278
|
if (
|
280
279
|
param.default is not inspect.Parameter.empty
|
@@ -18,14 +18,17 @@
|
|
18
18
|
import base64
|
19
19
|
import datetime
|
20
20
|
import enum
|
21
|
+
import functools
|
21
22
|
import typing
|
22
23
|
from typing import Union
|
23
24
|
import uuid
|
25
|
+
import warnings
|
24
26
|
|
25
27
|
import pydantic
|
26
28
|
from pydantic import alias_generators
|
27
29
|
|
28
30
|
from . import _api_client
|
31
|
+
from . import errors
|
29
32
|
|
30
33
|
|
31
34
|
def set_value_by_path(data, keys, value):
|
@@ -213,8 +216,16 @@ class CaseInSensitiveEnum(str, enum.Enum):
|
|
213
216
|
except KeyError:
|
214
217
|
try:
|
215
218
|
return cls[value.lower()] # Try to access directly with lowercase
|
216
|
-
except KeyError
|
217
|
-
|
219
|
+
except KeyError:
|
220
|
+
warnings.warn(f"{value} is not a valid {cls.__name__}")
|
221
|
+
try:
|
222
|
+
# Creating a enum instance based on the value
|
223
|
+
unknown_enum_val = cls._new_member_(cls) # pylint: disable=protected-access,attribute-error
|
224
|
+
unknown_enum_val._name_ = str(value) # pylint: disable=protected-access
|
225
|
+
unknown_enum_val._value_ = value # pylint: disable=protected-access
|
226
|
+
return unknown_enum_val
|
227
|
+
except:
|
228
|
+
return None
|
218
229
|
|
219
230
|
|
220
231
|
def timestamped_unique_name() -> str:
|
@@ -264,3 +275,23 @@ def encode_unserializable_types(data: dict[str, object]) -> dict[str, object]:
|
|
264
275
|
else:
|
265
276
|
processed_data[key] = value
|
266
277
|
return processed_data
|
278
|
+
|
279
|
+
|
280
|
+
def experimental_warning(message: str):
|
281
|
+
"""Experimental warning, only warns once."""
|
282
|
+
def decorator(func):
|
283
|
+
warning_done = False
|
284
|
+
@functools.wraps(func)
|
285
|
+
def wrapper(*args, **kwargs):
|
286
|
+
nonlocal warning_done
|
287
|
+
if not warning_done:
|
288
|
+
warning_done = True
|
289
|
+
warnings.warn(
|
290
|
+
message=message,
|
291
|
+
category=errors.ExperimentalWarning,
|
292
|
+
stacklevel=2,
|
293
|
+
)
|
294
|
+
return func(*args, **kwargs)
|
295
|
+
return wrapper
|
296
|
+
return decorator
|
297
|
+
|