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.
@@ -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
+
@@ -0,0 +1,7 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ recursive-include greycloud *.py
5
+ recursive-include tests *.py
6
+ global-exclude __pycache__
7
+ global-exclude *.py[co]
@@ -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.