synth-ai 0.1.5__py3-none-any.whl → 0.1.7__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/__init__.py CHANGED
@@ -4,5 +4,5 @@ Synth AI - Software for aiding the best and multiplying the will.
4
4
 
5
5
  from synth_ai.zyk import LM # Assuming LM is in zyk.py in the same directory
6
6
 
7
- __version__ = "0.1.5"
7
+ __version__ = "0.1.6"
8
8
  __all__ = ["LM"] # Explicitly define public API
@@ -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] = [
@@ -54,6 +55,10 @@ mistral_naming_regexes: List[Pattern] = [
54
55
  re.compile(r"^mistral-.*$"),
55
56
  ]
56
57
 
58
+ openrouter_naming_regexes: List[Pattern] = [
59
+ re.compile(r"^openrouter/.*$"), # openrouter/model-name pattern
60
+ ]
61
+
57
62
  # Custom endpoint patterns - check these before generic patterns
58
63
  custom_endpoint_naming_regexes: List[Pattern] = [
59
64
  # Modal endpoints: org--app.modal.run
@@ -92,6 +97,8 @@ def get_client(
92
97
  return GroqClient()
93
98
  elif any(regex.match(model_name) for regex in mistral_naming_regexes):
94
99
  return MistralClient()
100
+ elif any(regex.match(model_name) for regex in openrouter_naming_regexes):
101
+ return OpenRouterClient()
95
102
  elif any(regex.match(model_name) for regex in custom_endpoint_naming_regexes):
96
103
  # Custom endpoints are passed as the endpoint URL
97
104
  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
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synth-ai
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Home-page: https://github.com/synth-laboratories/synth-ai
5
5
  Author: Josh Purtell
6
6
  Author-email: josh@usesynth.com
@@ -1,4 +1,4 @@
1
- synth_ai/__init__.py,sha256=-qLyQqdy3njK2e_kHYslyaPezwEs9XgpovFi4ZyJWBs,225
1
+ synth_ai/__init__.py,sha256=2y79prX5jWHSuU6LWUXIQueT6y_o79P1ACvxDjNSKI0,225
2
2
  synth_ai/zyk/__init__.py,sha256=kGMD-drlBVdsyT-QFODMwaZUtxPCJ9mg58GKQUvFqo0,134
3
3
  synth_ai/zyk/lms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  synth_ai/zyk/lms/config.py,sha256=UBMi0DIFQDBV_eGPK5vG8R7VwxXcV10BPGq1iV8vVjg,282
@@ -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=MAlhGk5LBK7En-oUzFBoemGl_GZbenmvqhlkSQ7cfGc,1410
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=7D30Ol-eVaJ8pZnbqeKADJ6q_Nz5buOd2qQJrrn8Rlk,3647
17
+ synth_ai/zyk/lms/core/vendor_clients.py,sha256=A9_BR2lek9P8xzn_AXfdPbA0cguDhs7ZyyJeekNdRy8,3898
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.5.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
45
- synth_ai-0.1.5.dist-info/METADATA,sha256=Ip_93PnkbnO2yIKXxg-Pzqi7oBF7s4DrM5UYlXnUSBE,1084
46
- synth_ai-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- synth_ai-0.1.5.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
48
- synth_ai-0.1.5.dist-info/RECORD,,
45
+ synth_ai-0.1.7.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
46
+ synth_ai-0.1.7.dist-info/METADATA,sha256=dShMPd1m1ftiyhlhiZqWUoxxVhk53f9zS8hlbQVC6JA,1084
47
+ synth_ai-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
+ synth_ai-0.1.7.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
49
+ synth_ai-0.1.7.dist-info/RECORD,,