greycloud 0.1.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.
- greycloud-0.1.0/LICENSE +22 -0
- greycloud-0.1.0/MANIFEST.in +7 -0
- greycloud-0.1.0/PKG-INFO +400 -0
- greycloud-0.1.0/README.md +359 -0
- greycloud-0.1.0/greycloud/__init__.py +14 -0
- greycloud-0.1.0/greycloud/auth.py +246 -0
- greycloud-0.1.0/greycloud/batch.py +506 -0
- greycloud-0.1.0/greycloud/client.py +616 -0
- greycloud-0.1.0/greycloud/config.py +87 -0
- greycloud-0.1.0/greycloud.egg-info/PKG-INFO +400 -0
- greycloud-0.1.0/greycloud.egg-info/SOURCES.txt +22 -0
- greycloud-0.1.0/greycloud.egg-info/dependency_links.txt +1 -0
- greycloud-0.1.0/greycloud.egg-info/requires.txt +19 -0
- greycloud-0.1.0/greycloud.egg-info/top_level.txt +1 -0
- greycloud-0.1.0/pyproject.toml +103 -0
- greycloud-0.1.0/setup.cfg +4 -0
- greycloud-0.1.0/setup.py +10 -0
- greycloud-0.1.0/tests/__init__.py +1 -0
- greycloud-0.1.0/tests/conftest.py +121 -0
- greycloud-0.1.0/tests/test_auth.py +220 -0
- greycloud-0.1.0/tests/test_batch.py +444 -0
- greycloud-0.1.0/tests/test_client.py +340 -0
- greycloud-0.1.0/tests/test_config.py +213 -0
- greycloud-0.1.0/tests/test_init.py +43 -0
greycloud-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 GreyCloud Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
greycloud-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: greycloud
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reusable Google GenAI/Vertex AI Client Module
|
|
5
|
+
Author: GreyCloud Contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/jbff/greycloud
|
|
8
|
+
Project-URL: Documentation, https://github.com/jbff/greycloud#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/jbff/greycloud
|
|
10
|
+
Project-URL: Issues, https://github.com/jbff/greycloud/issues
|
|
11
|
+
Keywords: google,vertex-ai,genai,gemini,ai,ml
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: google-genai>=1.59.0
|
|
25
|
+
Requires-Dist: google-auth>=2.0.0
|
|
26
|
+
Requires-Dist: google-cloud-storage>=3.8.0
|
|
27
|
+
Provides-Extra: storage
|
|
28
|
+
Requires-Dist: google-cloud-storage>=3.8.0; extra == "storage"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=9.0.2; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
34
|
+
Requires-Dist: coverage>=7.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: greycloud[dev,storage]; extra == "all"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
## GreyCloud
|
|
43
|
+
|
|
44
|
+
A comprehensive, configurable Python package for interacting with Google's Vertex AI and GenAI services (Gemini), including authentication, content generation, batch processing, token counting, and file management.
|
|
45
|
+
|
|
46
|
+
GreyCloud wraps the lower-level `google-genai` client with:
|
|
47
|
+
|
|
48
|
+
- **Unified authentication** (API key or OAuth + optional service account impersonation)
|
|
49
|
+
- **Resilient content generation** with automatic retry and re-authentication
|
|
50
|
+
- **Config-driven client setup** via a single `GreyCloudConfig` dataclass
|
|
51
|
+
- **Optional Vertex AI Search tools** for retrieval-augmented generation
|
|
52
|
+
- **Batch helpers** for large offline jobs and GCS integration
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 1. What GreyCloud Does
|
|
57
|
+
|
|
58
|
+
GreyCloud provides three main building blocks:
|
|
59
|
+
|
|
60
|
+
- `GreyCloudConfig` – configuration object populated from environment variables or code
|
|
61
|
+
- `GreyCloudClient` – high-level client for content generation, streaming, token counting, and retries
|
|
62
|
+
- `GreyCloudBatch` – helper for batch jobs and GCS-backed workflows
|
|
63
|
+
|
|
64
|
+
High-level capabilities:
|
|
65
|
+
|
|
66
|
+
- **Content generation** (streaming and non-streaming) with per-request overrides
|
|
67
|
+
- **Automatic retry** with exponential backoff and authentication-aware recovery
|
|
68
|
+
- **Token counting** with graceful approximation fallback
|
|
69
|
+
- **Vertex AI Search integration** via a simple flag and datastore string
|
|
70
|
+
- **Batch processing** to upload files, create jobs, monitor, and download results
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. Why Use GreyCloud Instead of `google-genai` Directly?
|
|
75
|
+
|
|
76
|
+
Using `google-genai` directly is flexible but verbose. GreyCloud focuses on **developer ergonomics** and **resilience**:
|
|
77
|
+
|
|
78
|
+
- **Unified auth helper**
|
|
79
|
+
- One function (`create_client` / `GreyCloudClient`) that:
|
|
80
|
+
- Uses Application Default Credentials when available
|
|
81
|
+
- Optionally impersonates a service account when `sa_email` is set
|
|
82
|
+
- Falls back to `gcloud auth print-access-token` when needed
|
|
83
|
+
- Supports API key authentication via a simple config flag
|
|
84
|
+
- Clear error messages that point to:
|
|
85
|
+
- `gcloud auth application-default login`
|
|
86
|
+
- IAM role requirements for impersonation
|
|
87
|
+
|
|
88
|
+
- **Config normalization**
|
|
89
|
+
- A single dataclass (`GreyCloudConfig`) encapsulates:
|
|
90
|
+
- Project, location, endpoint, model
|
|
91
|
+
- Auth choices (API key vs OAuth + SA impersonation)
|
|
92
|
+
- Generation parameters (temperature, top_p, max_output_tokens, seed)
|
|
93
|
+
- Safety settings
|
|
94
|
+
- Thinking configuration
|
|
95
|
+
- Vertex AI Search datastore
|
|
96
|
+
- Batch/GCS bucket settings
|
|
97
|
+
|
|
98
|
+
- **Resilient generation**
|
|
99
|
+
- `GreyCloudClient.generate_with_retry(...)`:
|
|
100
|
+
- Detects auth-related vs transient errors
|
|
101
|
+
- Performs exponential backoff with jitter
|
|
102
|
+
- Attempts re-authentication when appropriate (for OAuth-based flows)
|
|
103
|
+
- Re-creates the underlying `genai.Client` as needed
|
|
104
|
+
|
|
105
|
+
- **Tools & Search wiring**
|
|
106
|
+
- Vertex AI Search is turned on with:
|
|
107
|
+
- `use_vertex_ai_search=True`
|
|
108
|
+
- `vertex_ai_search_datastore="projects/.../dataStores/..."`.
|
|
109
|
+
- GreyCloud constructs the appropriate `types.Tool` and wires it into calls.
|
|
110
|
+
|
|
111
|
+
- **Batch utilities**
|
|
112
|
+
- `GreyCloudBatch` wraps the more verbose raw batch APIs:
|
|
113
|
+
- Handles JSONL creation
|
|
114
|
+
- Manages GCS paths and result locations
|
|
115
|
+
- Tries multiple model naming formats (`publishers/google/models/...` vs short name)
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 3. Installation
|
|
120
|
+
|
|
121
|
+
### Basic Installation
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
pip install greycloud
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Development Installation
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git clone https://github.com/jbff/greycloud.git
|
|
131
|
+
cd greycloud
|
|
132
|
+
pip install -e ".[dev]"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## 4. Quick Start: Basic Client and Single Call
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from greycloud import GreyCloudConfig, GreyCloudClient
|
|
139
|
+
from google.genai import types
|
|
140
|
+
|
|
141
|
+
# Create configuration (override defaults as needed)
|
|
142
|
+
config = GreyCloudConfig(
|
|
143
|
+
project_id="your-project-id",
|
|
144
|
+
location="us-central1",
|
|
145
|
+
# Default model is a Gemini 3 flash model; you can override if desired.
|
|
146
|
+
model="gemini-3-flash-preview",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Create client
|
|
150
|
+
client = GreyCloudClient(config)
|
|
151
|
+
|
|
152
|
+
# Generate content
|
|
153
|
+
contents = [
|
|
154
|
+
types.Content(
|
|
155
|
+
role="user",
|
|
156
|
+
parts=[types.Part.from_text(text="Hello, how are you?")]
|
|
157
|
+
)
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
response = client.generate_content(contents)
|
|
161
|
+
print(response.text)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 5. Detailed Examples
|
|
167
|
+
|
|
168
|
+
### 5.1 Creating a Client from Environment Only
|
|
169
|
+
|
|
170
|
+
Environment:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
export PROJECT_ID="your-project-id"
|
|
174
|
+
export LOCATION="us-central1"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Code:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from greycloud import GreyCloudClient
|
|
181
|
+
from google.genai import types
|
|
182
|
+
|
|
183
|
+
client = GreyCloudClient() # GreyCloudConfig is created from env
|
|
184
|
+
|
|
185
|
+
contents = [
|
|
186
|
+
types.Content(
|
|
187
|
+
role="user",
|
|
188
|
+
parts=[types.Part.from_text(text="Summarize the benefits of Vertex AI.")]
|
|
189
|
+
)
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
response = client.generate_content(contents)
|
|
193
|
+
print(response.text)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 5.2 Per-Request Overrides
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
response = client.generate_content(
|
|
200
|
+
contents,
|
|
201
|
+
temperature=0.7,
|
|
202
|
+
max_output_tokens=1024,
|
|
203
|
+
system_instruction="You are a concise technical assistant.",
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 5.3 Streaming Generation
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
for chunk in client.generate_content_stream(contents):
|
|
211
|
+
print(chunk, end="", flush=True)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 5.4 Automatic Retry & Auth Recovery
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from google.genai import types
|
|
218
|
+
|
|
219
|
+
contents = [
|
|
220
|
+
types.Content(
|
|
221
|
+
role="user",
|
|
222
|
+
parts=[types.Part.from_text(text="Give me a short creative story about a robot therapist.")]
|
|
223
|
+
)
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
response = client.generate_with_retry(
|
|
227
|
+
contents,
|
|
228
|
+
max_retries=5,
|
|
229
|
+
streaming=False,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
print(response.text)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
For streaming with retry:
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
for chunk in client.generate_with_retry(
|
|
239
|
+
contents,
|
|
240
|
+
max_retries=5,
|
|
241
|
+
streaming=True,
|
|
242
|
+
):
|
|
243
|
+
print(chunk, end="", flush=True)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 5.5 Token Counting with Fallback
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from google.genai import types
|
|
250
|
+
|
|
251
|
+
contents = [
|
|
252
|
+
types.Content(
|
|
253
|
+
role="user",
|
|
254
|
+
parts=[types.Part.from_text(text="Count the tokens in this example message.")]
|
|
255
|
+
)
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
token_count = client.count_tokens(
|
|
259
|
+
contents,
|
|
260
|
+
system_instruction="You are a helpful assistant.",
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
print(f"Total tokens: {token_count}")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
If the underlying API is unavailable, GreyCloud falls back to an approximate character-based count.
|
|
267
|
+
|
|
268
|
+
### 5.6 Vertex AI Search as a Tool
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
from greycloud import GreyCloudConfig, GreyCloudClient
|
|
272
|
+
from google.genai import types
|
|
273
|
+
|
|
274
|
+
config = GreyCloudConfig(
|
|
275
|
+
project_id="your-project-id",
|
|
276
|
+
location="us-central1",
|
|
277
|
+
use_vertex_ai_search=True,
|
|
278
|
+
vertex_ai_search_datastore=(
|
|
279
|
+
"projects/PROJECT_ID/locations/LOCATION/"
|
|
280
|
+
"collections/default_collection/dataStores/DATASTORE_ID"
|
|
281
|
+
),
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
client = GreyCloudClient(config)
|
|
285
|
+
|
|
286
|
+
contents = [
|
|
287
|
+
types.Content(
|
|
288
|
+
role="user",
|
|
289
|
+
parts=[types.Part.from_text(text="Using the knowledge base, explain the diagnostic steps for adult ASD.")]
|
|
290
|
+
)
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
response = client.generate_content(contents)
|
|
294
|
+
print(response.text)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### 5.7 Batch Processing with GCS
|
|
298
|
+
|
|
299
|
+
Batch jobs use a GCS bucket for request input and result output. Set `batch_gcs_bucket` (and optionally `gcs_bucket` for general uploads). The batch API expects JSONL input: one line per request, each line a JSON object with a `request` key containing `model`, `contents`, and optional `config`/`metadata`. Results are written by Vertex to `predictions.jsonl` under the job’s destination prefix; `download_batch_results` finds and downloads that file.
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
from greycloud import GreyCloudConfig, GreyCloudBatch
|
|
303
|
+
from google.genai import types
|
|
304
|
+
import json
|
|
305
|
+
|
|
306
|
+
config = GreyCloudConfig(
|
|
307
|
+
project_id="your-project-id",
|
|
308
|
+
batch_gcs_bucket="your-project-batch-jobs", # Must exist; used for batch I/O
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
batch = GreyCloudBatch(config)
|
|
312
|
+
|
|
313
|
+
# Upload a couple of JSON docs (use same bucket via bucket_name)
|
|
314
|
+
files = [
|
|
315
|
+
{"name": "data1.json", "content": json.dumps({"key": "value"})},
|
|
316
|
+
{"name": "data2.json", "content": json.dumps({"key2": "value2"})},
|
|
317
|
+
]
|
|
318
|
+
|
|
319
|
+
file_uris = batch.upload_files_to_gcs(files, bucket_name=config.batch_gcs_bucket)
|
|
320
|
+
|
|
321
|
+
batch_requests = []
|
|
322
|
+
for filename, gcs_uri in file_uris.items():
|
|
323
|
+
batch_requests.append(
|
|
324
|
+
types.InlinedRequest(
|
|
325
|
+
model=config.model,
|
|
326
|
+
contents=[
|
|
327
|
+
{
|
|
328
|
+
"role": "user",
|
|
329
|
+
"parts": [
|
|
330
|
+
{"text": f"Analyze {filename}: "},
|
|
331
|
+
{"file_data": {"file_uri": gcs_uri, "mime_type": "application/json"}},
|
|
332
|
+
],
|
|
333
|
+
}
|
|
334
|
+
],
|
|
335
|
+
config=types.GenerateContentConfig(
|
|
336
|
+
temperature=0.2,
|
|
337
|
+
max_output_tokens=65535,
|
|
338
|
+
),
|
|
339
|
+
)
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
batch_job = batch.create_batch_job(batch_requests)
|
|
343
|
+
batch_job = batch.monitor_batch_job(batch_job)
|
|
344
|
+
|
|
345
|
+
output_file = batch.download_batch_results(batch_job, "results.jsonl")
|
|
346
|
+
print(f"Batch results saved to: {output_file}")
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### 5.8 Custom Auth (Advanced)
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
from greycloud.auth import create_client
|
|
353
|
+
|
|
354
|
+
client = create_client(
|
|
355
|
+
project_id="your-project-id",
|
|
356
|
+
location="us-central1",
|
|
357
|
+
sa_email="service-account@project.iam.gserviceaccount.com", # Optional
|
|
358
|
+
use_api_key=False,
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Documentation
|
|
365
|
+
|
|
366
|
+
All usage and configuration details are documented in this `README.md`. For additional examples, see:
|
|
367
|
+
|
|
368
|
+
- `examples/simple.py` – minimal content-generation script.
|
|
369
|
+
|
|
370
|
+
## Requirements
|
|
371
|
+
|
|
372
|
+
- Python 3.10+
|
|
373
|
+
- Google Cloud Project with Vertex AI enabled
|
|
374
|
+
- `google-genai` package (installed with `greycloud`)
|
|
375
|
+
- `google-auth` package (installed with `greycloud`, for OAuth)
|
|
376
|
+
- `google-cloud-storage` package (installed with `greycloud`; only needed if you use batch/GCS helpers)
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Testing
|
|
381
|
+
|
|
382
|
+
Run the test suite:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
pytest
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Run with coverage:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
pytest --cov=greycloud --cov-report=html
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## License
|
|
395
|
+
|
|
396
|
+
MIT License (see `LICENSE` file).
|
|
397
|
+
|
|
398
|
+
## Contributing
|
|
399
|
+
|
|
400
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|