ccs-llmconnector 1.1.1__py3-none-any.whl → 1.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ccs_llmconnector-1.1.1.dist-info → ccs_llmconnector-1.1.2.dist-info}/METADATA +1 -1
- {ccs_llmconnector-1.1.1.dist-info → ccs_llmconnector-1.1.2.dist-info}/RECORD +7 -7
- llmconnector/gemini_client.py +56 -38
- {ccs_llmconnector-1.1.1.dist-info → ccs_llmconnector-1.1.2.dist-info}/WHEEL +0 -0
- {ccs_llmconnector-1.1.1.dist-info → ccs_llmconnector-1.1.2.dist-info}/entry_points.txt +0 -0
- {ccs_llmconnector-1.1.1.dist-info → ccs_llmconnector-1.1.2.dist-info}/licenses/LICENSE +0 -0
- {ccs_llmconnector-1.1.1.dist-info → ccs_llmconnector-1.1.2.dist-info}/top_level.txt +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
ccs_llmconnector-1.1.
|
|
1
|
+
ccs_llmconnector-1.1.2.dist-info/licenses/LICENSE,sha256=rPcz2YmBB9VUWZTLJcRO_B4jKDpqmGRYi2eSI-unysg,1083
|
|
2
2
|
llmconnector/__init__.py,sha256=w68d7BCkhjjqMaOG9VDkPoYR4PNbv8NJqGmAV_Vyn6g,1358
|
|
3
3
|
llmconnector/anthropic_client.py,sha256=hGFZlUQ4yAs_H8StxWzHAYmqwgNT6lGI4yW8UmKhtm8,13260
|
|
4
4
|
llmconnector/client.py,sha256=2rhDpcBKKbQ1kGp7-Bk8ci_VVe9DEEvBf9nH4hKwg3w,13849
|
|
5
5
|
llmconnector/client_cli.py,sha256=ojLPNJ14lFycsLWtEMtdGpV033v2-23qPMuWqFlnySA,11463
|
|
6
|
-
llmconnector/gemini_client.py,sha256=
|
|
6
|
+
llmconnector/gemini_client.py,sha256=6J_dhPGEjh2n30uM8Jo1gUocyC_v7HnqZrXYXA5BVIA,19407
|
|
7
7
|
llmconnector/grok_client.py,sha256=uicZI28-vw7go677zZB5MTkw5aqWp2UP_GaguNUU99o,11254
|
|
8
8
|
llmconnector/openai_client.py,sha256=wvrEFzltg8PctM2DcNZ_7qmRPpF-CB8WQek6iYoRvR4,11051
|
|
9
9
|
llmconnector/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
10
10
|
llmconnector/types.py,sha256=JhXKjKncdUB2yPd-bqjOUnl-4Wgs6GIleDMChmwPW8w,1287
|
|
11
11
|
llmconnector/utils.py,sha256=Tw6wQLh7Cjk6igLJ-MnYGSSPJBUGl5-7R1xB0Aj7o8Y,2047
|
|
12
|
-
ccs_llmconnector-1.1.
|
|
13
|
-
ccs_llmconnector-1.1.
|
|
14
|
-
ccs_llmconnector-1.1.
|
|
15
|
-
ccs_llmconnector-1.1.
|
|
16
|
-
ccs_llmconnector-1.1.
|
|
12
|
+
ccs_llmconnector-1.1.2.dist-info/METADATA,sha256=LEWid1Hh1gdCA3rcF5KskOpc_Em8najLRjZdA1ep8kI,17001
|
|
13
|
+
ccs_llmconnector-1.1.2.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
14
|
+
ccs_llmconnector-1.1.2.dist-info/entry_points.txt,sha256=eFvLY3nHAG_QhaKlemhhK7echfezW0KiMdSNMZOStLc,60
|
|
15
|
+
ccs_llmconnector-1.1.2.dist-info/top_level.txt,sha256=Doer7TAUsN8UXQfPHPNsuBXVNCz2uV-Q0v4t4fwv_MM,13
|
|
16
|
+
ccs_llmconnector-1.1.2.dist-info/RECORD,,
|
llmconnector/gemini_client.py
CHANGED
|
@@ -15,11 +15,29 @@ from google.genai import types
|
|
|
15
15
|
from .types import ImageInput, MessageSequence, normalize_messages
|
|
16
16
|
from .utils import clamp_retries, run_sync_in_thread, run_with_retries
|
|
17
17
|
|
|
18
|
-
logger = logging.getLogger(__name__)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
_GEMINI_MIN_TIMEOUT_S = 10.0
|
|
22
|
+
_GEMINI_MIN_TIMEOUT_MS = int(_GEMINI_MIN_TIMEOUT_S * 1000)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _normalize_gemini_timeout_ms(timeout_s: float) -> int:
|
|
26
|
+
"""Convert a seconds timeout into the millisecond value expected by google-genai HttpOptions."""
|
|
27
|
+
# google-genai HttpOptions expects milliseconds, but our public API uses seconds.
|
|
28
|
+
effective_timeout_s = max(_GEMINI_MIN_TIMEOUT_S, timeout_s)
|
|
29
|
+
if effective_timeout_s != timeout_s:
|
|
30
|
+
logger.warning(
|
|
31
|
+
"Gemini timeout %ss is too short, clamping to %ss.",
|
|
32
|
+
timeout_s,
|
|
33
|
+
effective_timeout_s,
|
|
34
|
+
)
|
|
35
|
+
timeout_ms = int(effective_timeout_s * 1000)
|
|
36
|
+
return max(_GEMINI_MIN_TIMEOUT_MS, timeout_ms)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class GeminiClient:
|
|
40
|
+
"""Convenience wrapper around the Google Gemini SDK."""
|
|
23
41
|
|
|
24
42
|
def generate_response(
|
|
25
43
|
self,
|
|
@@ -102,15 +120,13 @@ class GeminiClient:
|
|
|
102
120
|
|
|
103
121
|
retry_count = clamp_retries(max_retries)
|
|
104
122
|
|
|
105
|
-
def _build_client() -> genai.Client:
|
|
106
|
-
client_kwargs: dict[str, object] = {"api_key": api_key}
|
|
107
|
-
if timeout_s is not None:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
client_kwargs["http_options"] = types.HttpOptions(timeout=effective_timeout)
|
|
113
|
-
return genai.Client(**client_kwargs)
|
|
123
|
+
def _build_client() -> genai.Client:
|
|
124
|
+
client_kwargs: dict[str, object] = {"api_key": api_key}
|
|
125
|
+
if timeout_s is not None:
|
|
126
|
+
client_kwargs["http_options"] = types.HttpOptions(
|
|
127
|
+
timeout=_normalize_gemini_timeout_ms(timeout_s)
|
|
128
|
+
)
|
|
129
|
+
return genai.Client(**client_kwargs)
|
|
114
130
|
|
|
115
131
|
def _run_request() -> str:
|
|
116
132
|
client = _build_client()
|
|
@@ -268,15 +284,13 @@ class GeminiClient:
|
|
|
268
284
|
|
|
269
285
|
retry_count = clamp_retries(max_retries)
|
|
270
286
|
|
|
271
|
-
def _build_client() -> genai.Client:
|
|
272
|
-
client_kwargs: dict[str, object] = {"api_key": api_key}
|
|
273
|
-
if timeout_s is not None:
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
client_kwargs["http_options"] = types.HttpOptions(timeout=effective_timeout)
|
|
279
|
-
return genai.Client(**client_kwargs)
|
|
287
|
+
def _build_client() -> genai.Client:
|
|
288
|
+
client_kwargs: dict[str, object] = {"api_key": api_key}
|
|
289
|
+
if timeout_s is not None:
|
|
290
|
+
client_kwargs["http_options"] = types.HttpOptions(
|
|
291
|
+
timeout=_normalize_gemini_timeout_ms(timeout_s)
|
|
292
|
+
)
|
|
293
|
+
return genai.Client(**client_kwargs)
|
|
280
294
|
|
|
281
295
|
def _run_request() -> bytes:
|
|
282
296
|
client = _build_client()
|
|
@@ -362,15 +376,13 @@ class GeminiClient:
|
|
|
362
376
|
|
|
363
377
|
retry_count = clamp_retries(max_retries)
|
|
364
378
|
|
|
365
|
-
def _build_client() -> genai.Client:
|
|
366
|
-
client_kwargs: dict[str, object] = {"api_key": api_key}
|
|
367
|
-
if timeout_s is not None:
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
client_kwargs["http_options"] = types.HttpOptions(timeout=effective_timeout)
|
|
373
|
-
return genai.Client(**client_kwargs)
|
|
379
|
+
def _build_client() -> genai.Client:
|
|
380
|
+
client_kwargs: dict[str, object] = {"api_key": api_key}
|
|
381
|
+
if timeout_s is not None:
|
|
382
|
+
client_kwargs["http_options"] = types.HttpOptions(
|
|
383
|
+
timeout=_normalize_gemini_timeout_ms(timeout_s)
|
|
384
|
+
)
|
|
385
|
+
return genai.Client(**client_kwargs)
|
|
374
386
|
|
|
375
387
|
def _run_request() -> list[dict[str, Optional[str]]]:
|
|
376
388
|
models: list[dict[str, Optional[str]]] = []
|
|
@@ -457,12 +469,18 @@ class GeminiClient:
|
|
|
457
469
|
return _part_from_path(Path(image))
|
|
458
470
|
|
|
459
471
|
|
|
460
|
-
def _part_from_path(path: Path) -> types.Part:
|
|
461
|
-
"""Create an image part from a local filesystem path."""
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
472
|
+
def _part_from_path(path: Path) -> types.Part:
|
|
473
|
+
"""Create an image part from a local filesystem path."""
|
|
474
|
+
# Ensure common audio types are recognized across platforms (used for transcription as well).
|
|
475
|
+
mimetypes.add_type("audio/mp4", ".m4a")
|
|
476
|
+
mimetypes.add_type("audio/mpeg", ".mp3")
|
|
477
|
+
mimetypes.add_type("audio/wav", ".wav")
|
|
478
|
+
mimetypes.add_type("audio/aac", ".aac")
|
|
479
|
+
|
|
480
|
+
expanded = path.expanduser()
|
|
481
|
+
data = expanded.read_bytes()
|
|
482
|
+
mime_type = mimetypes.guess_type(expanded.name)[0] or "application/octet-stream"
|
|
483
|
+
return types.Part.from_bytes(data=data, mime_type=mime_type)
|
|
466
484
|
|
|
467
485
|
|
|
468
486
|
def _part_from_url(url: str) -> types.Part:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|