utkarshshukla2912 commited on
Commit
c25fb8f
·
1 Parent(s): 5f8242b

added gvertex

Browse files
Files changed (9) hide show
  1. .env.example +1 -0
  2. README.md +0 -12
  3. app.py +52 -70
  4. generation_counter.json +1 -2
  5. pyproject.toml +2 -0
  6. requirements.txt +81 -0
  7. uv.lock +469 -2
  8. vertex_client.py +198 -0
  9. voices_config.json +189 -0
.env.example ADDED
@@ -0,0 +1 @@
 
 
1
+ auth_string={"type":"service_account","project_id":"desivocalprod01","private_key_id":"YOUR_PRIVATE_KEY_ID","private_key":"-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY_HERE\n-----END PRIVATE KEY-----\n","client_email":"[email protected]","client_id":"YOUR_CLIENT_ID","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"YOUR_CERT_URL"}
README.md DELETED
@@ -1,12 +0,0 @@
1
- ---
2
- title: Ringg TTS V1.0
3
- emoji: 😻
4
- colorFrom: pink
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 5.49.1
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -1,15 +1,13 @@
1
  import gradio as gr
2
- import requests
3
  import json
4
  import os
5
  from pathlib import Path
6
  import uuid
7
  import fcntl
8
  import time
 
9
 
10
  # gr.NO_RELOAD = False
11
- # API Base URL
12
- BASE_URL = os.environ.get("BASE_URL", "")
13
 
14
  # Counter persistence file
15
  COUNTER_FILE = Path("generation_counter.json")
@@ -33,7 +31,7 @@ def load_counter():
33
  data = json.load(f)
34
  fcntl.flock(f.fileno(), fcntl.LOCK_UN)
35
  return data.get("count", 0)
36
- except:
37
  # If locking fails, just read without lock
38
  f.seek(0)
39
  data = json.load(f)
@@ -54,7 +52,7 @@ def save_counter(count):
54
  f.flush()
55
  os.fsync(f.fileno())
56
  fcntl.flock(f.fileno(), fcntl.LOCK_UN)
57
- except:
58
  # If locking fails, just write without lock
59
  json.dump({"count": count, "last_updated": time.time()}, f)
60
  f.flush()
@@ -75,7 +73,7 @@ def increment_counter():
75
  try:
76
  data = json.load(f)
77
  current_count = data.get("count", 0)
78
- except:
79
  current_count = 0
80
 
81
  # Increment
@@ -90,13 +88,13 @@ def increment_counter():
90
 
91
  fcntl.flock(f.fileno(), fcntl.LOCK_UN)
92
  return new_count
93
- except:
94
  # Fallback without locking
95
  f.seek(0)
96
  try:
97
  data = json.load(f)
98
  current_count = data.get("count", 0)
99
- except:
100
  current_count = 0
101
  new_count = current_count + 1
102
  f.seek(0)
@@ -110,11 +108,14 @@ def increment_counter():
110
 
111
 
112
  def get_voices():
113
- """Fetch available voices from API"""
114
  try:
115
- response = requests.get(f"{BASE_URL}/voices", timeout=10)
116
- if response.status_code == 200:
117
- voices_data = response.json().get("voices", {})
 
 
 
118
  # Create a list of tuples (display_name, voice_id)
119
  voices = []
120
  for voice_id, voice_info in voices_data.items():
@@ -123,14 +124,16 @@ def get_voices():
123
  display_name = f"{name} ({gender})"
124
  voices.append((display_name, voice_id))
125
  return sorted(voices, key=lambda x: x[0])
126
- return []
 
 
127
  except Exception as e:
128
- print(f"Error fetching voices: {e}")
129
  return []
130
 
131
 
132
  def synthesize_speech(text, voice_id):
133
- """Synthesize speech from text"""
134
  if not text or not text.strip():
135
  return None, "⚠️ Please enter some text", "", "", "", "", "", ""
136
 
@@ -142,58 +145,48 @@ def synthesize_speech(text, voice_id):
142
  print(f"Input text length: {text_length} characters")
143
 
144
  try:
145
- payload = {"text": text, "voice_id": voice_id}
146
-
147
- response = requests.post(
148
- f"{BASE_URL}/synthesize",
149
- headers={"Content-Type": "application/json"},
150
- json=payload,
151
- timeout=30,
152
  )
153
 
154
- if response.status_code == 200:
155
- result = response.json()
156
-
157
- if result.get("success"):
158
- audio_url = result.get("audio_url", "")
159
- metrics = result.get("metrics", {})
160
 
161
- # Format metrics
 
162
  total_time = f"{metrics.get('t', 0):.3f}s"
163
  rtf = f"{metrics.get('rtf', 0):.4f}"
164
  wav_duration = f"{metrics.get('wav_seconds', 0):.2f}s"
165
  vocoder_time = f"{metrics.get('t_vocoder', 0):.3f}s"
166
  no_vocoder_time = f"{metrics.get('t_no_vocoder', 0):.3f}s"
167
  rtf_no_vocoder = f"{metrics.get('rtf_no_vocoder', 0):.4f}"
168
-
169
- status_msg = "✅ Audio generated successfully!"
170
-
171
- return (
172
- audio_url,
173
- status_msg,
174
- total_time,
175
- rtf,
176
- wav_duration,
177
- vocoder_time,
178
- no_vocoder_time,
179
- rtf_no_vocoder,
180
- )
181
  else:
182
- error_msg = result.get("message", "Unknown error")
183
- return None, f"❌ Synthesis failed: {error_msg}", "", "", "", "", "", ""
184
- else:
 
 
 
185
  return (
186
- None,
187
- f"❌ API returned status code: {response.status_code}",
188
- "",
189
- "",
190
- "",
191
- "",
192
- "",
193
- "",
194
  )
 
 
195
 
196
  except Exception as e:
 
197
  return None, f"❌ Error: {str(e)}", "", "", "", "", "", ""
198
 
199
 
@@ -299,26 +292,15 @@ with gr.Blocks(
299
 
300
  def on_generate(text, voice_display):
301
  voice_id = voice_choices.get(voice_display)
302
- audio_url, _status, t_time, rtf, wav_dur, voc_time, no_voc_time, rtf_no_voc = (
303
  synthesize_speech(text, voice_id)
304
  )
305
 
306
- # Download audio if URL is available
307
- audio_file = None
308
- # Always get fresh counter from file
309
  new_count = load_counter()
310
- if audio_url:
311
- try:
312
- audio_response = requests.get(audio_url, timeout=30)
313
- if audio_response.status_code == 200:
314
- # Save to temporary file
315
- audio_file = f"/tmp/ringg_{str(uuid.uuid4())}.wav"
316
- with open(audio_file, "wb") as f:
317
- f.write(audio_response.content)
318
- # Atomically increment the UNIVERSAL counter
319
- new_count = increment_counter()
320
- except Exception as e:
321
- _status = f"⚠️ Audio generated but download failed: {str(e)}"
322
 
323
  # Format metrics as JSON string (only if available)
324
  has_metrics = any([t_time, rtf, wav_dur, voc_time, no_voc_time, rtf_no_voc])
@@ -345,7 +327,7 @@ with gr.Blocks(
345
 
346
  def refresh_counter_on_load():
347
  """Refresh the universal generation counter when the UI loads/reloads"""
348
- return f"**🌍 Generations:** {load_counter()}"
349
 
350
  # Update character count on text input change
351
  text_input.change(fn=update_char_count, inputs=[text_input], outputs=[char_count])
 
1
  import gradio as gr
 
2
  import json
3
  import os
4
  from pathlib import Path
5
  import uuid
6
  import fcntl
7
  import time
8
+ from vertex_client import get_vertex_client
9
 
10
  # gr.NO_RELOAD = False
 
 
11
 
12
  # Counter persistence file
13
  COUNTER_FILE = Path("generation_counter.json")
 
31
  data = json.load(f)
32
  fcntl.flock(f.fileno(), fcntl.LOCK_UN)
33
  return data.get("count", 0)
34
+ except Exception:
35
  # If locking fails, just read without lock
36
  f.seek(0)
37
  data = json.load(f)
 
52
  f.flush()
53
  os.fsync(f.fileno())
54
  fcntl.flock(f.fileno(), fcntl.LOCK_UN)
55
+ except Exception:
56
  # If locking fails, just write without lock
57
  json.dump({"count": count, "last_updated": time.time()}, f)
58
  f.flush()
 
73
  try:
74
  data = json.load(f)
75
  current_count = data.get("count", 0)
76
+ except Exception:
77
  current_count = 0
78
 
79
  # Increment
 
88
 
89
  fcntl.flock(f.fileno(), fcntl.LOCK_UN)
90
  return new_count
91
+ except Exception:
92
  # Fallback without locking
93
  f.seek(0)
94
  try:
95
  data = json.load(f)
96
  current_count = data.get("count", 0)
97
+ except Exception:
98
  current_count = 0
99
  new_count = current_count + 1
100
  f.seek(0)
 
108
 
109
 
110
  def get_voices():
111
+ """Fetch available voices from Vertex AI"""
112
  try:
113
+ vertex_client = get_vertex_client()
114
+ success, voices_response = vertex_client.get_voices()
115
+
116
+ if success and voices_response:
117
+ print("✅ Fetched voices from Vertex AI")
118
+ voices_data = voices_response.get("voices", {})
119
  # Create a list of tuples (display_name, voice_id)
120
  voices = []
121
  for voice_id, voice_info in voices_data.items():
 
124
  display_name = f"{name} ({gender})"
125
  voices.append((display_name, voice_id))
126
  return sorted(voices, key=lambda x: x[0])
127
+ else:
128
+ print("❌ Failed to fetch voices from Vertex AI")
129
+ return []
130
  except Exception as e:
131
+ print(f"Error fetching voices from Vertex AI: {e}")
132
  return []
133
 
134
 
135
  def synthesize_speech(text, voice_id):
136
+ """Synthesize speech from text using Vertex AI"""
137
  if not text or not text.strip():
138
  return None, "⚠️ Please enter some text", "", "", "", "", "", ""
139
 
 
145
  print(f"Input text length: {text_length} characters")
146
 
147
  try:
148
+ vertex_client = get_vertex_client()
149
+ success, audio_bytes, metrics = vertex_client.synthesize(
150
+ text, voice_id, timeout=60
 
 
 
 
151
  )
152
 
153
+ if success and audio_bytes:
154
+ print("✅ Synthesized audio using Vertex AI")
155
+ # Save binary audio to temp file
156
+ audio_file = f"/tmp/ringg_{str(uuid.uuid4())}.wav"
157
+ with open(audio_file, "wb") as f:
158
+ f.write(audio_bytes)
159
 
160
+ # Format metrics if available
161
+ if metrics:
162
  total_time = f"{metrics.get('t', 0):.3f}s"
163
  rtf = f"{metrics.get('rtf', 0):.4f}"
164
  wav_duration = f"{metrics.get('wav_seconds', 0):.2f}s"
165
  vocoder_time = f"{metrics.get('t_vocoder', 0):.3f}s"
166
  no_vocoder_time = f"{metrics.get('t_no_vocoder', 0):.3f}s"
167
  rtf_no_vocoder = f"{metrics.get('rtf_no_vocoder', 0):.4f}"
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  else:
169
+ total_time = rtf = wav_duration = vocoder_time = no_vocoder_time = (
170
+ rtf_no_vocoder
171
+ ) = ""
172
+
173
+ status_msg = "✅ Audio generated successfully!"
174
+
175
  return (
176
+ audio_file,
177
+ status_msg,
178
+ total_time,
179
+ rtf,
180
+ wav_duration,
181
+ vocoder_time,
182
+ no_vocoder_time,
183
+ rtf_no_vocoder,
184
  )
185
+ else:
186
+ return None, "❌ Failed to generate audio", "", "", "", "", "", ""
187
 
188
  except Exception as e:
189
+ print(f"❌ Vertex AI synthesis failed: {e}")
190
  return None, f"❌ Error: {str(e)}", "", "", "", "", "", ""
191
 
192
 
 
292
 
293
  def on_generate(text, voice_display):
294
  voice_id = voice_choices.get(voice_display)
295
+ audio_file, _status, t_time, rtf, wav_dur, voc_time, no_voc_time, rtf_no_voc = (
296
  synthesize_speech(text, voice_id)
297
  )
298
 
299
+ # Get fresh counter from file
 
 
300
  new_count = load_counter()
301
+ if audio_file:
302
+ # Atomically increment the UNIVERSAL counter
303
+ new_count = increment_counter()
 
 
 
 
 
 
 
 
 
304
 
305
  # Format metrics as JSON string (only if available)
306
  has_metrics = any([t_time, rtf, wav_dur, voc_time, no_voc_time, rtf_no_voc])
 
327
 
328
  def refresh_counter_on_load():
329
  """Refresh the universal generation counter when the UI loads/reloads"""
330
+ return f"**🌍 Generations since last reload:** {load_counter()}"
331
 
332
  # Update character count on text input change
333
  text_input.change(fn=update_char_count, inputs=[text_input], outputs=[char_count])
generation_counter.json CHANGED
@@ -1,2 +1 @@
1
- {"count": 1524, "last_updated": 0}
2
-
 
1
+ {"count": 3, "last_updated": 1762495500.191227}
 
pyproject.toml CHANGED
@@ -5,4 +5,6 @@ requires-python = ">=3.10"
5
  dependencies = [
6
  "gradio>=5.49.1",
7
  "requests>=2.32.5",
 
 
8
  ]
 
5
  dependencies = [
6
  "gradio>=5.49.1",
7
  "requests>=2.32.5",
8
+ "google-cloud-aiplatform>=1.38.0",
9
+ "python-dotenv>=1.0.0",
10
  ]
requirements.txt ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==24.1.0
2
+ annotated-doc==0.0.3
3
+ annotated-types==0.7.0
4
+ anyio==4.11.0
5
+ brotli==1.1.0
6
+ cachetools==6.2.1
7
+ certifi==2025.10.5
8
+ charset-normalizer==3.4.4
9
+ click==8.3.0
10
+ docstring-parser==0.17.0
11
+ fastapi==0.121.0
12
+ ffmpy==0.6.4
13
+ filelock==3.20.0
14
+ fsspec==2025.10.0
15
+ google-api-core==2.28.1
16
+ google-auth==2.43.0
17
+ google-cloud-aiplatform==1.126.1
18
+ google-cloud-bigquery==3.38.0
19
+ google-cloud-core==2.5.0
20
+ google-cloud-resource-manager==1.15.0
21
+ google-cloud-storage==3.5.0
22
+ google-crc32c==1.7.1
23
+ google-genai==1.49.0
24
+ google-resumable-media==2.7.2
25
+ googleapis-common-protos==1.72.0
26
+ gradio==5.49.1
27
+ gradio-client==1.13.3
28
+ groovy==0.1.2
29
+ grpc-google-iam-v1==0.14.3
30
+ grpcio==1.76.0
31
+ grpcio-status==1.76.0
32
+ h11==0.16.0
33
+ hf-xet==1.2.0
34
+ httpcore==1.0.9
35
+ httpx==0.28.1
36
+ huggingface-hub==1.0.1
37
+ idna==3.11
38
+ jinja2==3.1.6
39
+ markdown-it-py==4.0.0
40
+ markupsafe==3.0.3
41
+ mdurl==0.1.2
42
+ numpy==2.3.4
43
+ orjson==3.11.4
44
+ packaging==25.0
45
+ pandas==2.3.3
46
+ pillow==11.3.0
47
+ proto-plus==1.26.1
48
+ protobuf==6.33.0
49
+ pyasn1==0.6.1
50
+ pyasn1-modules==0.4.2
51
+ pydantic==2.11.10
52
+ pydantic-core==2.33.2
53
+ pydub==0.25.1
54
+ pygments==2.19.2
55
+ python-dateutil==2.9.0.post0
56
+ python-dotenv==1.2.1
57
+ python-multipart==0.0.20
58
+ pytz==2025.2
59
+ pyyaml==6.0.3
60
+ requests==2.32.5
61
+ rich==14.2.0
62
+ rsa==4.9.1
63
+ ruff==0.14.3
64
+ safehttpx==0.1.7
65
+ semantic-version==2.10.0
66
+ shapely==2.1.2
67
+ shellingham==1.5.4
68
+ six==1.17.0
69
+ sniffio==1.3.1
70
+ starlette==0.49.3
71
+ tenacity==9.1.2
72
+ tomlkit==0.13.3
73
+ tqdm==4.67.1
74
+ typer==0.20.0
75
+ typer-slim==0.20.0
76
+ typing-extensions==4.15.0
77
+ typing-inspection==0.4.2
78
+ tzdata==2025.2
79
+ urllib3==2.5.0
80
+ uvicorn==0.38.0
81
+ websockets==15.0.1
uv.lock CHANGED
@@ -2,7 +2,8 @@ version = 1
2
  revision = 2
3
  requires-python = ">=3.10"
4
  resolution-markers = [
5
- "python_full_version >= '3.13'",
 
6
  "python_full_version == '3.12.*'",
7
  "python_full_version == '3.11.*'",
8
  "python_full_version < '3.11'",
@@ -176,6 +177,15 @@ wheels = [
176
  { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517, upload_time = "2024-10-18T12:32:54.066Z" },
177
  ]
178
 
 
 
 
 
 
 
 
 
 
179
  [[package]]
180
  name = "certifi"
181
  version = "2025.10.5"
@@ -295,6 +305,15 @@ wheels = [
295
  { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload_time = "2022-10-25T02:36:20.889Z" },
296
  ]
297
 
 
 
 
 
 
 
 
 
 
298
  [[package]]
299
  name = "exceptiongroup"
300
  version = "1.3.0"
@@ -349,6 +368,214 @@ wheels = [
349
  { url = "https://files.pythonhosted.org/packages/eb/02/a6b21098b1d5d6249b7c5ab69dde30108a71e4e819d4a9778f1de1d5b70d/fsspec-2025.10.0-py3-none-any.whl", hash = "sha256:7c7712353ae7d875407f97715f0e1ffcc21e33d5b24556cb1e090ae9409ec61d", size = 200966, upload_time = "2025-10-30T14:58:42.53Z" },
350
  ]
351
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  [[package]]
353
  name = "gradio"
354
  version = "5.49.1"
@@ -416,6 +643,95 @@ wheels = [
416
  { url = "https://files.pythonhosted.org/packages/28/27/3d6dcadc8a3214d8522c1e7f6a19554e33659be44546d44a2f7572ac7d2a/groovy-0.1.2-py3-none-any.whl", hash = "sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64", size = 14090, upload_time = "2025-02-28T20:24:55.152Z" },
417
  ]
418
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  [[package]]
420
  name = "h11"
421
  version = "0.16.0"
@@ -700,7 +1016,8 @@ name = "numpy"
700
  version = "2.3.4"
701
  source = { registry = "https://pypi.org/simple" }
702
  resolution-markers = [
703
- "python_full_version >= '3.13'",
 
704
  "python_full_version == '3.12.*'",
705
  "python_full_version == '3.11.*'",
706
  ]
@@ -1035,6 +1352,54 @@ wheels = [
1035
  { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload_time = "2025-07-01T09:16:27.732Z" },
1036
  ]
1037
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1038
  [[package]]
1039
  name = "pydantic"
1040
  version = "2.11.10"
@@ -1167,6 +1532,15 @@ wheels = [
1167
  { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload_time = "2024-03-01T18:36:18.57Z" },
1168
  ]
1169
 
 
 
 
 
 
 
 
 
 
1170
  [[package]]
1171
  name = "python-multipart"
1172
  version = "0.0.20"
@@ -1282,16 +1656,32 @@ name = "ringg-tts-v1-0"
1282
  version = "0.1.0"
1283
  source = { virtual = "." }
1284
  dependencies = [
 
1285
  { name = "gradio" },
 
1286
  { name = "requests" },
1287
  ]
1288
 
1289
  [package.metadata]
1290
  requires-dist = [
 
1291
  { name = "gradio", specifier = ">=5.49.1" },
 
1292
  { name = "requests", specifier = ">=2.32.5" },
1293
  ]
1294
 
 
 
 
 
 
 
 
 
 
 
 
 
1295
  [[package]]
1296
  name = "ruff"
1297
  version = "0.14.3"
@@ -1339,6 +1729,74 @@ wheels = [
1339
  { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552, upload_time = "2022-05-26T13:35:21.206Z" },
1340
  ]
1341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1342
  [[package]]
1343
  name = "shellingham"
1344
  version = "1.5.4"
@@ -1379,6 +1837,15 @@ wheels = [
1379
  { url = "https://files.pythonhosted.org/packages/a3/e0/021c772d6a662f43b63044ab481dc6ac7592447605b5b35a957785363122/starlette-0.49.3-py3-none-any.whl", hash = "sha256:b579b99715fdc2980cf88c8ec96d3bf1ce16f5a8051a7c2b84ef9b1cdecaea2f", size = 74340, upload_time = "2025-11-01T15:12:24.387Z" },
1380
  ]
1381
 
 
 
 
 
 
 
 
 
 
1382
  [[package]]
1383
  name = "tomlkit"
1384
  version = "0.13.3"
 
2
  revision = 2
3
  requires-python = ">=3.10"
4
  resolution-markers = [
5
+ "python_full_version >= '3.14'",
6
+ "python_full_version == '3.13.*'",
7
  "python_full_version == '3.12.*'",
8
  "python_full_version == '3.11.*'",
9
  "python_full_version < '3.11'",
 
177
  { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517, upload_time = "2024-10-18T12:32:54.066Z" },
178
  ]
179
 
180
+ [[package]]
181
+ name = "cachetools"
182
+ version = "6.2.1"
183
+ source = { registry = "https://pypi.org/simple" }
184
+ sdist = { url = "https://files.pythonhosted.org/packages/cc/7e/b975b5814bd36faf009faebe22c1072a1fa1168db34d285ef0ba071ad78c/cachetools-6.2.1.tar.gz", hash = "sha256:3f391e4bd8f8bf0931169baf7456cc822705f4e2a31f840d218f445b9a854201", size = 31325, upload_time = "2025-10-12T14:55:30.139Z" }
185
+ wheels = [
186
+ { url = "https://files.pythonhosted.org/packages/96/c5/1e741d26306c42e2bf6ab740b2202872727e0f606033c9dd713f8b93f5a8/cachetools-6.2.1-py3-none-any.whl", hash = "sha256:09868944b6dde876dfd44e1d47e18484541eaf12f26f29b7af91b26cc892d701", size = 11280, upload_time = "2025-10-12T14:55:28.382Z" },
187
+ ]
188
+
189
  [[package]]
190
  name = "certifi"
191
  version = "2025.10.5"
 
305
  { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload_time = "2022-10-25T02:36:20.889Z" },
306
  ]
307
 
308
+ [[package]]
309
+ name = "docstring-parser"
310
+ version = "0.17.0"
311
+ source = { registry = "https://pypi.org/simple" }
312
+ sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload_time = "2025-07-21T07:35:01.868Z" }
313
+ wheels = [
314
+ { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload_time = "2025-07-21T07:35:00.684Z" },
315
+ ]
316
+
317
  [[package]]
318
  name = "exceptiongroup"
319
  version = "1.3.0"
 
368
  { url = "https://files.pythonhosted.org/packages/eb/02/a6b21098b1d5d6249b7c5ab69dde30108a71e4e819d4a9778f1de1d5b70d/fsspec-2025.10.0-py3-none-any.whl", hash = "sha256:7c7712353ae7d875407f97715f0e1ffcc21e33d5b24556cb1e090ae9409ec61d", size = 200966, upload_time = "2025-10-30T14:58:42.53Z" },
369
  ]
370
 
371
+ [[package]]
372
+ name = "google-api-core"
373
+ version = "2.28.1"
374
+ source = { registry = "https://pypi.org/simple" }
375
+ dependencies = [
376
+ { name = "google-auth" },
377
+ { name = "googleapis-common-protos" },
378
+ { name = "proto-plus" },
379
+ { name = "protobuf" },
380
+ { name = "requests" },
381
+ ]
382
+ sdist = { url = "https://files.pythonhosted.org/packages/61/da/83d7043169ac2c8c7469f0e375610d78ae2160134bf1b80634c482fa079c/google_api_core-2.28.1.tar.gz", hash = "sha256:2b405df02d68e68ce0fbc138559e6036559e685159d148ae5861013dc201baf8", size = 176759, upload_time = "2025-10-28T21:34:51.529Z" }
383
+ wheels = [
384
+ { url = "https://files.pythonhosted.org/packages/ed/d4/90197b416cb61cefd316964fd9e7bd8324bcbafabf40eef14a9f20b81974/google_api_core-2.28.1-py3-none-any.whl", hash = "sha256:4021b0f8ceb77a6fb4de6fde4502cecab45062e66ff4f2895169e0b35bc9466c", size = 173706, upload_time = "2025-10-28T21:34:50.151Z" },
385
+ ]
386
+
387
+ [package.optional-dependencies]
388
+ grpc = [
389
+ { name = "grpcio" },
390
+ { name = "grpcio-status" },
391
+ ]
392
+
393
+ [[package]]
394
+ name = "google-auth"
395
+ version = "2.43.0"
396
+ source = { registry = "https://pypi.org/simple" }
397
+ dependencies = [
398
+ { name = "cachetools" },
399
+ { name = "pyasn1-modules" },
400
+ { name = "rsa" },
401
+ ]
402
+ sdist = { url = "https://files.pythonhosted.org/packages/ff/ef/66d14cf0e01b08d2d51ffc3c20410c4e134a1548fc246a6081eae585a4fe/google_auth-2.43.0.tar.gz", hash = "sha256:88228eee5fc21b62a1b5fe773ca15e67778cb07dc8363adcb4a8827b52d81483", size = 296359, upload_time = "2025-11-06T00:13:36.587Z" }
403
+ wheels = [
404
+ { url = "https://files.pythonhosted.org/packages/6f/d1/385110a9ae86d91cc14c5282c61fe9f4dc41c0b9f7d423c6ad77038c4448/google_auth-2.43.0-py2.py3-none-any.whl", hash = "sha256:af628ba6fa493f75c7e9dbe9373d148ca9f4399b5ea29976519e0a3848eddd16", size = 223114, upload_time = "2025-11-06T00:13:35.209Z" },
405
+ ]
406
+
407
+ [[package]]
408
+ name = "google-cloud-aiplatform"
409
+ version = "1.126.1"
410
+ source = { registry = "https://pypi.org/simple" }
411
+ dependencies = [
412
+ { name = "docstring-parser" },
413
+ { name = "google-api-core", extra = ["grpc"] },
414
+ { name = "google-auth" },
415
+ { name = "google-cloud-bigquery" },
416
+ { name = "google-cloud-resource-manager" },
417
+ { name = "google-cloud-storage" },
418
+ { name = "google-genai" },
419
+ { name = "packaging" },
420
+ { name = "proto-plus" },
421
+ { name = "protobuf" },
422
+ { name = "pydantic" },
423
+ { name = "shapely" },
424
+ { name = "typing-extensions" },
425
+ ]
426
+ sdist = { url = "https://files.pythonhosted.org/packages/0c/36/f8e41679e6cb7ea6b50c0bfeaea0b9daf1475cafa152ad30456f6ec5471f/google_cloud_aiplatform-1.126.1.tar.gz", hash = "sha256:956706c587b817e36d5a16af5ab7f48c73dde76c71d660ecd4284f0339dc37d4", size = 9777644, upload_time = "2025-11-06T22:00:52.894Z" }
427
+ wheels = [
428
+ { url = "https://files.pythonhosted.org/packages/b2/c6/3dc21f6182703d170624ed9f87894d35e1d51d1facbb471aa62cc255f233/google_cloud_aiplatform-1.126.1-py2.py3-none-any.whl", hash = "sha256:66d4daea95356d772ff026f13448ea80aa763dfd8daedc21d9ca36d0a1ee8a65", size = 8123682, upload_time = "2025-11-06T22:00:49.874Z" },
429
+ ]
430
+
431
+ [[package]]
432
+ name = "google-cloud-bigquery"
433
+ version = "3.38.0"
434
+ source = { registry = "https://pypi.org/simple" }
435
+ dependencies = [
436
+ { name = "google-api-core", extra = ["grpc"] },
437
+ { name = "google-auth" },
438
+ { name = "google-cloud-core" },
439
+ { name = "google-resumable-media" },
440
+ { name = "packaging" },
441
+ { name = "python-dateutil" },
442
+ { name = "requests" },
443
+ ]
444
+ sdist = { url = "https://files.pythonhosted.org/packages/07/b2/a17e40afcf9487e3d17db5e36728ffe75c8d5671c46f419d7b6528a5728a/google_cloud_bigquery-3.38.0.tar.gz", hash = "sha256:8afcb7116f5eac849097a344eb8bfda78b7cfaae128e60e019193dd483873520", size = 503666, upload_time = "2025-09-17T20:33:33.47Z" }
445
+ wheels = [
446
+ { url = "https://files.pythonhosted.org/packages/39/3c/c8cada9ec282b29232ed9aed5a0b5cca6cf5367cb2ffa8ad0d2583d743f1/google_cloud_bigquery-3.38.0-py3-none-any.whl", hash = "sha256:e06e93ff7b245b239945ef59cb59616057598d369edac457ebf292bd61984da6", size = 259257, upload_time = "2025-09-17T20:33:31.404Z" },
447
+ ]
448
+
449
+ [[package]]
450
+ name = "google-cloud-core"
451
+ version = "2.5.0"
452
+ source = { registry = "https://pypi.org/simple" }
453
+ dependencies = [
454
+ { name = "google-api-core" },
455
+ { name = "google-auth" },
456
+ ]
457
+ sdist = { url = "https://files.pythonhosted.org/packages/a6/03/ef0bc99d0e0faf4fdbe67ac445e18cdaa74824fd93cd069e7bb6548cb52d/google_cloud_core-2.5.0.tar.gz", hash = "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963", size = 36027, upload_time = "2025-10-29T23:17:39.513Z" }
458
+ wheels = [
459
+ { url = "https://files.pythonhosted.org/packages/89/20/bfa472e327c8edee00f04beecc80baeddd2ab33ee0e86fd7654da49d45e9/google_cloud_core-2.5.0-py3-none-any.whl", hash = "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc", size = 29469, upload_time = "2025-10-29T23:17:38.548Z" },
460
+ ]
461
+
462
+ [[package]]
463
+ name = "google-cloud-resource-manager"
464
+ version = "1.15.0"
465
+ source = { registry = "https://pypi.org/simple" }
466
+ dependencies = [
467
+ { name = "google-api-core", extra = ["grpc"] },
468
+ { name = "google-auth" },
469
+ { name = "grpc-google-iam-v1" },
470
+ { name = "grpcio" },
471
+ { name = "proto-plus" },
472
+ { name = "protobuf" },
473
+ ]
474
+ sdist = { url = "https://files.pythonhosted.org/packages/fc/19/b95d0e8814ce42522e434cdd85c0cb6236d874d9adf6685fc8e6d1fda9d1/google_cloud_resource_manager-1.15.0.tar.gz", hash = "sha256:3d0b78c3daa713f956d24e525b35e9e9a76d597c438837171304d431084cedaf", size = 449227, upload_time = "2025-10-20T14:57:01.108Z" }
475
+ wheels = [
476
+ { url = "https://files.pythonhosted.org/packages/8c/93/5aef41a5f146ad4559dd7040ae5fa8e7ddcab4dfadbef6cb4b66d775e690/google_cloud_resource_manager-1.15.0-py3-none-any.whl", hash = "sha256:0ccde5db644b269ddfdf7b407a2c7b60bdbf459f8e666344a5285601d00c7f6d", size = 397151, upload_time = "2025-10-20T14:53:45.409Z" },
477
+ ]
478
+
479
+ [[package]]
480
+ name = "google-cloud-storage"
481
+ version = "3.5.0"
482
+ source = { registry = "https://pypi.org/simple" }
483
+ dependencies = [
484
+ { name = "google-api-core" },
485
+ { name = "google-auth" },
486
+ { name = "google-cloud-core" },
487
+ { name = "google-crc32c" },
488
+ { name = "google-resumable-media" },
489
+ { name = "requests" },
490
+ ]
491
+ sdist = { url = "https://files.pythonhosted.org/packages/6d/98/c0c6d10f893509585c755a6567689e914df3501ae269f46b0d67d7e7c70a/google_cloud_storage-3.5.0.tar.gz", hash = "sha256:10b89e1d1693114b3e0ca921bdd28c5418701fd092e39081bb77e5cee0851ab7", size = 17242207, upload_time = "2025-11-05T12:41:02.715Z" }
492
+ wheels = [
493
+ { url = "https://files.pythonhosted.org/packages/20/81/a567236070e7fe79a17a11b118d7f5ce4adefe2edd18caf1824d7e29a30a/google_cloud_storage-3.5.0-py3-none-any.whl", hash = "sha256:e28fd6ad8764e60dbb9a398a7bc3296e7920c494bc329057d828127e5f9630d3", size = 289998, upload_time = "2025-11-05T12:41:01.212Z" },
494
+ ]
495
+
496
+ [[package]]
497
+ name = "google-crc32c"
498
+ version = "1.7.1"
499
+ source = { registry = "https://pypi.org/simple" }
500
+ sdist = { url = "https://files.pythonhosted.org/packages/19/ae/87802e6d9f9d69adfaedfcfd599266bf386a54d0be058b532d04c794f76d/google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472", size = 14495, upload_time = "2025-03-26T14:29:13.32Z" }
501
+ wheels = [
502
+ { url = "https://files.pythonhosted.org/packages/eb/69/b1b05cf415df0d86691d6a8b4b7e60ab3a6fb6efb783ee5cd3ed1382bfd3/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:b07d48faf8292b4db7c3d64ab86f950c2e94e93a11fd47271c28ba458e4a0d76", size = 30467, upload_time = "2025-03-26T14:31:11.92Z" },
503
+ { url = "https://files.pythonhosted.org/packages/44/3d/92f8928ecd671bd5b071756596971c79d252d09b835cdca5a44177fa87aa/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7cc81b3a2fbd932a4313eb53cc7d9dde424088ca3a0337160f35d91826880c1d", size = 30311, upload_time = "2025-03-26T14:53:14.161Z" },
504
+ { url = "https://files.pythonhosted.org/packages/33/42/c2d15a73df79d45ed6b430b9e801d0bd8e28ac139a9012d7d58af50a385d/google_crc32c-1.7.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c67ca0a1f5b56162951a9dae987988679a7db682d6f97ce0f6381ebf0fbea4c", size = 37889, upload_time = "2025-03-26T14:41:27.83Z" },
505
+ { url = "https://files.pythonhosted.org/packages/57/ea/ac59c86a3c694afd117bb669bde32aaf17d0de4305d01d706495f09cbf19/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc5319db92daa516b653600794d5b9f9439a9a121f3e162f94b0e1891c7933cb", size = 33028, upload_time = "2025-03-26T14:41:29.141Z" },
506
+ { url = "https://files.pythonhosted.org/packages/60/44/87e77e8476767a4a93f6cf271157c6d948eacec63688c093580af13b04be/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcdf5a64adb747610140572ed18d011896e3b9ae5195f2514b7ff678c80f1603", size = 38026, upload_time = "2025-03-26T14:41:29.921Z" },
507
+ { url = "https://files.pythonhosted.org/packages/c8/bf/21ac7bb305cd7c1a6de9c52f71db0868e104a5b573a4977cd9d0ff830f82/google_crc32c-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:754561c6c66e89d55754106739e22fdaa93fafa8da7221b29c8b8e8270c6ec8a", size = 33476, upload_time = "2025-03-26T14:29:09.086Z" },
508
+ { url = "https://files.pythonhosted.org/packages/f7/94/220139ea87822b6fdfdab4fb9ba81b3fff7ea2c82e2af34adc726085bffc/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6fbab4b935989e2c3610371963ba1b86afb09537fd0c633049be82afe153ac06", size = 30468, upload_time = "2025-03-26T14:32:52.215Z" },
509
+ { url = "https://files.pythonhosted.org/packages/94/97/789b23bdeeb9d15dc2904660463ad539d0318286d7633fe2760c10ed0c1c/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ed66cbe1ed9cbaaad9392b5259b3eba4a9e565420d734e6238813c428c3336c9", size = 30313, upload_time = "2025-03-26T14:57:38.758Z" },
510
+ { url = "https://files.pythonhosted.org/packages/81/b8/976a2b843610c211e7ccb3e248996a61e87dbb2c09b1499847e295080aec/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6547b657621b6cbed3562ea7826c3e11cab01cd33b74e1f677690652883e77", size = 33048, upload_time = "2025-03-26T14:41:30.679Z" },
511
+ { url = "https://files.pythonhosted.org/packages/c9/16/a3842c2cf591093b111d4a5e2bfb478ac6692d02f1b386d2a33283a19dc9/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68e17bad8f7dd9a49181a1f5a8f4b251c6dbc8cc96fb79f1d321dfd57d66f53", size = 32669, upload_time = "2025-03-26T14:41:31.432Z" },
512
+ { url = "https://files.pythonhosted.org/packages/04/17/ed9aba495916fcf5fe4ecb2267ceb851fc5f273c4e4625ae453350cfd564/google_crc32c-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:6335de12921f06e1f774d0dd1fbea6bf610abe0887a1638f64d694013138be5d", size = 33476, upload_time = "2025-03-26T14:29:10.211Z" },
513
+ { url = "https://files.pythonhosted.org/packages/dd/b7/787e2453cf8639c94b3d06c9d61f512234a82e1d12d13d18584bd3049904/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2d73a68a653c57281401871dd4aeebbb6af3191dcac751a76ce430df4d403194", size = 30470, upload_time = "2025-03-26T14:34:31.655Z" },
514
+ { url = "https://files.pythonhosted.org/packages/ed/b4/6042c2b0cbac3ec3a69bb4c49b28d2f517b7a0f4a0232603c42c58e22b44/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:22beacf83baaf59f9d3ab2bbb4db0fb018da8e5aebdce07ef9f09fce8220285e", size = 30315, upload_time = "2025-03-26T15:01:54.634Z" },
515
+ { url = "https://files.pythonhosted.org/packages/29/ad/01e7a61a5d059bc57b702d9ff6a18b2585ad97f720bd0a0dbe215df1ab0e/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19eafa0e4af11b0a4eb3974483d55d2d77ad1911e6cf6f832e1574f6781fd337", size = 33180, upload_time = "2025-03-26T14:41:32.168Z" },
516
+ { url = "https://files.pythonhosted.org/packages/3b/a5/7279055cf004561894ed3a7bfdf5bf90a53f28fadd01af7cd166e88ddf16/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d86616faaea68101195c6bdc40c494e4d76f41e07a37ffdef270879c15fb65", size = 32794, upload_time = "2025-03-26T14:41:33.264Z" },
517
+ { url = "https://files.pythonhosted.org/packages/0f/d6/77060dbd140c624e42ae3ece3df53b9d811000729a5c821b9fd671ceaac6/google_crc32c-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:b7491bdc0c7564fcf48c0179d2048ab2f7c7ba36b84ccd3a3e1c3f7a72d3bba6", size = 33477, upload_time = "2025-03-26T14:29:10.94Z" },
518
+ { url = "https://files.pythonhosted.org/packages/8b/72/b8d785e9184ba6297a8620c8a37cf6e39b81a8ca01bb0796d7cbb28b3386/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:df8b38bdaf1629d62d51be8bdd04888f37c451564c2042d36e5812da9eff3c35", size = 30467, upload_time = "2025-03-26T14:36:06.909Z" },
519
+ { url = "https://files.pythonhosted.org/packages/34/25/5f18076968212067c4e8ea95bf3b69669f9fc698476e5f5eb97d5b37999f/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:e42e20a83a29aa2709a0cf271c7f8aefaa23b7ab52e53b322585297bb94d4638", size = 30309, upload_time = "2025-03-26T15:06:15.318Z" },
520
+ { url = "https://files.pythonhosted.org/packages/92/83/9228fe65bf70e93e419f38bdf6c5ca5083fc6d32886ee79b450ceefd1dbd/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:905a385140bf492ac300026717af339790921f411c0dfd9aa5a9e69a08ed32eb", size = 33133, upload_time = "2025-03-26T14:41:34.388Z" },
521
+ { url = "https://files.pythonhosted.org/packages/c3/ca/1ea2fd13ff9f8955b85e7956872fdb7050c4ace8a2306a6d177edb9cf7fe/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b211ddaf20f7ebeec5c333448582c224a7c90a9d98826fbab82c0ddc11348e6", size = 32773, upload_time = "2025-03-26T14:41:35.19Z" },
522
+ { url = "https://files.pythonhosted.org/packages/89/32/a22a281806e3ef21b72db16f948cad22ec68e4bdd384139291e00ff82fe2/google_crc32c-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:0f99eaa09a9a7e642a61e06742856eec8b19fc0037832e03f941fe7cf0c8e4db", size = 33475, upload_time = "2025-03-26T14:29:11.771Z" },
523
+ { url = "https://files.pythonhosted.org/packages/b8/c5/002975aff514e57fc084ba155697a049b3f9b52225ec3bc0f542871dd524/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d1da0d74ec5634a05f53ef7df18fc646666a25efaaca9fc7dcfd4caf1d98c3", size = 33243, upload_time = "2025-03-26T14:41:35.975Z" },
524
+ { url = "https://files.pythonhosted.org/packages/61/cb/c585282a03a0cea70fcaa1bf55d5d702d0f2351094d663ec3be1c6c67c52/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10554d4abc5238823112c2ad7e4560f96c7bf3820b202660373d769d9e6e4c9", size = 32870, upload_time = "2025-03-26T14:41:37.08Z" },
525
+ { url = "https://files.pythonhosted.org/packages/0b/43/31e57ce04530794917dfe25243860ec141de9fadf4aa9783dffe7dac7c39/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8e9afc74168b0b2232fb32dd202c93e46b7d5e4bf03e66ba5dc273bb3559589", size = 28242, upload_time = "2025-03-26T14:41:42.858Z" },
526
+ { url = "https://files.pythonhosted.org/packages/eb/f3/8b84cd4e0ad111e63e30eb89453f8dd308e3ad36f42305cf8c202461cdf0/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa8136cc14dd27f34a3221c0f16fd42d8a40e4778273e61a3c19aedaa44daf6b", size = 28049, upload_time = "2025-03-26T14:41:44.651Z" },
527
+ { url = "https://files.pythonhosted.org/packages/16/1b/1693372bf423ada422f80fd88260dbfd140754adb15cbc4d7e9a68b1cb8e/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85fef7fae11494e747c9fd1359a527e5970fc9603c90764843caabd3a16a0a48", size = 28241, upload_time = "2025-03-26T14:41:45.898Z" },
528
+ { url = "https://files.pythonhosted.org/packages/fd/3c/2a19a60a473de48717b4efb19398c3f914795b64a96cf3fbe82588044f78/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6efb97eb4369d52593ad6f75e7e10d053cf00c48983f7a973105bc70b0ac4d82", size = 28048, upload_time = "2025-03-26T14:41:46.696Z" },
529
+ ]
530
+
531
+ [[package]]
532
+ name = "google-genai"
533
+ version = "1.49.0"
534
+ source = { registry = "https://pypi.org/simple" }
535
+ dependencies = [
536
+ { name = "anyio" },
537
+ { name = "google-auth" },
538
+ { name = "httpx" },
539
+ { name = "pydantic" },
540
+ { name = "requests" },
541
+ { name = "tenacity" },
542
+ { name = "typing-extensions" },
543
+ { name = "websockets" },
544
+ ]
545
+ sdist = { url = "https://files.pythonhosted.org/packages/82/49/1a724ee3c3748fa50721d53a52d9fee88c67d0c43bb16eb2b10ee89ab239/google_genai-1.49.0.tar.gz", hash = "sha256:35eb16023b72e298571ae30e919c810694f258f2ba68fc77a2185c7c8829ad5a", size = 253493, upload_time = "2025-11-05T22:41:03.278Z" }
546
+ wheels = [
547
+ { url = "https://files.pythonhosted.org/packages/d5/d3/84a152746dc7bdebb8ba0fd7d6157263044acd1d14b2a53e8df4a307b6b7/google_genai-1.49.0-py3-none-any.whl", hash = "sha256:ad49cd5be5b63397069e7aef9a4fe0a84cbdf25fcd93408e795292308db4ef32", size = 256098, upload_time = "2025-11-05T22:41:01.429Z" },
548
+ ]
549
+
550
+ [[package]]
551
+ name = "google-resumable-media"
552
+ version = "2.7.2"
553
+ source = { registry = "https://pypi.org/simple" }
554
+ dependencies = [
555
+ { name = "google-crc32c" },
556
+ ]
557
+ sdist = { url = "https://files.pythonhosted.org/packages/58/5a/0efdc02665dca14e0837b62c8a1a93132c264bd02054a15abb2218afe0ae/google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0", size = 2163099, upload_time = "2024-08-07T22:20:38.555Z" }
558
+ wheels = [
559
+ { url = "https://files.pythonhosted.org/packages/82/35/b8d3baf8c46695858cb9d8835a53baa1eeb9906ddaf2f728a5f5b640fd1e/google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa", size = 81251, upload_time = "2024-08-07T22:20:36.409Z" },
560
+ ]
561
+
562
+ [[package]]
563
+ name = "googleapis-common-protos"
564
+ version = "1.72.0"
565
+ source = { registry = "https://pypi.org/simple" }
566
+ dependencies = [
567
+ { name = "protobuf" },
568
+ ]
569
+ sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload_time = "2025-11-06T18:29:24.087Z" }
570
+ wheels = [
571
+ { url = "https://files.pythonhosted.org/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515, upload_time = "2025-11-06T18:29:13.14Z" },
572
+ ]
573
+
574
+ [package.optional-dependencies]
575
+ grpc = [
576
+ { name = "grpcio" },
577
+ ]
578
+
579
  [[package]]
580
  name = "gradio"
581
  version = "5.49.1"
 
643
  { url = "https://files.pythonhosted.org/packages/28/27/3d6dcadc8a3214d8522c1e7f6a19554e33659be44546d44a2f7572ac7d2a/groovy-0.1.2-py3-none-any.whl", hash = "sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64", size = 14090, upload_time = "2025-02-28T20:24:55.152Z" },
644
  ]
645
 
646
+ [[package]]
647
+ name = "grpc-google-iam-v1"
648
+ version = "0.14.3"
649
+ source = { registry = "https://pypi.org/simple" }
650
+ dependencies = [
651
+ { name = "googleapis-common-protos", extra = ["grpc"] },
652
+ { name = "grpcio" },
653
+ { name = "protobuf" },
654
+ ]
655
+ sdist = { url = "https://files.pythonhosted.org/packages/76/1e/1011451679a983f2f5c6771a1682542ecb027776762ad031fd0d7129164b/grpc_google_iam_v1-0.14.3.tar.gz", hash = "sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389", size = 23745, upload_time = "2025-10-15T21:14:53.318Z" }
656
+ wheels = [
657
+ { url = "https://files.pythonhosted.org/packages/4a/bd/330a1bbdb1afe0b96311249e699b6dc9cfc17916394fd4503ac5aca2514b/grpc_google_iam_v1-0.14.3-py3-none-any.whl", hash = "sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6", size = 32690, upload_time = "2025-10-15T21:14:51.72Z" },
658
+ ]
659
+
660
+ [[package]]
661
+ name = "grpcio"
662
+ version = "1.76.0"
663
+ source = { registry = "https://pypi.org/simple" }
664
+ dependencies = [
665
+ { name = "typing-extensions" },
666
+ ]
667
+ sdist = { url = "https://files.pythonhosted.org/packages/b6/e0/318c1ce3ae5a17894d5791e87aea147587c9e702f24122cc7a5c8bbaeeb1/grpcio-1.76.0.tar.gz", hash = "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", size = 12785182, upload_time = "2025-10-21T16:23:12.106Z" }
668
+ wheels = [
669
+ { url = "https://files.pythonhosted.org/packages/88/17/ff4795dc9a34b6aee6ec379f1b66438a3789cd1315aac0cbab60d92f74b3/grpcio-1.76.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:65a20de41e85648e00305c1bb09a3598f840422e522277641145a32d42dcefcc", size = 5840037, upload_time = "2025-10-21T16:20:25.069Z" },
670
+ { url = "https://files.pythonhosted.org/packages/4e/ff/35f9b96e3fa2f12e1dcd58a4513a2e2294a001d64dec81677361b7040c9a/grpcio-1.76.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:40ad3afe81676fd9ec6d9d406eda00933f218038433980aa19d401490e46ecde", size = 11836482, upload_time = "2025-10-21T16:20:30.113Z" },
671
+ { url = "https://files.pythonhosted.org/packages/3e/1c/8374990f9545e99462caacea5413ed783014b3b66ace49e35c533f07507b/grpcio-1.76.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:035d90bc79eaa4bed83f524331d55e35820725c9fbb00ffa1904d5550ed7ede3", size = 6407178, upload_time = "2025-10-21T16:20:32.733Z" },
672
+ { url = "https://files.pythonhosted.org/packages/1e/77/36fd7d7c75a6c12542c90a6d647a27935a1ecaad03e0ffdb7c42db6b04d2/grpcio-1.76.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4215d3a102bd95e2e11b5395c78562967959824156af11fa93d18fdd18050990", size = 7075684, upload_time = "2025-10-21T16:20:35.435Z" },
673
+ { url = "https://files.pythonhosted.org/packages/38/f7/e3cdb252492278e004722306c5a8935eae91e64ea11f0af3437a7de2e2b7/grpcio-1.76.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:49ce47231818806067aea3324d4bf13825b658ad662d3b25fada0bdad9b8a6af", size = 6611133, upload_time = "2025-10-21T16:20:37.541Z" },
674
+ { url = "https://files.pythonhosted.org/packages/7e/20/340db7af162ccd20a0893b5f3c4a5d676af7b71105517e62279b5b61d95a/grpcio-1.76.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8cc3309d8e08fd79089e13ed4819d0af72aa935dd8f435a195fd152796752ff2", size = 7195507, upload_time = "2025-10-21T16:20:39.643Z" },
675
+ { url = "https://files.pythonhosted.org/packages/10/f0/b2160addc1487bd8fa4810857a27132fb4ce35c1b330c2f3ac45d697b106/grpcio-1.76.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:971fd5a1d6e62e00d945423a567e42eb1fa678ba89072832185ca836a94daaa6", size = 8160651, upload_time = "2025-10-21T16:20:42.492Z" },
676
+ { url = "https://files.pythonhosted.org/packages/2c/2c/ac6f98aa113c6ef111b3f347854e99ebb7fb9d8f7bb3af1491d438f62af4/grpcio-1.76.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d9adda641db7207e800a7f089068f6f645959f2df27e870ee81d44701dd9db3", size = 7620568, upload_time = "2025-10-21T16:20:45.995Z" },
677
+ { url = "https://files.pythonhosted.org/packages/90/84/7852f7e087285e3ac17a2703bc4129fafee52d77c6c82af97d905566857e/grpcio-1.76.0-cp310-cp310-win32.whl", hash = "sha256:063065249d9e7e0782d03d2bca50787f53bd0fb89a67de9a7b521c4a01f1989b", size = 3998879, upload_time = "2025-10-21T16:20:48.592Z" },
678
+ { url = "https://files.pythonhosted.org/packages/10/30/d3d2adcbb6dd3ff59d6ac3df6ef830e02b437fb5c90990429fd180e52f30/grpcio-1.76.0-cp310-cp310-win_amd64.whl", hash = "sha256:a6ae758eb08088d36812dd5d9af7a9859c05b1e0f714470ea243694b49278e7b", size = 4706892, upload_time = "2025-10-21T16:20:50.697Z" },
679
+ { url = "https://files.pythonhosted.org/packages/a0/00/8163a1beeb6971f66b4bbe6ac9457b97948beba8dd2fc8e1281dce7f79ec/grpcio-1.76.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2e1743fbd7f5fa713a1b0a8ac8ebabf0ec980b5d8809ec358d488e273b9cf02a", size = 5843567, upload_time = "2025-10-21T16:20:52.829Z" },
680
+ { url = "https://files.pythonhosted.org/packages/10/c1/934202f5cf335e6d852530ce14ddb0fef21be612ba9ecbbcbd4d748ca32d/grpcio-1.76.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:a8c2cf1209497cf659a667d7dea88985e834c24b7c3b605e6254cbb5076d985c", size = 11848017, upload_time = "2025-10-21T16:20:56.705Z" },
681
+ { url = "https://files.pythonhosted.org/packages/11/0b/8dec16b1863d74af6eb3543928600ec2195af49ca58b16334972f6775663/grpcio-1.76.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:08caea849a9d3c71a542827d6df9d5a69067b0a1efbea8a855633ff5d9571465", size = 6412027, upload_time = "2025-10-21T16:20:59.3Z" },
682
+ { url = "https://files.pythonhosted.org/packages/d7/64/7b9e6e7ab910bea9d46f2c090380bab274a0b91fb0a2fe9b0cd399fffa12/grpcio-1.76.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f0e34c2079d47ae9f6188211db9e777c619a21d4faba6977774e8fa43b085e48", size = 7075913, upload_time = "2025-10-21T16:21:01.645Z" },
683
+ { url = "https://files.pythonhosted.org/packages/68/86/093c46e9546073cefa789bd76d44c5cb2abc824ca62af0c18be590ff13ba/grpcio-1.76.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8843114c0cfce61b40ad48df65abcfc00d4dba82eae8718fab5352390848c5da", size = 6615417, upload_time = "2025-10-21T16:21:03.844Z" },
684
+ { url = "https://files.pythonhosted.org/packages/f7/b6/5709a3a68500a9c03da6fb71740dcdd5ef245e39266461a03f31a57036d8/grpcio-1.76.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8eddfb4d203a237da6f3cc8a540dad0517d274b5a1e9e636fd8d2c79b5c1d397", size = 7199683, upload_time = "2025-10-21T16:21:06.195Z" },
685
+ { url = "https://files.pythonhosted.org/packages/91/d3/4b1f2bf16ed52ce0b508161df3a2d186e4935379a159a834cb4a7d687429/grpcio-1.76.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:32483fe2aab2c3794101c2a159070584e5db11d0aa091b2c0ea9c4fc43d0d749", size = 8163109, upload_time = "2025-10-21T16:21:08.498Z" },
686
+ { url = "https://files.pythonhosted.org/packages/5c/61/d9043f95f5f4cf085ac5dd6137b469d41befb04bd80280952ffa2a4c3f12/grpcio-1.76.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dcfe41187da8992c5f40aa8c5ec086fa3672834d2be57a32384c08d5a05b4c00", size = 7626676, upload_time = "2025-10-21T16:21:10.693Z" },
687
+ { url = "https://files.pythonhosted.org/packages/36/95/fd9a5152ca02d8881e4dd419cdd790e11805979f499a2e5b96488b85cf27/grpcio-1.76.0-cp311-cp311-win32.whl", hash = "sha256:2107b0c024d1b35f4083f11245c0e23846ae64d02f40b2b226684840260ed054", size = 3997688, upload_time = "2025-10-21T16:21:12.746Z" },
688
+ { url = "https://files.pythonhosted.org/packages/60/9c/5c359c8d4c9176cfa3c61ecd4efe5affe1f38d9bae81e81ac7186b4c9cc8/grpcio-1.76.0-cp311-cp311-win_amd64.whl", hash = "sha256:522175aba7af9113c48ec10cc471b9b9bd4f6ceb36aeb4544a8e2c80ed9d252d", size = 4709315, upload_time = "2025-10-21T16:21:15.26Z" },
689
+ { url = "https://files.pythonhosted.org/packages/bf/05/8e29121994b8d959ffa0afd28996d452f291b48cfc0875619de0bde2c50c/grpcio-1.76.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8", size = 5799718, upload_time = "2025-10-21T16:21:17.939Z" },
690
+ { url = "https://files.pythonhosted.org/packages/d9/75/11d0e66b3cdf998c996489581bdad8900db79ebd83513e45c19548f1cba4/grpcio-1.76.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280", size = 11825627, upload_time = "2025-10-21T16:21:20.466Z" },
691
+ { url = "https://files.pythonhosted.org/packages/28/50/2f0aa0498bc188048f5d9504dcc5c2c24f2eb1a9337cd0fa09a61a2e75f0/grpcio-1.76.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4", size = 6359167, upload_time = "2025-10-21T16:21:23.122Z" },
692
+ { url = "https://files.pythonhosted.org/packages/66/e5/bbf0bb97d29ede1d59d6588af40018cfc345b17ce979b7b45424628dc8bb/grpcio-1.76.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11", size = 7044267, upload_time = "2025-10-21T16:21:25.995Z" },
693
+ { url = "https://files.pythonhosted.org/packages/f5/86/f6ec2164f743d9609691115ae8ece098c76b894ebe4f7c94a655c6b03e98/grpcio-1.76.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6", size = 6573963, upload_time = "2025-10-21T16:21:28.631Z" },
694
+ { url = "https://files.pythonhosted.org/packages/60/bc/8d9d0d8505feccfdf38a766d262c71e73639c165b311c9457208b56d92ae/grpcio-1.76.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8", size = 7164484, upload_time = "2025-10-21T16:21:30.837Z" },
695
+ { url = "https://files.pythonhosted.org/packages/67/e6/5d6c2fc10b95edf6df9b8f19cf10a34263b7fd48493936fffd5085521292/grpcio-1.76.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980", size = 8127777, upload_time = "2025-10-21T16:21:33.577Z" },
696
+ { url = "https://files.pythonhosted.org/packages/3f/c8/dce8ff21c86abe025efe304d9e31fdb0deaaa3b502b6a78141080f206da0/grpcio-1.76.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882", size = 7594014, upload_time = "2025-10-21T16:21:41.882Z" },
697
+ { url = "https://files.pythonhosted.org/packages/e0/42/ad28191ebf983a5d0ecef90bab66baa5a6b18f2bfdef9d0a63b1973d9f75/grpcio-1.76.0-cp312-cp312-win32.whl", hash = "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958", size = 3984750, upload_time = "2025-10-21T16:21:44.006Z" },
698
+ { url = "https://files.pythonhosted.org/packages/9e/00/7bd478cbb851c04a48baccaa49b75abaa8e4122f7d86da797500cccdd771/grpcio-1.76.0-cp312-cp312-win_amd64.whl", hash = "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347", size = 4704003, upload_time = "2025-10-21T16:21:46.244Z" },
699
+ { url = "https://files.pythonhosted.org/packages/fc/ed/71467ab770effc9e8cef5f2e7388beb2be26ed642d567697bb103a790c72/grpcio-1.76.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2", size = 5807716, upload_time = "2025-10-21T16:21:48.475Z" },
700
+ { url = "https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468", size = 11821522, upload_time = "2025-10-21T16:21:51.142Z" },
701
+ { url = "https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3", size = 6362558, upload_time = "2025-10-21T16:21:54.213Z" },
702
+ { url = "https://files.pythonhosted.org/packages/bd/64/9784eab483358e08847498ee56faf8ff6ea8e0a4592568d9f68edc97e9e9/grpcio-1.76.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb", size = 7049990, upload_time = "2025-10-21T16:21:56.476Z" },
703
+ { url = "https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae", size = 6575387, upload_time = "2025-10-21T16:21:59.051Z" },
704
+ { url = "https://files.pythonhosted.org/packages/15/0f/f12c32b03f731f4a6242f771f63039df182c8b8e2cf8075b245b409259d4/grpcio-1.76.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77", size = 7166668, upload_time = "2025-10-21T16:22:02.049Z" },
705
+ { url = "https://files.pythonhosted.org/packages/ff/2d/3ec9ce0c2b1d92dd59d1c3264aaec9f0f7c817d6e8ac683b97198a36ed5a/grpcio-1.76.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03", size = 8124928, upload_time = "2025-10-21T16:22:04.984Z" },
706
+ { url = "https://files.pythonhosted.org/packages/1a/74/fd3317be5672f4856bcdd1a9e7b5e17554692d3db9a3b273879dc02d657d/grpcio-1.76.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42", size = 7589983, upload_time = "2025-10-21T16:22:07.881Z" },
707
+ { url = "https://files.pythonhosted.org/packages/45/bb/ca038cf420f405971f19821c8c15bcbc875505f6ffadafe9ffd77871dc4c/grpcio-1.76.0-cp313-cp313-win32.whl", hash = "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f", size = 3984727, upload_time = "2025-10-21T16:22:10.032Z" },
708
+ { url = "https://files.pythonhosted.org/packages/41/80/84087dc56437ced7cdd4b13d7875e7439a52a261e3ab4e06488ba6173b0a/grpcio-1.76.0-cp313-cp313-win_amd64.whl", hash = "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8", size = 4702799, upload_time = "2025-10-21T16:22:12.709Z" },
709
+ { url = "https://files.pythonhosted.org/packages/b4/46/39adac80de49d678e6e073b70204091e76631e03e94928b9ea4ecf0f6e0e/grpcio-1.76.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62", size = 5808417, upload_time = "2025-10-21T16:22:15.02Z" },
710
+ { url = "https://files.pythonhosted.org/packages/9c/f5/a4531f7fb8b4e2a60b94e39d5d924469b7a6988176b3422487be61fe2998/grpcio-1.76.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd", size = 11828219, upload_time = "2025-10-21T16:22:17.954Z" },
711
+ { url = "https://files.pythonhosted.org/packages/4b/1c/de55d868ed7a8bd6acc6b1d6ddc4aa36d07a9f31d33c912c804adb1b971b/grpcio-1.76.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc", size = 6367826, upload_time = "2025-10-21T16:22:20.721Z" },
712
+ { url = "https://files.pythonhosted.org/packages/59/64/99e44c02b5adb0ad13ab3adc89cb33cb54bfa90c74770f2607eea629b86f/grpcio-1.76.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a", size = 7049550, upload_time = "2025-10-21T16:22:23.637Z" },
713
+ { url = "https://files.pythonhosted.org/packages/43/28/40a5be3f9a86949b83e7d6a2ad6011d993cbe9b6bd27bea881f61c7788b6/grpcio-1.76.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba", size = 6575564, upload_time = "2025-10-21T16:22:26.016Z" },
714
+ { url = "https://files.pythonhosted.org/packages/4b/a9/1be18e6055b64467440208a8559afac243c66a8b904213af6f392dc2212f/grpcio-1.76.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09", size = 7176236, upload_time = "2025-10-21T16:22:28.362Z" },
715
+ { url = "https://files.pythonhosted.org/packages/0f/55/dba05d3fcc151ce6e81327541d2cc8394f442f6b350fead67401661bf041/grpcio-1.76.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc", size = 8125795, upload_time = "2025-10-21T16:22:31.075Z" },
716
+ { url = "https://files.pythonhosted.org/packages/4a/45/122df922d05655f63930cf42c9e3f72ba20aadb26c100ee105cad4ce4257/grpcio-1.76.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc", size = 7592214, upload_time = "2025-10-21T16:22:33.831Z" },
717
+ { url = "https://files.pythonhosted.org/packages/4a/6e/0b899b7f6b66e5af39e377055fb4a6675c9ee28431df5708139df2e93233/grpcio-1.76.0-cp314-cp314-win32.whl", hash = "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e", size = 4062961, upload_time = "2025-10-21T16:22:36.468Z" },
718
+ { url = "https://files.pythonhosted.org/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", size = 4834462, upload_time = "2025-10-21T16:22:39.772Z" },
719
+ ]
720
+
721
+ [[package]]
722
+ name = "grpcio-status"
723
+ version = "1.76.0"
724
+ source = { registry = "https://pypi.org/simple" }
725
+ dependencies = [
726
+ { name = "googleapis-common-protos" },
727
+ { name = "grpcio" },
728
+ { name = "protobuf" },
729
+ ]
730
+ sdist = { url = "https://files.pythonhosted.org/packages/3f/46/e9f19d5be65e8423f886813a2a9d0056ba94757b0c5007aa59aed1a961fa/grpcio_status-1.76.0.tar.gz", hash = "sha256:25fcbfec74c15d1a1cb5da3fab8ee9672852dc16a5a9eeb5baf7d7a9952943cd", size = 13679, upload_time = "2025-10-21T16:28:52.545Z" }
731
+ wheels = [
732
+ { url = "https://files.pythonhosted.org/packages/8c/cc/27ba60ad5a5f2067963e6a858743500df408eb5855e98be778eaef8c9b02/grpcio_status-1.76.0-py3-none-any.whl", hash = "sha256:380568794055a8efbbd8871162df92012e0228a5f6dffaf57f2a00c534103b18", size = 14425, upload_time = "2025-10-21T16:28:40.853Z" },
733
+ ]
734
+
735
  [[package]]
736
  name = "h11"
737
  version = "0.16.0"
 
1016
  version = "2.3.4"
1017
  source = { registry = "https://pypi.org/simple" }
1018
  resolution-markers = [
1019
+ "python_full_version >= '3.14'",
1020
+ "python_full_version == '3.13.*'",
1021
  "python_full_version == '3.12.*'",
1022
  "python_full_version == '3.11.*'",
1023
  ]
 
1352
  { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload_time = "2025-07-01T09:16:27.732Z" },
1353
  ]
1354
 
1355
+ [[package]]
1356
+ name = "proto-plus"
1357
+ version = "1.26.1"
1358
+ source = { registry = "https://pypi.org/simple" }
1359
+ dependencies = [
1360
+ { name = "protobuf" },
1361
+ ]
1362
+ sdist = { url = "https://files.pythonhosted.org/packages/f4/ac/87285f15f7cce6d4a008f33f1757fb5a13611ea8914eb58c3d0d26243468/proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012", size = 56142, upload_time = "2025-03-10T15:54:38.843Z" }
1363
+ wheels = [
1364
+ { url = "https://files.pythonhosted.org/packages/4e/6d/280c4c2ce28b1593a19ad5239c8b826871fc6ec275c21afc8e1820108039/proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", size = 50163, upload_time = "2025-03-10T15:54:37.335Z" },
1365
+ ]
1366
+
1367
+ [[package]]
1368
+ name = "protobuf"
1369
+ version = "6.33.0"
1370
+ source = { registry = "https://pypi.org/simple" }
1371
+ sdist = { url = "https://files.pythonhosted.org/packages/19/ff/64a6c8f420818bb873713988ca5492cba3a7946be57e027ac63495157d97/protobuf-6.33.0.tar.gz", hash = "sha256:140303d5c8d2037730c548f8c7b93b20bb1dc301be280c378b82b8894589c954", size = 443463, upload_time = "2025-10-15T20:39:52.159Z" }
1372
+ wheels = [
1373
+ { url = "https://files.pythonhosted.org/packages/7e/ee/52b3fa8feb6db4a833dfea4943e175ce645144532e8a90f72571ad85df4e/protobuf-6.33.0-cp310-abi3-win32.whl", hash = "sha256:d6101ded078042a8f17959eccd9236fb7a9ca20d3b0098bbcb91533a5680d035", size = 425593, upload_time = "2025-10-15T20:39:40.29Z" },
1374
+ { url = "https://files.pythonhosted.org/packages/7b/c6/7a465f1825872c55e0341ff4a80198743f73b69ce5d43ab18043699d1d81/protobuf-6.33.0-cp310-abi3-win_amd64.whl", hash = "sha256:9a031d10f703f03768f2743a1c403af050b6ae1f3480e9c140f39c45f81b13ee", size = 436882, upload_time = "2025-10-15T20:39:42.841Z" },
1375
+ { url = "https://files.pythonhosted.org/packages/e1/a9/b6eee662a6951b9c3640e8e452ab3e09f117d99fc10baa32d1581a0d4099/protobuf-6.33.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:905b07a65f1a4b72412314082c7dbfae91a9e8b68a0cc1577515f8df58ecf455", size = 427521, upload_time = "2025-10-15T20:39:43.803Z" },
1376
+ { url = "https://files.pythonhosted.org/packages/10/35/16d31e0f92c6d2f0e77c2a3ba93185130ea13053dd16200a57434c882f2b/protobuf-6.33.0-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e0697ece353e6239b90ee43a9231318302ad8353c70e6e45499fa52396debf90", size = 324445, upload_time = "2025-10-15T20:39:44.932Z" },
1377
+ { url = "https://files.pythonhosted.org/packages/e6/eb/2a981a13e35cda8b75b5585aaffae2eb904f8f351bdd3870769692acbd8a/protobuf-6.33.0-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:e0a1715e4f27355afd9570f3ea369735afc853a6c3951a6afe1f80d8569ad298", size = 339159, upload_time = "2025-10-15T20:39:46.186Z" },
1378
+ { url = "https://files.pythonhosted.org/packages/21/51/0b1cbad62074439b867b4e04cc09b93f6699d78fd191bed2bbb44562e077/protobuf-6.33.0-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:35be49fd3f4fefa4e6e2aacc35e8b837d6703c37a2168a55ac21e9b1bc7559ef", size = 323172, upload_time = "2025-10-15T20:39:47.465Z" },
1379
+ { url = "https://files.pythonhosted.org/packages/07/d1/0a28c21707807c6aacd5dc9c3704b2aa1effbf37adebd8caeaf68b17a636/protobuf-6.33.0-py3-none-any.whl", hash = "sha256:25c9e1963c6734448ea2d308cfa610e692b801304ba0908d7bfa564ac5132995", size = 170477, upload_time = "2025-10-15T20:39:51.311Z" },
1380
+ ]
1381
+
1382
+ [[package]]
1383
+ name = "pyasn1"
1384
+ version = "0.6.1"
1385
+ source = { registry = "https://pypi.org/simple" }
1386
+ sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload_time = "2024-09-10T22:41:42.55Z" }
1387
+ wheels = [
1388
+ { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload_time = "2024-09-11T16:00:36.122Z" },
1389
+ ]
1390
+
1391
+ [[package]]
1392
+ name = "pyasn1-modules"
1393
+ version = "0.4.2"
1394
+ source = { registry = "https://pypi.org/simple" }
1395
+ dependencies = [
1396
+ { name = "pyasn1" },
1397
+ ]
1398
+ sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload_time = "2025-03-28T02:41:22.17Z" }
1399
+ wheels = [
1400
+ { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload_time = "2025-03-28T02:41:19.028Z" },
1401
+ ]
1402
+
1403
  [[package]]
1404
  name = "pydantic"
1405
  version = "2.11.10"
 
1532
  { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload_time = "2024-03-01T18:36:18.57Z" },
1533
  ]
1534
 
1535
+ [[package]]
1536
+ name = "python-dotenv"
1537
+ version = "1.2.1"
1538
+ source = { registry = "https://pypi.org/simple" }
1539
+ sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload_time = "2025-10-26T15:12:10.434Z" }
1540
+ wheels = [
1541
+ { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload_time = "2025-10-26T15:12:09.109Z" },
1542
+ ]
1543
+
1544
  [[package]]
1545
  name = "python-multipart"
1546
  version = "0.0.20"
 
1656
  version = "0.1.0"
1657
  source = { virtual = "." }
1658
  dependencies = [
1659
+ { name = "google-cloud-aiplatform" },
1660
  { name = "gradio" },
1661
+ { name = "python-dotenv" },
1662
  { name = "requests" },
1663
  ]
1664
 
1665
  [package.metadata]
1666
  requires-dist = [
1667
+ { name = "google-cloud-aiplatform", specifier = ">=1.38.0" },
1668
  { name = "gradio", specifier = ">=5.49.1" },
1669
+ { name = "python-dotenv", specifier = ">=1.0.0" },
1670
  { name = "requests", specifier = ">=2.32.5" },
1671
  ]
1672
 
1673
+ [[package]]
1674
+ name = "rsa"
1675
+ version = "4.9.1"
1676
+ source = { registry = "https://pypi.org/simple" }
1677
+ dependencies = [
1678
+ { name = "pyasn1" },
1679
+ ]
1680
+ sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload_time = "2025-04-16T09:51:18.218Z" }
1681
+ wheels = [
1682
+ { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload_time = "2025-04-16T09:51:17.142Z" },
1683
+ ]
1684
+
1685
  [[package]]
1686
  name = "ruff"
1687
  version = "0.14.3"
 
1729
  { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552, upload_time = "2022-05-26T13:35:21.206Z" },
1730
  ]
1731
 
1732
+ [[package]]
1733
+ name = "shapely"
1734
+ version = "2.1.2"
1735
+ source = { registry = "https://pypi.org/simple" }
1736
+ dependencies = [
1737
+ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
1738
+ { name = "numpy", version = "2.3.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
1739
+ ]
1740
+ sdist = { url = "https://files.pythonhosted.org/packages/4d/bc/0989043118a27cccb4e906a46b7565ce36ca7b57f5a18b78f4f1b0f72d9d/shapely-2.1.2.tar.gz", hash = "sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9", size = 315489, upload_time = "2025-09-24T13:51:41.432Z" }
1741
+ wheels = [
1742
+ { url = "https://files.pythonhosted.org/packages/05/89/c3548aa9b9812a5d143986764dededfa48d817714e947398bdda87c77a72/shapely-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7ae48c236c0324b4e139bea88a306a04ca630f49be66741b340729d380d8f52f", size = 1825959, upload_time = "2025-09-24T13:50:00.682Z" },
1743
+ { url = "https://files.pythonhosted.org/packages/ce/8a/7ebc947080442edd614ceebe0ce2cdbd00c25e832c240e1d1de61d0e6b38/shapely-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eba6710407f1daa8e7602c347dfc94adc02205ec27ed956346190d66579eb9ea", size = 1629196, upload_time = "2025-09-24T13:50:03.447Z" },
1744
+ { url = "https://files.pythonhosted.org/packages/c8/86/c9c27881c20d00fc409e7e059de569d5ed0abfcec9c49548b124ebddea51/shapely-2.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef4a456cc8b7b3d50ccec29642aa4aeda959e9da2fe9540a92754770d5f0cf1f", size = 2951065, upload_time = "2025-09-24T13:50:05.266Z" },
1745
+ { url = "https://files.pythonhosted.org/packages/50/8a/0ab1f7433a2a85d9e9aea5b1fbb333f3b09b309e7817309250b4b7b2cc7a/shapely-2.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e38a190442aacc67ff9f75ce60aec04893041f16f97d242209106d502486a142", size = 3058666, upload_time = "2025-09-24T13:50:06.872Z" },
1746
+ { url = "https://files.pythonhosted.org/packages/bb/c6/5a30ffac9c4f3ffd5b7113a7f5299ccec4713acd5ee44039778a7698224e/shapely-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:40d784101f5d06a1fd30b55fc11ea58a61be23f930d934d86f19a180909908a4", size = 3966905, upload_time = "2025-09-24T13:50:09.417Z" },
1747
+ { url = "https://files.pythonhosted.org/packages/9c/72/e92f3035ba43e53959007f928315a68fbcf2eeb4e5ededb6f0dc7ff1ecc3/shapely-2.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f6f6cd5819c50d9bcf921882784586aab34a4bd53e7553e175dece6db513a6f0", size = 4129260, upload_time = "2025-09-24T13:50:11.183Z" },
1748
+ { url = "https://files.pythonhosted.org/packages/42/24/605901b73a3d9f65fa958e63c9211f4be23d584da8a1a7487382fac7fdc5/shapely-2.1.2-cp310-cp310-win32.whl", hash = "sha256:fe9627c39c59e553c90f5bc3128252cb85dc3b3be8189710666d2f8bc3a5503e", size = 1544301, upload_time = "2025-09-24T13:50:12.521Z" },
1749
+ { url = "https://files.pythonhosted.org/packages/e1/89/6db795b8dd3919851856bd2ddd13ce434a748072f6fdee42ff30cbd3afa3/shapely-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:1d0bfb4b8f661b3b4ec3565fa36c340bfb1cda82087199711f86a88647d26b2f", size = 1722074, upload_time = "2025-09-24T13:50:13.909Z" },
1750
+ { url = "https://files.pythonhosted.org/packages/8f/8d/1ff672dea9ec6a7b5d422eb6d095ed886e2e523733329f75fdcb14ee1149/shapely-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91121757b0a36c9aac3427a651a7e6567110a4a67c97edf04f8d55d4765f6618", size = 1820038, upload_time = "2025-09-24T13:50:15.628Z" },
1751
+ { url = "https://files.pythonhosted.org/packages/4f/ce/28fab8c772ce5db23a0d86bf0adaee0c4c79d5ad1db766055fa3dab442e2/shapely-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16a9c722ba774cf50b5d4541242b4cce05aafd44a015290c82ba8a16931ff63d", size = 1626039, upload_time = "2025-09-24T13:50:16.881Z" },
1752
+ { url = "https://files.pythonhosted.org/packages/70/8b/868b7e3f4982f5006e9395c1e12343c66a8155c0374fdc07c0e6a1ab547d/shapely-2.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cc4f7397459b12c0b196c9efe1f9d7e92463cbba142632b4cc6d8bbbbd3e2b09", size = 3001519, upload_time = "2025-09-24T13:50:18.606Z" },
1753
+ { url = "https://files.pythonhosted.org/packages/13/02/58b0b8d9c17c93ab6340edd8b7308c0c5a5b81f94ce65705819b7416dba5/shapely-2.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:136ab87b17e733e22f0961504d05e77e7be8c9b5a8184f685b4a91a84efe3c26", size = 3110842, upload_time = "2025-09-24T13:50:21.77Z" },
1754
+ { url = "https://files.pythonhosted.org/packages/af/61/8e389c97994d5f331dcffb25e2fa761aeedfb52b3ad9bcdd7b8671f4810a/shapely-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:16c5d0fc45d3aa0a69074979f4f1928ca2734fb2e0dde8af9611e134e46774e7", size = 4021316, upload_time = "2025-09-24T13:50:23.626Z" },
1755
+ { url = "https://files.pythonhosted.org/packages/d3/d4/9b2a9fe6039f9e42ccf2cb3e84f219fd8364b0c3b8e7bbc857b5fbe9c14c/shapely-2.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6ddc759f72b5b2b0f54a7e7cde44acef680a55019eb52ac63a7af2cf17cb9cd2", size = 4178586, upload_time = "2025-09-24T13:50:25.443Z" },
1756
+ { url = "https://files.pythonhosted.org/packages/16/f6/9840f6963ed4decf76b08fd6d7fed14f8779fb7a62cb45c5617fa8ac6eab/shapely-2.1.2-cp311-cp311-win32.whl", hash = "sha256:2fa78b49485391224755a856ed3b3bd91c8455f6121fee0db0e71cefb07d0ef6", size = 1543961, upload_time = "2025-09-24T13:50:26.968Z" },
1757
+ { url = "https://files.pythonhosted.org/packages/38/1e/3f8ea46353c2a33c1669eb7327f9665103aa3a8dfe7f2e4ef714c210b2c2/shapely-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:c64d5c97b2f47e3cd9b712eaced3b061f2b71234b3fc263e0fcf7d889c6559dc", size = 1722856, upload_time = "2025-09-24T13:50:28.497Z" },
1758
+ { url = "https://files.pythonhosted.org/packages/24/c0/f3b6453cf2dfa99adc0ba6675f9aaff9e526d2224cbd7ff9c1a879238693/shapely-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe2533caae6a91a543dec62e8360fe86ffcdc42a7c55f9dfd0128a977a896b94", size = 1833550, upload_time = "2025-09-24T13:50:30.019Z" },
1759
+ { url = "https://files.pythonhosted.org/packages/86/07/59dee0bc4b913b7ab59ab1086225baca5b8f19865e6101db9ebb7243e132/shapely-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ba4d1333cc0bc94381d6d4308d2e4e008e0bd128bdcff5573199742ee3634359", size = 1643556, upload_time = "2025-09-24T13:50:32.291Z" },
1760
+ { url = "https://files.pythonhosted.org/packages/26/29/a5397e75b435b9895cd53e165083faed5d12fd9626eadec15a83a2411f0f/shapely-2.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0bd308103340030feef6c111d3eb98d50dc13feea33affc8a6f9fa549e9458a3", size = 2988308, upload_time = "2025-09-24T13:50:33.862Z" },
1761
+ { url = "https://files.pythonhosted.org/packages/b9/37/e781683abac55dde9771e086b790e554811a71ed0b2b8a1e789b7430dd44/shapely-2.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e7d4d7ad262a48bb44277ca12c7c78cb1b0f56b32c10734ec9a1d30c0b0c54b", size = 3099844, upload_time = "2025-09-24T13:50:35.459Z" },
1762
+ { url = "https://files.pythonhosted.org/packages/d8/f3/9876b64d4a5a321b9dc482c92bb6f061f2fa42131cba643c699f39317cb9/shapely-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9eddfe513096a71896441a7c37db72da0687b34752c4e193577a145c71736fc", size = 3988842, upload_time = "2025-09-24T13:50:37.478Z" },
1763
+ { url = "https://files.pythonhosted.org/packages/d1/a0/704c7292f7014c7e74ec84eddb7b109e1fbae74a16deae9c1504b1d15565/shapely-2.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:980c777c612514c0cf99bc8a9de6d286f5e186dcaf9091252fcd444e5638193d", size = 4152714, upload_time = "2025-09-24T13:50:39.9Z" },
1764
+ { url = "https://files.pythonhosted.org/packages/53/46/319c9dc788884ad0785242543cdffac0e6530e4d0deb6c4862bc4143dcf3/shapely-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9111274b88e4d7b54a95218e243282709b330ef52b7b86bc6aaf4f805306f454", size = 1542745, upload_time = "2025-09-24T13:50:41.414Z" },
1765
+ { url = "https://files.pythonhosted.org/packages/ec/bf/cb6c1c505cb31e818e900b9312d514f381fbfa5c4363edfce0fcc4f8c1a4/shapely-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:743044b4cfb34f9a67205cee9279feaf60ba7d02e69febc2afc609047cb49179", size = 1722861, upload_time = "2025-09-24T13:50:43.35Z" },
1766
+ { url = "https://files.pythonhosted.org/packages/c3/90/98ef257c23c46425dc4d1d31005ad7c8d649fe423a38b917db02c30f1f5a/shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8", size = 1832644, upload_time = "2025-09-24T13:50:44.886Z" },
1767
+ { url = "https://files.pythonhosted.org/packages/6d/ab/0bee5a830d209adcd3a01f2d4b70e587cdd9fd7380d5198c064091005af8/shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a", size = 1642887, upload_time = "2025-09-24T13:50:46.735Z" },
1768
+ { url = "https://files.pythonhosted.org/packages/2d/5e/7d7f54ba960c13302584c73704d8c4d15404a51024631adb60b126a4ae88/shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e", size = 2970931, upload_time = "2025-09-24T13:50:48.374Z" },
1769
+ { url = "https://files.pythonhosted.org/packages/f2/a2/83fc37e2a58090e3d2ff79175a95493c664bcd0b653dd75cb9134645a4e5/shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6", size = 3082855, upload_time = "2025-09-24T13:50:50.037Z" },
1770
+ { url = "https://files.pythonhosted.org/packages/44/2b/578faf235a5b09f16b5f02833c53822294d7f21b242f8e2d0cf03fb64321/shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af", size = 3979960, upload_time = "2025-09-24T13:50:51.74Z" },
1771
+ { url = "https://files.pythonhosted.org/packages/4d/04/167f096386120f692cc4ca02f75a17b961858997a95e67a3cb6a7bbd6b53/shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd", size = 4142851, upload_time = "2025-09-24T13:50:53.49Z" },
1772
+ { url = "https://files.pythonhosted.org/packages/48/74/fb402c5a6235d1c65a97348b48cdedb75fb19eca2b1d66d04969fc1c6091/shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350", size = 1541890, upload_time = "2025-09-24T13:50:55.337Z" },
1773
+ { url = "https://files.pythonhosted.org/packages/41/47/3647fe7ad990af60ad98b889657a976042c9988c2807cf322a9d6685f462/shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715", size = 1722151, upload_time = "2025-09-24T13:50:57.153Z" },
1774
+ { url = "https://files.pythonhosted.org/packages/3c/49/63953754faa51ffe7d8189bfbe9ca34def29f8c0e34c67cbe2a2795f269d/shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40", size = 1834130, upload_time = "2025-09-24T13:50:58.49Z" },
1775
+ { url = "https://files.pythonhosted.org/packages/7f/ee/dce001c1984052970ff60eb4727164892fb2d08052c575042a47f5a9e88f/shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b", size = 1642802, upload_time = "2025-09-24T13:50:59.871Z" },
1776
+ { url = "https://files.pythonhosted.org/packages/da/e7/fc4e9a19929522877fa602f705706b96e78376afb7fad09cad5b9af1553c/shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801", size = 3018460, upload_time = "2025-09-24T13:51:02.08Z" },
1777
+ { url = "https://files.pythonhosted.org/packages/a1/18/7519a25db21847b525696883ddc8e6a0ecaa36159ea88e0fef11466384d0/shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0", size = 3095223, upload_time = "2025-09-24T13:51:04.472Z" },
1778
+ { url = "https://files.pythonhosted.org/packages/48/de/b59a620b1f3a129c3fecc2737104a0a7e04e79335bd3b0a1f1609744cf17/shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c", size = 4030760, upload_time = "2025-09-24T13:51:06.455Z" },
1779
+ { url = "https://files.pythonhosted.org/packages/96/b3/c6655ee7232b417562bae192ae0d3ceaadb1cc0ffc2088a2ddf415456cc2/shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99", size = 4170078, upload_time = "2025-09-24T13:51:08.584Z" },
1780
+ { url = "https://files.pythonhosted.org/packages/a0/8e/605c76808d73503c9333af8f6cbe7e1354d2d238bda5f88eea36bfe0f42a/shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf", size = 1559178, upload_time = "2025-09-24T13:51:10.73Z" },
1781
+ { url = "https://files.pythonhosted.org/packages/36/f7/d317eb232352a1f1444d11002d477e54514a4a6045536d49d0c59783c0da/shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c", size = 1739756, upload_time = "2025-09-24T13:51:12.105Z" },
1782
+ { url = "https://files.pythonhosted.org/packages/fc/c4/3ce4c2d9b6aabd27d26ec988f08cb877ba9e6e96086eff81bfea93e688c7/shapely-2.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223", size = 1831290, upload_time = "2025-09-24T13:51:13.56Z" },
1783
+ { url = "https://files.pythonhosted.org/packages/17/b9/f6ab8918fc15429f79cb04afa9f9913546212d7fb5e5196132a2af46676b/shapely-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c", size = 1641463, upload_time = "2025-09-24T13:51:14.972Z" },
1784
+ { url = "https://files.pythonhosted.org/packages/a5/57/91d59ae525ca641e7ac5551c04c9503aee6f29b92b392f31790fcb1a4358/shapely-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df", size = 2970145, upload_time = "2025-09-24T13:51:16.961Z" },
1785
+ { url = "https://files.pythonhosted.org/packages/8a/cb/4948be52ee1da6927831ab59e10d4c29baa2a714f599f1f0d1bc747f5777/shapely-2.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf", size = 3073806, upload_time = "2025-09-24T13:51:18.712Z" },
1786
+ { url = "https://files.pythonhosted.org/packages/03/83/f768a54af775eb41ef2e7bec8a0a0dbe7d2431c3e78c0a8bdba7ab17e446/shapely-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4", size = 3980803, upload_time = "2025-09-24T13:51:20.37Z" },
1787
+ { url = "https://files.pythonhosted.org/packages/9f/cb/559c7c195807c91c79d38a1f6901384a2878a76fbdf3f1048893a9b7534d/shapely-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc", size = 4133301, upload_time = "2025-09-24T13:51:21.887Z" },
1788
+ { url = "https://files.pythonhosted.org/packages/80/cd/60d5ae203241c53ef3abd2ef27c6800e21afd6c94e39db5315ea0cbafb4a/shapely-2.1.2-cp314-cp314-win32.whl", hash = "sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566", size = 1583247, upload_time = "2025-09-24T13:51:23.401Z" },
1789
+ { url = "https://files.pythonhosted.org/packages/74/d4/135684f342e909330e50d31d441ace06bf83c7dc0777e11043f99167b123/shapely-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c", size = 1773019, upload_time = "2025-09-24T13:51:24.873Z" },
1790
+ { url = "https://files.pythonhosted.org/packages/a3/05/a44f3f9f695fa3ada22786dc9da33c933da1cbc4bfe876fe3a100bafe263/shapely-2.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a", size = 1834137, upload_time = "2025-09-24T13:51:26.665Z" },
1791
+ { url = "https://files.pythonhosted.org/packages/52/7e/4d57db45bf314573427b0a70dfca15d912d108e6023f623947fa69f39b72/shapely-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076", size = 1642884, upload_time = "2025-09-24T13:51:28.029Z" },
1792
+ { url = "https://files.pythonhosted.org/packages/5a/27/4e29c0a55d6d14ad7422bf86995d7ff3f54af0eba59617eb95caf84b9680/shapely-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1", size = 3018320, upload_time = "2025-09-24T13:51:29.903Z" },
1793
+ { url = "https://files.pythonhosted.org/packages/9f/bb/992e6a3c463f4d29d4cd6ab8963b75b1b1040199edbd72beada4af46bde5/shapely-2.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0", size = 3094931, upload_time = "2025-09-24T13:51:32.699Z" },
1794
+ { url = "https://files.pythonhosted.org/packages/9c/16/82e65e21070e473f0ed6451224ed9fa0be85033d17e0c6e7213a12f59d12/shapely-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26", size = 4030406, upload_time = "2025-09-24T13:51:34.189Z" },
1795
+ { url = "https://files.pythonhosted.org/packages/7c/75/c24ed871c576d7e2b64b04b1fe3d075157f6eb54e59670d3f5ffb36e25c7/shapely-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0", size = 4169511, upload_time = "2025-09-24T13:51:36.297Z" },
1796
+ { url = "https://files.pythonhosted.org/packages/b1/f7/b3d1d6d18ebf55236eec1c681ce5e665742aab3c0b7b232720a7d43df7b6/shapely-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735", size = 1602607, upload_time = "2025-09-24T13:51:37.757Z" },
1797
+ { url = "https://files.pythonhosted.org/packages/9a/f6/f09272a71976dfc138129b8faf435d064a811ae2f708cb147dccdf7aacdb/shapely-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9", size = 1796682, upload_time = "2025-09-24T13:51:39.233Z" },
1798
+ ]
1799
+
1800
  [[package]]
1801
  name = "shellingham"
1802
  version = "1.5.4"
 
1837
  { url = "https://files.pythonhosted.org/packages/a3/e0/021c772d6a662f43b63044ab481dc6ac7592447605b5b35a957785363122/starlette-0.49.3-py3-none-any.whl", hash = "sha256:b579b99715fdc2980cf88c8ec96d3bf1ce16f5a8051a7c2b84ef9b1cdecaea2f", size = 74340, upload_time = "2025-11-01T15:12:24.387Z" },
1838
  ]
1839
 
1840
+ [[package]]
1841
+ name = "tenacity"
1842
+ version = "9.1.2"
1843
+ source = { registry = "https://pypi.org/simple" }
1844
+ sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload_time = "2025-04-02T08:25:09.966Z" }
1845
+ wheels = [
1846
+ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload_time = "2025-04-02T08:25:07.678Z" },
1847
+ ]
1848
+
1849
  [[package]]
1850
  name = "tomlkit"
1851
  version = "0.13.3"
vertex_client.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Vertex AI client for TTS synthesis using Google Cloud AI Platform.
3
+ """
4
+ import os
5
+ import json
6
+ import logging
7
+ import requests
8
+ from typing import Optional, Dict, Any, Tuple
9
+ from google.cloud import aiplatform
10
+ from google.oauth2 import service_account
11
+ from dotenv import load_dotenv
12
+
13
+ # Load environment variables from .env file (for local development)
14
+ load_dotenv()
15
+
16
+ # Configure logging
17
+ logging.basicConfig(level=logging.INFO)
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class VertexAIClient:
22
+ """Client for interacting with Vertex AI TTS endpoint."""
23
+
24
+ def __init__(self):
25
+ """Initialize the Vertex AI client."""
26
+ self.endpoint = None
27
+ self.credentials = None
28
+ self.initialized = False
29
+
30
+ def _load_credentials(self) -> Optional[service_account.Credentials]:
31
+ """
32
+ Load credentials from auth_string environment variable.
33
+
34
+ Returns:
35
+ Credentials object or None if failed
36
+ """
37
+ try:
38
+ auth_string = os.environ.get("auth_string")
39
+ if not auth_string:
40
+ logger.warning("auth_string environment variable not found")
41
+ return None
42
+
43
+ # Parse JSON credentials
44
+ credentials_dict = json.loads(auth_string)
45
+ credentials = service_account.Credentials.from_service_account_info(
46
+ credentials_dict
47
+ )
48
+ logger.info("Successfully loaded credentials from auth_string")
49
+ return credentials
50
+
51
+ except json.JSONDecodeError as e:
52
+ logger.error(f"Failed to parse auth_string JSON: {e}")
53
+ return None
54
+ except Exception as e:
55
+ logger.error(f"Failed to load credentials: {e}")
56
+ return None
57
+
58
+ def initialize(self) -> bool:
59
+ """
60
+ Initialize Vertex AI and find the zipvoice endpoint.
61
+
62
+ Returns:
63
+ True if initialization successful, False otherwise
64
+ """
65
+ if self.initialized:
66
+ return True
67
+
68
+ try:
69
+ # Load credentials
70
+ self.credentials = self._load_credentials()
71
+ if not self.credentials:
72
+ logger.error("Cannot initialize without credentials")
73
+ return False
74
+
75
+ # Initialize Vertex AI
76
+ aiplatform.init(
77
+ project="desivocalprod01",
78
+ location="asia-south1",
79
+ credentials=self.credentials,
80
+ )
81
+ logger.info("Vertex AI initialized for project desivocalprod01")
82
+
83
+ # Find the zipvoice endpoint
84
+ for endpoint in aiplatform.Endpoint.list():
85
+ if endpoint.display_name == "zipvoice":
86
+ self.endpoint = endpoint
87
+ self.initialized = True
88
+ logger.info(f"Found zipvoice endpoint: {endpoint.resource_name}")
89
+ return True
90
+
91
+ logger.error("zipvoice endpoint not found in Vertex AI")
92
+ return False
93
+
94
+ except Exception as e:
95
+ logger.error(f"Failed to initialize Vertex AI: {e}")
96
+ return False
97
+
98
+ def get_voices(self) -> Tuple[bool, Optional[Dict[str, Any]]]:
99
+ """
100
+ Get available voices from local configuration file.
101
+
102
+ Note: Vertex AI endpoint doesn't have a separate /voices API.
103
+ Voices are configured in voices_config.json
104
+
105
+ Returns:
106
+ Tuple of (success, voices_dict)
107
+ voices_dict format: {"voices": {"voice_id": {"name": "...", "gender": "..."}}}
108
+ """
109
+ try:
110
+ # Try to load from voices_config.json in current directory
111
+ import pathlib
112
+ config_path = pathlib.Path(__file__).parent / "voices_config.json"
113
+
114
+ if config_path.exists():
115
+ logger.info(f"Loading voices from {config_path}")
116
+ with open(config_path, "r") as f:
117
+ voices_data = json.load(f)
118
+ logger.info(f"Successfully loaded {len(voices_data.get('voices', {}))} voices from config")
119
+ return True, voices_data
120
+ else:
121
+ logger.warning(f"voices_config.json not found at {config_path}")
122
+ # Return empty voices list
123
+ return True, {"voices": {}}
124
+
125
+ except Exception as e:
126
+ logger.error(f"Failed to load voices config: {e}")
127
+ return False, None
128
+
129
+ def synthesize(self, text: str, voice_id: str, timeout: int = 60) -> Tuple[bool, Optional[bytes], Optional[Dict[str, Any]]]:
130
+ """
131
+ Synthesize speech from text using Vertex AI endpoint.
132
+
133
+ Args:
134
+ text: Text to synthesize
135
+ voice_id: Voice ID to use
136
+ timeout: Request timeout in seconds
137
+
138
+ Returns:
139
+ Tuple of (success, audio_bytes, metrics)
140
+ """
141
+ if not self.initialized:
142
+ if not self.initialize():
143
+ return False, None, None
144
+
145
+ try:
146
+ logger.info(f"Synthesizing text (length: {len(text)}) with voice {voice_id}")
147
+ response = self.endpoint.raw_predict(
148
+ body=json.dumps({
149
+ "text": text,
150
+ "voice_id": voice_id,
151
+ }),
152
+ headers={"Content-Type": "application/json"},
153
+ )
154
+
155
+ # Parse JSON response
156
+ result = json.loads(response.text) if hasattr(response, 'text') else response
157
+ logger.info(f"Vertex AI response: {result}")
158
+
159
+ # Check if synthesis was successful
160
+ if result.get("success"):
161
+ audio_url = result.get("audio_url")
162
+ metrics = result.get("metrics")
163
+
164
+ if not audio_url:
165
+ logger.error("No audio_url in successful response")
166
+ return False, None, None
167
+
168
+ # Download audio from URL
169
+ logger.info(f"Downloading audio from: {audio_url}")
170
+ audio_response = requests.get(audio_url, timeout=timeout)
171
+
172
+ if audio_response.status_code == 200:
173
+ audio_data = audio_response.content
174
+ logger.info(f"Successfully downloaded audio ({len(audio_data)} bytes)")
175
+ return True, audio_data, metrics
176
+ else:
177
+ logger.error(f"Failed to download audio: HTTP {audio_response.status_code}")
178
+ return False, None, None
179
+ else:
180
+ error_msg = result.get("message", "Unknown error")
181
+ logger.error(f"Synthesis failed: {error_msg}")
182
+ return False, None, None
183
+
184
+ except Exception as e:
185
+ logger.error(f"Failed to synthesize speech with Vertex AI: {e}")
186
+ return False, None, None
187
+
188
+
189
+ # Global instance
190
+ _vertex_client = None
191
+
192
+
193
+ def get_vertex_client() -> VertexAIClient:
194
+ """Get or create the global Vertex AI client instance."""
195
+ global _vertex_client
196
+ if _vertex_client is None:
197
+ _vertex_client = VertexAIClient()
198
+ return _vertex_client
voices_config.json ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "voices": {
3
+ "6e9ebcc0-7c1e-4261-9362-9b66bf819eaf": {
4
+ "name": "Bigg Boss Lite",
5
+ "gender": "Male",
6
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/55c4611d-5c1a-4df2-9ccb-6405f8d6b829.mp3"
7
+ },
8
+ "4089f7a4-b39a-4407-8ee4-4b3bef60b7e8": {
9
+ "name": "Standard",
10
+ "gender": "Female",
11
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/3e585562-a07c-4789-9ba3-baba9c7eb1a2.mp3"
12
+ },
13
+ "25548131-6fcd-4aa1-9112-0601ea9cde9e": {
14
+ "name": "Sales Impact Lite",
15
+ "gender": "Male",
16
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/80aeab18-36a4-433a-b4bd-014214f75d88.mp3"
17
+ },
18
+ "f0c65873-9fe1-48a6-ac38-cdf1293bb74e": {
19
+ "name": "Meditation Lite",
20
+ "gender": "Female",
21
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/3203fb72-f2a9-4630-8836-50f8abc59c03.mp3"
22
+ },
23
+ "cfccf6f0-f92e-4793-ba89-7d19c385a4a6": {
24
+ "name": "Aryan",
25
+ "gender": "Male",
26
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/df2d2665-9df5-4e0a-8451-fc868a614dd2.mp3"
27
+ },
28
+ "f9407c73-e283-4da3-9b1f-99929141e0df": {
29
+ "name": "Audiobook Lite",
30
+ "gender": "Female",
31
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/e464252a-26c1-4c62-a1e7-f55ea81f7a48.mp3"
32
+ },
33
+ "f40076ea-6aeb-4687-9889-3b773fbaa9f3": {
34
+ "name": "Wamika Lite",
35
+ "gender": "Female",
36
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/Lecture_Hindi.mp3"
37
+ },
38
+ "19f41593-8cec-4b16-b375-a6f6ca76db10": {
39
+ "name": "Kamala",
40
+ "gender": "Female",
41
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/6c81cee1-f8b7-450b-9b7a-6054637bf6c4.mp3"
42
+ },
43
+ "f55db771-1cce-4f54-a7d6-8b118d321d39": {
44
+ "name": "Elearning",
45
+ "gender": "Male",
46
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/2694c3b4-43dd-4893-8ced-a9b2da5465e5.mp3"
47
+ },
48
+ "9c8ab827-6b6e-45ae-936c-f41ede490ead": {
49
+ "name": "Sales",
50
+ "gender": "Male",
51
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/bf13a806-58e9-4ba7-ba8a-e14b941aa96e.mp3"
52
+ },
53
+ "1e1e7a72-c04f-46cd-9b65-12f9f5185824": {
54
+ "name": "Adam",
55
+ "gender": "Male",
56
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/1e1e7a72-c04f-46cd-9b65-12f9f5185824.mp3"
57
+ },
58
+ "f27d74e5-ea71-4697-be3e-f04bbd80c1a8": {
59
+ "name": "Marketing",
60
+ "gender": "Male",
61
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/c29e3251-f531-4096-b6c3-0dd07573877f.mp3"
62
+ },
63
+ "d4025456-83a0-45da-a15b-3ffcce0cd6b8": {
64
+ "name": "Marketing Lite",
65
+ "gender": "Female",
66
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/1b4ac4e8-9eb6-4beb-ad6f-ffc5f275219e.mp3"
67
+ },
68
+ "0cc72d86-2959-11ef-b685-a218303b6499": {
69
+ "name": "Documentary",
70
+ "gender": "Male",
71
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/33bb7db6-093a-4ab4-b507-7eab9f96de4d.mp3"
72
+ },
73
+ "f671e3c0-c9e2-4b7d-992e-3a8a7d7b7789": {
74
+ "name": "Swapnil",
75
+ "gender": "Male",
76
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/7d8edbfb-cbe0-43e0-82b0-fd91293c0389.mp3"
77
+ },
78
+ "c990fbbc-7981-4ed6-b3f1-ee109299b628": {
79
+ "name": "Palomi",
80
+ "gender": "Female",
81
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/81ad91b8-6464-4308-86fe-7b9c9f231c51.mp3"
82
+ },
83
+ "e775dbe9-db42-4813-85f7-ec3d5f9934b4": {
84
+ "name": "Rohit Bollywood",
85
+ "gender": "Male",
86
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/906de532-b217-4262-ba99-ab00824231f8.mp3"
87
+ },
88
+ "237e7675-3d90-4d6f-856c-c8def47df71f": {
89
+ "name": "Janvi",
90
+ "gender": "Female",
91
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/0bf140a2-10b0-477a-baae-f01cbdb98162.mp3"
92
+ },
93
+ "ffade7c0-2958-11ef-b685-a218303b6499": {
94
+ "name": "Anchor",
95
+ "gender": "Female",
96
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/complete-audio+(18).mp3"
97
+ },
98
+ "fd5ff2d1-baab-4277-aa0b-fcc75fa46d2f": {
99
+ "name": "Vivan",
100
+ "gender": "Male",
101
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/1fa596a9-250a-49f1-bb7c-c798506db441.mp3"
102
+ },
103
+ "edb596de-1e85-4adb-89aa-a5e58f67fdee": {
104
+ "name": "Neha",
105
+ "gender": "Female",
106
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/18a213d4-3baf-48f6-ade4-a344cb1cff52.mp3"
107
+ },
108
+ "199af31c-3d08-4f80-9879-772f91994797": {
109
+ "name": "Rakul Lite",
110
+ "gender": "Female",
111
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/76ff02a0-1b03-4923-92ab-b5fe807b6a8e.mp3"
112
+ },
113
+ "cd9e2d83-063f-4b21-9045-38a7a1fa9f66": {
114
+ "name": "Teacher",
115
+ "gender": "Female",
116
+ "sample": "https://storage.googleapis.com/desivocal-stage/desi-vocal/22db00f0-b37b-4405-aca5-bedde5f97052.mp3"
117
+ },
118
+ "112e8972-72a4-4359-8c88-a66f2662eb9b": {
119
+ "name": "Advertisement",
120
+ "gender": "Male",
121
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/c1e6d92f-e28b-4525-851d-2dff7301a634.mp3"
122
+ },
123
+ "34e961be-4049-4068-b382-6f31792e27b5": {
124
+ "name": "Yuvak",
125
+ "gender": "Male",
126
+ "sample": "https://storage.googleapis.com/desivocal-stage/desi-vocal/b070da66-4cb3-4720-991f-845e24169d09.mp3"
127
+ },
128
+ "0472cf70-1d18-48ba-a918-2bab820a7291": {
129
+ "name": "Maharaj Ji",
130
+ "gender": "Male",
131
+ "sample": "https://storage.googleapis.com/desivocal-stage/desi-vocal/9897cb2f-090c-4610-9e04-0def6f9e54f9.mp3"
132
+ },
133
+ "be0aae9f-1ab7-4088-8e8a-efe4648e902b": {
134
+ "name": "Shayar",
135
+ "gender": "Male",
136
+ "sample": "https://assets.desivocal.com/audio-samples/aa3ba7d4-19d7-4cb0-81c9-6f7e201fcf7b.mp3"
137
+ },
138
+ "055ece90-1c21-42bf-9f59-c459ba84d99c": {
139
+ "name": "Storyteller",
140
+ "gender": "Male",
141
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/1e849418-558c-4a74-bfc7-f64bb5d4443a.mp3"
142
+ },
143
+ "83ba74e4-9efb-4db3-913a-f2a0ad66904d": {
144
+ "name": "Standard",
145
+ "gender": "Male",
146
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/90624ddd-aa66-4b9c-8f1f-171a44530226.mp3"
147
+ },
148
+ "59062c58-3423-4e70-9154-6ae9e5e5be48": {
149
+ "name": "News",
150
+ "gender": "Male",
151
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/56334a9a-85c9-4eb9-9062-845b6c4e38a1.mp3"
152
+ },
153
+ "76d34dfb-a062-43f3-907f-b4372fe177be": {
154
+ "name": "Mohan Expressive",
155
+ "gender": "Male",
156
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/53938aee-e365-482f-9173-32e380864cc5.mp3"
157
+ },
158
+ "a9a87659-18c5-4751-a426-34ae4f4b19ae": {
159
+ "name": "Motivational",
160
+ "gender": "Male",
161
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/8dc19b78-4e4e-43a1-ad7b-6585d2f904d0.mp3"
162
+ },
163
+ "153a9408-2959-11ef-b685-a218303b6499": {
164
+ "name": "Youtube Shorts",
165
+ "gender": "Male",
166
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/a56c731f-e776-4870-9aac-4198be5577d3.mp3"
167
+ },
168
+ "4c2e77e8-7f10-4608-9957-e93939da63dc": {
169
+ "name": "Fiction",
170
+ "gender": "Female",
171
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/804e4bb1-bc69-4d60-a81e-0124f1c8fe9b.mp3"
172
+ },
173
+ "9cca245b-4d6a-4d80-ba94-f5cf70938b6a": {
174
+ "name": "Dialogue Delivery",
175
+ "gender": "Male",
176
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/f73eb7f8-4105-4127-b637-dda3ee3af51b.mp3"
177
+ },
178
+ "57d7a45c-013a-4e63-b26c-c3c24d57d13e": {
179
+ "name": "Nisha",
180
+ "gender": "Female",
181
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/50bc297f-677c-4065-beb1-7c3c628337a8.mp3"
182
+ },
183
+ "f883d522-2958-11ef-b685-a218303b6499": {
184
+ "name": "Anchor",
185
+ "gender": "Male",
186
+ "sample": "https://storage.googleapis.com/desivocal-cdn/audio-samples/d1429e0f-5ba8-47f1-b62d-06288cd84208.mp3"
187
+ }
188
+ }
189
+ }