synth-ai 0.1.6__py3-none-any.whl → 0.1.8__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.
- synth_ai/zyk/lms/core/all.py +6 -0
- synth_ai/zyk/lms/core/vendor_clients.py +8 -0
- synth_ai/zyk/lms/vendors/supported/openrouter.py +70 -0
- {synth_ai-0.1.6.dist-info → synth_ai-0.1.8.dist-info}/METADATA +1 -1
- {synth_ai-0.1.6.dist-info → synth_ai-0.1.8.dist-info}/RECORD +8 -7
- {synth_ai-0.1.6.dist-info → synth_ai-0.1.8.dist-info}/WHEEL +0 -0
- {synth_ai-0.1.6.dist-info → synth_ai-0.1.8.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.1.6.dist-info → synth_ai-0.1.8.dist-info}/top_level.txt +0 -0
synth_ai/zyk/lms/core/all.py
CHANGED
@@ -9,6 +9,7 @@ from synth_ai.zyk.lms.vendors.supported.together import TogetherAPI
|
|
9
9
|
from synth_ai.zyk.lms.vendors.supported.groq import GroqAPI
|
10
10
|
from synth_ai.zyk.lms.vendors.core.mistral_api import MistralAPI
|
11
11
|
from synth_ai.zyk.lms.vendors.supported.custom_endpoint import CustomEndpointAPI
|
12
|
+
from synth_ai.zyk.lms.vendors.supported.openrouter import OpenRouterAPI
|
12
13
|
|
13
14
|
|
14
15
|
class OpenAIClient(OpenAIPrivate):
|
@@ -51,3 +52,8 @@ class MistralClient(MistralAPI):
|
|
51
52
|
class CustomEndpointClient(CustomEndpointAPI):
|
52
53
|
def __init__(self, endpoint_url: str):
|
53
54
|
super().__init__(endpoint_url=endpoint_url)
|
55
|
+
|
56
|
+
|
57
|
+
class OpenRouterClient(OpenRouterAPI):
|
58
|
+
def __init__(self):
|
59
|
+
super().__init__()
|
@@ -11,6 +11,7 @@ from synth_ai.zyk.lms.core.all import (
|
|
11
11
|
OpenAIStructuredOutputClient,
|
12
12
|
TogetherClient,
|
13
13
|
CustomEndpointClient,
|
14
|
+
OpenRouterClient,
|
14
15
|
)
|
15
16
|
|
16
17
|
openai_naming_regexes: List[Pattern] = [
|
@@ -48,12 +49,17 @@ groq_naming_regexes: List[Pattern] = [
|
|
48
49
|
re.compile(r"^meta-llama/llama-4-scout-17b-16e-instruct$"),
|
49
50
|
re.compile(r"^meta-llama/llama-4-maverick-17b-128e-instruct$"),
|
50
51
|
re.compile(r"^qwen/qwen3-32b$"),
|
52
|
+
re.compile(r"^moonshotai/kimi-k2-instruct$"),
|
51
53
|
]
|
52
54
|
|
53
55
|
mistral_naming_regexes: List[Pattern] = [
|
54
56
|
re.compile(r"^mistral-.*$"),
|
55
57
|
]
|
56
58
|
|
59
|
+
openrouter_naming_regexes: List[Pattern] = [
|
60
|
+
re.compile(r"^openrouter/.*$"), # openrouter/model-name pattern
|
61
|
+
]
|
62
|
+
|
57
63
|
# Custom endpoint patterns - check these before generic patterns
|
58
64
|
custom_endpoint_naming_regexes: List[Pattern] = [
|
59
65
|
# Modal endpoints: org--app.modal.run
|
@@ -92,6 +98,8 @@ def get_client(
|
|
92
98
|
return GroqClient()
|
93
99
|
elif any(regex.match(model_name) for regex in mistral_naming_regexes):
|
94
100
|
return MistralClient()
|
101
|
+
elif any(regex.match(model_name) for regex in openrouter_naming_regexes):
|
102
|
+
return OpenRouterClient()
|
95
103
|
elif any(regex.match(model_name) for regex in custom_endpoint_naming_regexes):
|
96
104
|
# Custom endpoints are passed as the endpoint URL
|
97
105
|
return CustomEndpointClient(endpoint_url=model_name)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import os
|
2
|
+
from typing import Any, Dict, List, Optional
|
3
|
+
from openai import AsyncOpenAI, OpenAI
|
4
|
+
from synth_ai.zyk.lms.vendors.openai_standard import OpenAIStandard
|
5
|
+
from synth_ai.zyk.lms.vendors.base import BaseLMResponse
|
6
|
+
from synth_ai.zyk.lms.tools.base import BaseTool
|
7
|
+
|
8
|
+
|
9
|
+
class OpenRouterAPI(OpenAIStandard):
|
10
|
+
"""OpenRouter API client for accessing various models through OpenRouter's unified API."""
|
11
|
+
|
12
|
+
def __init__(self):
|
13
|
+
api_key = os.getenv("OPENROUTER_API_KEY")
|
14
|
+
if not api_key:
|
15
|
+
raise ValueError("OPENROUTER_API_KEY environment variable is not set")
|
16
|
+
|
17
|
+
# OpenRouter requires specific headers
|
18
|
+
default_headers = {
|
19
|
+
"HTTP-Referer": os.getenv("OPENROUTER_APP_URL", "https://github.com/synth-laboratories/synth-ai"),
|
20
|
+
"X-Title": os.getenv("OPENROUTER_APP_TITLE", "synth-ai")
|
21
|
+
}
|
22
|
+
|
23
|
+
super().__init__(
|
24
|
+
sync_client=OpenAI(
|
25
|
+
api_key=api_key,
|
26
|
+
base_url="https://openrouter.ai/api/v1",
|
27
|
+
default_headers=default_headers
|
28
|
+
),
|
29
|
+
async_client=AsyncOpenAI(
|
30
|
+
api_key=api_key,
|
31
|
+
base_url="https://openrouter.ai/api/v1",
|
32
|
+
default_headers=default_headers
|
33
|
+
)
|
34
|
+
)
|
35
|
+
|
36
|
+
def _strip_prefix(self, model: str) -> str:
|
37
|
+
"""Remove the 'openrouter/' prefix from model names."""
|
38
|
+
if model.startswith("openrouter/"):
|
39
|
+
return model[len("openrouter/"):]
|
40
|
+
return model
|
41
|
+
|
42
|
+
async def _hit_api_async(
|
43
|
+
self,
|
44
|
+
model: str,
|
45
|
+
messages: List[Dict[str, Any]],
|
46
|
+
lm_config: Dict[str, Any],
|
47
|
+
use_ephemeral_cache_only: bool = False,
|
48
|
+
reasoning_effort: str = "high",
|
49
|
+
tools: Optional[List[BaseTool]] = None,
|
50
|
+
) -> BaseLMResponse:
|
51
|
+
# Strip the 'openrouter/' prefix before calling the API
|
52
|
+
model = self._strip_prefix(model)
|
53
|
+
return await super()._hit_api_async(
|
54
|
+
model, messages, lm_config, use_ephemeral_cache_only, reasoning_effort, tools
|
55
|
+
)
|
56
|
+
|
57
|
+
def _hit_api_sync(
|
58
|
+
self,
|
59
|
+
model: str,
|
60
|
+
messages: List[Dict[str, Any]],
|
61
|
+
lm_config: Dict[str, Any],
|
62
|
+
use_ephemeral_cache_only: bool = False,
|
63
|
+
reasoning_effort: str = "high",
|
64
|
+
tools: Optional[List[BaseTool]] = None,
|
65
|
+
) -> BaseLMResponse:
|
66
|
+
# Strip the 'openrouter/' prefix before calling the API
|
67
|
+
model = self._strip_prefix(model)
|
68
|
+
return super()._hit_api_sync(
|
69
|
+
model, messages, lm_config, use_ephemeral_cache_only, reasoning_effort, tools
|
70
|
+
)
|
@@ -11,10 +11,10 @@ synth_ai/zyk/lms/caching/handler.py,sha256=HEo_e8q3kqDSVW0hN1AA6Rx5cBvlEeizi-kiO
|
|
11
11
|
synth_ai/zyk/lms/caching/initialize.py,sha256=zZls6RKAax6Z-8oJInGaSg_RPN_fEZ6e_RCX64lMLJw,416
|
12
12
|
synth_ai/zyk/lms/caching/persistent.py,sha256=ZaY1A9qhvfNKzcAI9FnwbIrgMKvVeIfb_yCyl3M8dxE,2860
|
13
13
|
synth_ai/zyk/lms/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
synth_ai/zyk/lms/core/all.py,sha256=
|
14
|
+
synth_ai/zyk/lms/core/all.py,sha256=hy6voRBO76geqG9IWWOyb_65Gay_iaEuRNblTz-gEi4,1574
|
15
15
|
synth_ai/zyk/lms/core/exceptions.py,sha256=K0BVdAzxVIchsvYZAaHEH1GAWBZvpxhFi-SPcJOjyPQ,205
|
16
16
|
synth_ai/zyk/lms/core/main.py,sha256=pLz7COTdvDWQivYaA1iYYF2onUOosD_sFaPJG48bdKM,10598
|
17
|
-
synth_ai/zyk/lms/core/vendor_clients.py,sha256=
|
17
|
+
synth_ai/zyk/lms/core/vendor_clients.py,sha256=aOON3T3OJ69U9mLF3C6-LQ9kcx6-nKZIbF2YzO_5Cl8,3948
|
18
18
|
synth_ai/zyk/lms/cost/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
synth_ai/zyk/lms/cost/monitor.py,sha256=cSKIvw6WdPZIRubADWxQoh1MdB40T8-jjgfNUeUHIn0,5
|
20
20
|
synth_ai/zyk/lms/cost/statefulness.py,sha256=TOsuXL8IjtKOYJ2aJQF8TwJVqn_wQ7AIwJJmdhMye7U,36
|
@@ -40,9 +40,10 @@ synth_ai/zyk/lms/vendors/supported/custom_endpoint.py,sha256=awluDoUgcRROsZdH_o_
|
|
40
40
|
synth_ai/zyk/lms/vendors/supported/deepseek.py,sha256=BElW0NGpkSA62wOqzzMtDw8XR36rSNXK5LldeHJkQrc,2430
|
41
41
|
synth_ai/zyk/lms/vendors/supported/groq.py,sha256=Fbi7QvhdLx0F-VHO5PY-uIQlPR0bo3C9h1MvIOx8nz0,388
|
42
42
|
synth_ai/zyk/lms/vendors/supported/ollama.py,sha256=K30VBFRTd7NYyPmyBVRZS2sm0UB651AHp9i3wd55W64,469
|
43
|
+
synth_ai/zyk/lms/vendors/supported/openrouter.py,sha256=QdpqZFVCap-0oPsKiJkWr7o-dGaX3IMPSGehS2jw1IM,2607
|
43
44
|
synth_ai/zyk/lms/vendors/supported/together.py,sha256=Ni_jBqqGPN0PkkY-Ew64s3gNKk51k3FCpLSwlNhKbf0,342
|
44
|
-
synth_ai-0.1.
|
45
|
-
synth_ai-0.1.
|
46
|
-
synth_ai-0.1.
|
47
|
-
synth_ai-0.1.
|
48
|
-
synth_ai-0.1.
|
45
|
+
synth_ai-0.1.8.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
|
46
|
+
synth_ai-0.1.8.dist-info/METADATA,sha256=mXoPocDv-vqgeXFJkrve0JBF-neWEU9CNEPSMjSfv9s,1084
|
47
|
+
synth_ai-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
48
|
+
synth_ai-0.1.8.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
|
49
|
+
synth_ai-0.1.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|