Skip to content

Commit e5f5fe3

Browse files
committed
Merge branch 'main' into 3-13
Change-Id: Ifb5440630c1ba4933f34f78923f119a3896faa68
2 parents 9ce4014 + 8f7f5cb commit e5f5fe3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+454
-2417
lines changed

.github/workflows/samples.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
2929
for file in ${NEW_FILES}; do
3030
echo "Testing $file"
31+
name=$(basename $file)
3132
if [[ -f ${file} ]]; then
3233
# File exists, so needs to be listed.
3334
if ! grep -q $name ${README}; then

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ pytest
9393

9494
Or to debug, use:
9595

96-
```commandline
96+
```
9797
pip install nose2
9898
9999
nose2 --debugger
100+
```
100101

101102
### Type checking
102103

@@ -124,7 +125,6 @@ black .
124125
python docs/build_docs.py
125126
```
126127

127-
128128
[setup]: https://cloud.google.com/nodejs/docs/setup
129129
[projects]: https://console.cloud.google.com/project
130130
[billing]: https://support.google.com/cloud/answer/6293499#enable-billing

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The Google AI Python SDK is the easiest way for Python developers to build with
99
## Get started with the Gemini API
1010
1. Go to [Google AI Studio](https://aistudio.google.com/).
1111
2. Login with your Google account.
12-
3. [Create](https://aistudio.google.com/app/apikey) an API key. Note that in Europe the free tier is not available.
12+
3. [Create](https://aistudio.google.com/app/apikey) an API key.
1313
4. Try a Python SDK [quickstart](https://github.com/google-gemini/gemini-api-cookbook/blob/main/quickstarts/Prompting.ipynb) in the [Gemini API Cookbook](https://github.com/google-gemini/gemini-api-cookbook/).
1414
5. For detailed instructions, try the
1515
[Python SDK tutorial](https://ai.google.dev/tutorials/python_quickstart) on [ai.google.dev](https://ai.google.dev).
@@ -33,7 +33,7 @@ genai.configure(api_key=os.environ["GEMINI_API_KEY"])
3333
3. Create a model and run a prompt.
3434

3535
```python
36-
model = genai.GenerativeModel('gemini-1.0-pro-latest')
36+
model = genai.GenerativeModel('gemini-1.5-flash')
3737
response = model.generate_content("The opposite of hot is")
3838
print(response.text)
3939
```

google/generativeai/__init__.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@
4848

4949
from google.generativeai.client import configure
5050

51-
from google.generativeai.discuss import chat
52-
from google.generativeai.discuss import chat_async
53-
from google.generativeai.discuss import count_message_tokens
54-
5551
from google.generativeai.embedding import embed_content
5652
from google.generativeai.embedding import embed_content_async
5753

@@ -77,19 +73,13 @@
7773
from google.generativeai.operations import list_operations
7874
from google.generativeai.operations import get_operation
7975

80-
from google.generativeai.text import generate_text
81-
from google.generativeai.text import generate_embeddings
82-
from google.generativeai.text import count_text_tokens
83-
8476
from google.generativeai.types import GenerationConfig
8577

8678
__version__ = version.__version__
8779

88-
del discuss
8980
del embedding
9081
del files
9182
del generative_models
92-
del text
9383
del models
9484
del client
9585
del operations

google/generativeai/answer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def generate_answer(
283283
answer_style: Style in which the grounded answer should be returned.
284284
safety_settings: Safety settings for generated output. Defaults to None.
285285
temperature: Controls the randomness of the output.
286-
client: If you're not relying on a default client, you pass a `glm.TextServiceClient` instead.
286+
client: If you're not relying on a default client, you pass a `glm.GenerativeServiceClient` instead.
287287
request_options: Options for the request.
288288
289289
Returns:
@@ -337,7 +337,7 @@ async def generate_answer_async(
337337
answer_style: Style in which the grounded answer should be returned.
338338
safety_settings: Safety settings for generated output. Defaults to None.
339339
temperature: Controls the randomness of the output.
340-
client: If you're not relying on a default client, you pass a `glm.TextServiceClient` instead.
340+
client: If you're not relying on a default client, you pass a `glm.GenerativeServiceClient` instead.
341341
342342
Returns:
343343
A `types.Answer` containing the model's text answer response.

google/generativeai/client.py

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import os
44
import contextlib
5+
import inspect
56
import dataclasses
67
import pathlib
7-
import types
88
from typing import Any, cast
99
from collections.abc import Sequence
1010
import httplib2
@@ -30,6 +30,21 @@
3030
__version__ = "0.0.0"
3131

3232
USER_AGENT = "genai-py"
33+
34+
#### Caution! ####
35+
# - It would make sense for the discovery URL to respect the client_options.endpoint setting.
36+
# - That would make testing Files on the staging server possible.
37+
# - We tried fixing this once, but broke colab in the process because their endpoint didn't forward the discovery
38+
# requests. https://github.com/google-gemini/generative-ai-python/pull/333
39+
# - Kaggle would have a similar problem (b/362278209).
40+
# - I think their proxy would forward the discovery traffic.
41+
# - But they don't need to intercept the files-service at all, and uploads of large files could overload them.
42+
# - Do the scotty uploads go to the same domain?
43+
# - If you do route the discovery call to kaggle, be sure to attach the default_metadata (they need it).
44+
# - One solution to all this would be if configure could take overrides per service.
45+
# - set client_options.endpoint, but use a different endpoint for file service? It's not clear how best to do that
46+
# through the file service.
47+
##################
3348
GENAI_API_DISCOVERY_URL = "https://generativelanguage.googleapis.com/$discovery/rest"
3449

3550

@@ -50,7 +65,7 @@ def __init__(self, *args, **kwargs):
5065
self._discovery_api = None
5166
super().__init__(*args, **kwargs)
5267

53-
def _setup_discovery_api(self):
68+
def _setup_discovery_api(self, metadata: dict | Sequence[tuple[str, str]] = ()):
5469
api_key = self._client_options.api_key
5570
if api_key is None:
5671
raise ValueError(
@@ -61,6 +76,7 @@ def _setup_discovery_api(self):
6176
http=httplib2.Http(),
6277
postproc=lambda resp, content: (resp, content),
6378
uri=f"{GENAI_API_DISCOVERY_URL}?version=v1beta&key={api_key}",
79+
headers=dict(metadata),
6480
)
6581
response, content = request.execute()
6682
request.http.close()
@@ -78,9 +94,10 @@ def create_file(
7894
name: str | None = None,
7995
display_name: str | None = None,
8096
resumable: bool = True,
97+
metadata: Sequence[tuple[str, str]] = (),
8198
) -> protos.File:
8299
if self._discovery_api is None:
83-
self._setup_discovery_api()
100+
self._setup_discovery_api(metadata)
84101

85102
file = {}
86103
if name is not None:
@@ -92,6 +109,8 @@ def create_file(
92109
filename=path, mimetype=mime_type, resumable=resumable
93110
)
94111
request = self._discovery_api.media().upload(body={"file": file}, media_body=media)
112+
for key, value in metadata:
113+
request.headers[key] = value
95114
result = request.execute()
96115

97116
return self.get_file({"name": result["file"]["name"]})
@@ -108,9 +127,6 @@ async def create_file(self, *args, **kwargs):
108127
class _ClientManager:
109128
client_config: dict[str, Any] = dataclasses.field(default_factory=dict)
110129
default_metadata: Sequence[tuple[str, str]] = ()
111-
112-
discuss_client: glm.DiscussServiceClient | None = None
113-
discuss_async_client: glm.DiscussServiceAsyncClient | None = None
114130
clients: dict[str, Any] = dataclasses.field(default_factory=dict)
115131

116132
def configure(
@@ -119,7 +135,7 @@ def configure(
119135
api_key: str | None = None,
120136
credentials: ga_credentials.Credentials | dict | None = None,
121137
# The user can pass a string to choose `rest` or `grpc` or 'grpc_asyncio'.
122-
# See `_transport_registry` in `DiscussServiceClientMeta`.
138+
# See _transport_registry in the google.ai.generativelanguage package.
123139
# Since the transport classes align with the client classes it wouldn't make
124140
# sense to accept a `Transport` object here even though the client classes can.
125141
# We could accept a dict since all the `Transport` classes take the same args,
@@ -229,16 +245,14 @@ def make_client(self, name):
229245
def keep(name, f):
230246
if name.startswith("_"):
231247
return False
232-
elif name == "create_file":
233-
return False
234-
elif not isinstance(f, types.FunctionType):
235-
return False
236-
elif isinstance(f, classmethod):
248+
249+
if not callable(f):
237250
return False
238-
elif isinstance(f, staticmethod):
251+
252+
if "metadata" not in inspect.signature(f).parameters.keys():
239253
return False
240-
else:
241-
return True
254+
255+
return True
242256

243257
def add_default_metadata_wrapper(f):
244258
def call(*args, metadata=(), **kwargs):
@@ -247,7 +261,7 @@ def call(*args, metadata=(), **kwargs):
247261

248262
return call
249263

250-
for name, value in cls.__dict__.items():
264+
for name, value in inspect.getmembers(cls):
251265
if not keep(name, value):
252266
continue
253267
f = getattr(client, name)
@@ -281,7 +295,6 @@ def configure(
281295
api_key: str | None = None,
282296
credentials: ga_credentials.Credentials | dict | None = None,
283297
# The user can pass a string to choose `rest` or `grpc` or 'grpc_asyncio'.
284-
# See `_transport_registry` in `DiscussServiceClientMeta`.
285298
# Since the transport classes align with the client classes it wouldn't make
286299
# sense to accept a `Transport` object here even though the client classes can.
287300
# We could accept a dict since all the `Transport` classes take the same args,
@@ -326,14 +339,6 @@ def get_default_cache_client() -> glm.CacheServiceClient:
326339
return _client_manager.get_default_client("cache")
327340

328341

329-
def get_default_discuss_client() -> glm.DiscussServiceClient:
330-
return _client_manager.get_default_client("discuss")
331-
332-
333-
def get_default_discuss_async_client() -> glm.DiscussServiceAsyncClient:
334-
return _client_manager.get_default_client("discuss_async")
335-
336-
337342
def get_default_file_client() -> glm.FilesServiceClient:
338343
return _client_manager.get_default_client("file")
339344

@@ -350,10 +355,6 @@ def get_default_generative_async_client() -> glm.GenerativeServiceAsyncClient:
350355
return _client_manager.get_default_client("generative_async")
351356

352357

353-
def get_default_text_client() -> glm.TextServiceClient:
354-
return _client_manager.get_default_client("text")
355-
356-
357358
def get_default_operations_client() -> operations_v1.OperationsClient:
358359
return _client_manager.get_default_client("operations")
359360

0 commit comments

Comments
 (0)