synth-ai 0.1.8__py3-none-any.whl → 0.2.0__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.6"
7
+ __version__ = "0.1.9"
8
8
  __all__ = ["LM"] # Explicitly define public API
@@ -7,6 +7,7 @@ from synth_ai.zyk.lms.vendors.core.openai_api import (
7
7
  from synth_ai.zyk.lms.vendors.supported.deepseek import DeepSeekAPI
8
8
  from synth_ai.zyk.lms.vendors.supported.together import TogetherAPI
9
9
  from synth_ai.zyk.lms.vendors.supported.groq import GroqAPI
10
+ from synth_ai.zyk.lms.vendors.supported.grok import GrokAPI
10
11
  from synth_ai.zyk.lms.vendors.core.mistral_api import MistralAPI
11
12
  from synth_ai.zyk.lms.vendors.supported.custom_endpoint import CustomEndpointAPI
12
13
  from synth_ai.zyk.lms.vendors.supported.openrouter import OpenRouterAPI
@@ -44,6 +45,11 @@ class GroqClient(GroqAPI):
44
45
  super().__init__()
45
46
 
46
47
 
48
+ class GrokClient(GrokAPI):
49
+ def __init__(self):
50
+ super().__init__()
51
+
52
+
47
53
  class MistralClient(MistralAPI):
48
54
  def __init__(self):
49
55
  super().__init__()
@@ -1,4 +1,5 @@
1
- from typing import Any, Dict, List, Literal, Optional
1
+ from typing import Any, Dict, List, Literal, Optional, Union
2
+ import os
2
3
 
3
4
  from pydantic import BaseModel, Field
4
5
 
@@ -66,6 +67,21 @@ def build_messages(
66
67
 
67
68
 
68
69
  class LM:
70
+ """
71
+ Language Model interface for interacting with various AI providers.
72
+
73
+ Args:
74
+ model_name: The name of the model to use.
75
+ formatting_model_name: The model to use for formatting structured outputs.
76
+ temperature: The temperature setting for the model (0.0 to 1.0).
77
+ max_retries: Number of retries for API calls ("None", "Few", or "Many").
78
+ structured_output_mode: Mode for structured outputs ("stringified_json" or "forced_json").
79
+ synth_logging: Whether to enable Synth logging.
80
+ provider: Optional provider override. If specified, forces the use of a specific vendor
81
+ implementation regardless of model name. Can also be set via SYNTH_AI_DEFAULT_PROVIDER
82
+ environment variable. Supported values: "openai", "anthropic", "groq", "gemini",
83
+ "deepseek", "grok", "mistral", "openrouter", "together", or a custom string.
84
+ """
69
85
  # if str
70
86
  model_name: str
71
87
  client: VendorBase
@@ -82,16 +98,21 @@ class LM:
82
98
  "stringified_json", "forced_json"
83
99
  ] = "stringified_json",
84
100
  synth_logging: bool = True,
101
+ provider: Optional[Union[Literal["openai", "anthropic", "groq", "gemini", "deepseek", "grok", "mistral", "openrouter", "together"], str]] = None,
85
102
  ):
86
103
  # print("Structured output mode", structured_output_mode)
104
+ # Check for environment variable if provider is not specified
105
+ effective_provider = provider or os.environ.get("SYNTH_AI_DEFAULT_PROVIDER")
106
+
87
107
  self.client = get_client(
88
108
  model_name,
89
109
  with_formatting=structured_output_mode == "forced_json",
90
110
  synth_logging=synth_logging,
111
+ provider=effective_provider,
91
112
  )
92
113
  # print(self.client.__class__)
93
114
 
94
- formatting_client = get_client(formatting_model_name, with_formatting=True)
115
+ formatting_client = get_client(formatting_model_name, with_formatting=True, synth_logging=synth_logging, provider=None)
95
116
 
96
117
  max_retries_dict = {"None": 0, "Few": 2, "Many": 5}
97
118
  self.structured_output_handler = StructuredOutputHandler(
@@ -1,11 +1,12 @@
1
1
  import re
2
- from typing import Any, List, Pattern
2
+ from typing import Any, List, Pattern, Optional, Dict
3
3
 
4
4
  from synth_ai.zyk.lms.core.all import (
5
5
  AnthropicClient,
6
6
  DeepSeekClient,
7
7
  GeminiClient,
8
8
  GroqClient,
9
+ GrokClient,
9
10
  MistralClient,
10
11
  # OpenAIClient,
11
12
  OpenAIStructuredOutputClient,
@@ -52,6 +53,13 @@ groq_naming_regexes: List[Pattern] = [
52
53
  re.compile(r"^moonshotai/kimi-k2-instruct$"),
53
54
  ]
54
55
 
56
+ grok_naming_regexes: List[Pattern] = [
57
+ re.compile(r"^grok-3-beta$"),
58
+ re.compile(r"^grok-3-mini-beta$"),
59
+ re.compile(r"^grok-beta$"),
60
+ re.compile(r"^grok-.*$"), # Catch-all for future Grok models
61
+ ]
62
+
55
63
  mistral_naming_regexes: List[Pattern] = [
56
64
  re.compile(r"^mistral-.*$"),
57
65
  ]
@@ -69,13 +77,72 @@ custom_endpoint_naming_regexes: List[Pattern] = [
69
77
  re.compile(r"^[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-]+\.[a-zA-Z]+\/[a-zA-Z0-9\-\/]+$"), # domain.tld/path
70
78
  ]
71
79
 
80
+ # Provider mapping for explicit provider overrides
81
+ PROVIDER_MAP: Dict[str, Any] = {
82
+ "openai": OpenAIStructuredOutputClient,
83
+ "anthropic": AnthropicClient,
84
+ "groq": GroqClient,
85
+ "gemini": GeminiClient,
86
+ "deepseek": DeepSeekClient,
87
+ "grok": GrokClient,
88
+ "mistral": MistralClient,
89
+ "openrouter": OpenRouterClient,
90
+ "together": TogetherClient,
91
+ }
92
+
72
93
 
73
94
  def get_client(
74
95
  model_name: str,
75
96
  with_formatting: bool = False,
76
97
  synth_logging: bool = True,
98
+ provider: Optional[str] = None,
77
99
  ) -> Any:
100
+ """
101
+ Get a vendor client for the specified model.
102
+
103
+ Args:
104
+ model_name: The name of the model to use.
105
+ with_formatting: Whether to use formatting capabilities.
106
+ synth_logging: Whether to enable Synth logging.
107
+ provider: Optional provider override. If specified, forces the use of a specific vendor
108
+ implementation regardless of model name.
109
+
110
+ Returns:
111
+ A vendor client instance.
112
+
113
+ Raises:
114
+ ValueError: If the provider is unsupported or model name is invalid.
115
+ """
78
116
  # print("With formatting", with_formatting)
117
+
118
+ # If provider is explicitly specified, use it
119
+ if provider:
120
+ if provider not in PROVIDER_MAP:
121
+ raise ValueError(f"Unsupported provider: '{provider}'. Supported providers are: {', '.join(PROVIDER_MAP.keys())}")
122
+
123
+ # Log the provider override
124
+ if synth_logging:
125
+ print(f"Provider override: using '{provider}' for model '{model_name}'")
126
+
127
+ client_class = PROVIDER_MAP[provider]
128
+
129
+ # Special handling for OpenAI with formatting
130
+ if provider == "openai":
131
+ return client_class(synth_logging=synth_logging)
132
+ # Special handling for Anthropic with formatting
133
+ elif provider == "anthropic" and with_formatting:
134
+ client = client_class()
135
+ client._hit_api_async_structured_output = OpenAIStructuredOutputClient(
136
+ synth_logging=synth_logging
137
+ )._hit_api_async
138
+ return client
139
+ # Custom endpoint needs the model_name as endpoint_url
140
+ elif provider == "custom_endpoint":
141
+ return CustomEndpointClient(endpoint_url=model_name)
142
+ else:
143
+ return client_class()
144
+
145
+ # Original regex-based detection
79
146
  if any(regex.match(model_name) for regex in openai_naming_regexes):
80
147
  # print("Returning OpenAIStructuredOutputClient")
81
148
  return OpenAIStructuredOutputClient(
@@ -96,6 +163,8 @@ def get_client(
96
163
  return DeepSeekClient()
97
164
  elif any(regex.match(model_name) for regex in groq_naming_regexes):
98
165
  return GroqClient()
166
+ elif any(regex.match(model_name) for regex in grok_naming_regexes):
167
+ return GrokClient()
99
168
  elif any(regex.match(model_name) for regex in mistral_naming_regexes):
100
169
  return MistralClient()
101
170
  elif any(regex.match(model_name) for regex in openrouter_naming_regexes):
@@ -15,7 +15,7 @@ from synth_ai.zyk.lms.constants import (
15
15
  GEMINI_REASONING_MODELS,
16
16
  GEMINI_THINKING_BUDGETS,
17
17
  )
18
- from synth_ai.zyk.lms.vendors.retries import BACKOFF_TOLERANCE, backoff
18
+ from synth_ai.zyk.lms.vendors.retries import BACKOFF_TOLERANCE, MAX_BACKOFF, backoff
19
19
  import logging
20
20
 
21
21
 
@@ -197,6 +197,7 @@ class GeminiAPI(VendorBase):
197
197
  backoff.expo,
198
198
  exceptions_to_retry,
199
199
  max_tries=BACKOFF_TOLERANCE,
200
+ max_time=MAX_BACKOFF,
200
201
  on_giveup=lambda e: print(e),
201
202
  )
202
203
  async def _hit_api_async(
@@ -245,6 +246,7 @@ class GeminiAPI(VendorBase):
245
246
  backoff.expo,
246
247
  exceptions_to_retry,
247
248
  max_tries=BACKOFF_TOLERANCE,
249
+ max_time=MAX_BACKOFF,
248
250
  on_giveup=lambda e: print(e),
249
251
  )
250
252
  def _hit_api_sync(
@@ -11,6 +11,8 @@ from synth_ai.zyk.lms.caching.initialize import (
11
11
  from synth_ai.zyk.lms.tools.base import BaseTool
12
12
  from synth_ai.zyk.lms.vendors.base import BaseLMResponse, VendorBase
13
13
  from synth_ai.zyk.lms.constants import SPECIAL_BASE_TEMPS
14
+ from synth_ai.zyk.lms.vendors.retries import MAX_BACKOFF
15
+ import backoff
14
16
 
15
17
  DEFAULT_EXCEPTIONS_TO_RETRY = (
16
18
  pydantic_core._pydantic_core.ValidationError,
@@ -35,16 +37,9 @@ def special_orion_transform(
35
37
  return messages
36
38
 
37
39
 
38
- def on_backoff_handler_async(details):
39
- # Print every 5th retry attempt, excluding the first retry
40
- if details["tries"] > 1 and (details["tries"] - 1) % 5 == 0:
41
- print(f"Retrying async API call (attempt {details['tries'] - 1})")
42
-
43
-
44
- def on_backoff_handler_sync(details):
45
- # Print every 5th retry attempt, excluding the first retry
46
- if details["tries"] > 1 and (details["tries"] - 1) % 5 == 0:
47
- print(f"Retrying sync API call (attempt {details['tries'] - 1})")
40
+ def _silent_backoff_handler(_details):
41
+ """No-op handler to keep stdout clean while still allowing visibility via logging if desired."""
42
+ pass
48
43
 
49
44
 
50
45
  class OpenAIStandard(VendorBase):
@@ -65,13 +60,13 @@ class OpenAIStandard(VendorBase):
65
60
  self.used_for_structured_outputs = used_for_structured_outputs
66
61
  self.exceptions_to_retry = exceptions_to_retry
67
62
 
68
- # @backoff.on_exception(
69
- # backoff.expo,
70
- # exceptions_to_retry,
71
- # max_tries=BACKOFF_TOLERANCE,
72
- # on_backoff=on_backoff_handler_async,
73
- # on_giveup=lambda e: print(e),
74
- # )
63
+ @backoff.on_exception(
64
+ backoff.expo,
65
+ DEFAULT_EXCEPTIONS_TO_RETRY,
66
+ max_time=MAX_BACKOFF,
67
+ jitter=backoff.full_jitter,
68
+ on_backoff=_silent_backoff_handler,
69
+ )
75
70
  async def _hit_api_async(
76
71
  self,
77
72
  model: str,
@@ -145,13 +140,13 @@ class OpenAIStandard(VendorBase):
145
140
  )
146
141
  return lm_response
147
142
 
148
- # @backoff.on_exception(
149
- # backoff.expo,
150
- # exceptions_to_retry,
151
- # max_tries=BACKOFF_TOLERANCE,
152
- # on_backoff=on_backoff_handler_sync,
153
- # on_giveup=lambda e: print(e),
154
- # )
143
+ @backoff.on_exception(
144
+ backoff.expo,
145
+ DEFAULT_EXCEPTIONS_TO_RETRY,
146
+ max_time=MAX_BACKOFF,
147
+ jitter=backoff.full_jitter,
148
+ on_backoff=_silent_backoff_handler,
149
+ )
155
150
  def _hit_api_sync(
156
151
  self,
157
152
  model: str,
@@ -1,3 +1,14 @@
1
1
  import backoff
2
+ import os
2
3
 
3
- BACKOFF_TOLERANCE = 20
4
+ # Number of retry attempts that some legacy decorators rely on.
5
+ BACKOFF_TOLERANCE: int = 20
6
+
7
+ # Maximum wall-clock seconds allowed for exponential back-off when retrying an
8
+ # LLM API call. This can be overridden at runtime with the environment
9
+ # variable `SYNTH_AI_MAX_BACKOFF`.
10
+
11
+ try:
12
+ MAX_BACKOFF: int = max(1, int(os.getenv("SYNTH_AI_MAX_BACKOFF", "120")))
13
+ except ValueError:
14
+ MAX_BACKOFF = 120
@@ -0,0 +1,77 @@
1
+ import os
2
+ from typing import Any, Dict, List, Optional
3
+
4
+ from openai import AsyncOpenAI, OpenAI
5
+
6
+ from synth_ai.zyk.lms.tools.base import BaseTool
7
+ from synth_ai.zyk.lms.vendors.openai_standard import OpenAIStandard
8
+
9
+
10
+ class GrokAPI(OpenAIStandard):
11
+ """
12
+ Vendor shim for xAI Grok models.
13
+
14
+ It re-uses ``OpenAIStandard`` because xAI's REST endpoints are
15
+ OpenAI-compatible, including the ``tools`` / ``tool_choice`` function-calling
16
+ interface.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ *,
22
+ api_key: Optional[str] = None,
23
+ base_url: str = "https://api.x.ai/v1",
24
+ ) -> None:
25
+ api_key = api_key or os.getenv("XAI_API_KEY")
26
+ if not api_key:
27
+ raise ValueError(
28
+ "Set the XAI_API_KEY environment variable or pass api_key explicitly."
29
+ )
30
+
31
+ super().__init__(
32
+ sync_client=OpenAI(api_key=api_key, base_url=base_url),
33
+ async_client=AsyncOpenAI(api_key=api_key, base_url=base_url),
34
+ used_for_structured_outputs=True,
35
+ )
36
+
37
+ async def _hit_api_async(
38
+ self,
39
+ model: str,
40
+ messages: List[Dict[str, Any]],
41
+ lm_config: Dict[str, Any],
42
+ use_ephemeral_cache_only: bool = False,
43
+ reasoning_effort: str = "high",
44
+ tools: Optional[List[BaseTool]] = None,
45
+ ):
46
+ if not model:
47
+ raise ValueError("Model name is required for Grok API calls")
48
+
49
+ return await super()._hit_api_async(
50
+ model,
51
+ messages,
52
+ lm_config,
53
+ use_ephemeral_cache_only=use_ephemeral_cache_only,
54
+ reasoning_effort=reasoning_effort,
55
+ tools=tools,
56
+ )
57
+
58
+ def _hit_api_sync(
59
+ self,
60
+ model: str,
61
+ messages: List[Dict[str, Any]],
62
+ lm_config: Dict[str, Any],
63
+ use_ephemeral_cache_only: bool = False,
64
+ reasoning_effort: str = "high",
65
+ tools: Optional[List[BaseTool]] = None,
66
+ ):
67
+ if not model:
68
+ raise ValueError("Model name is required for Grok API calls")
69
+
70
+ return super()._hit_api_sync(
71
+ model,
72
+ messages,
73
+ lm_config,
74
+ use_ephemeral_cache_only=use_ephemeral_cache_only,
75
+ reasoning_effort=reasoning_effort,
76
+ tools=tools,
77
+ )
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.2
2
2
  Name: synth-ai
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Home-page: https://github.com/synth-laboratories/synth-ai
5
5
  Author: Josh Purtell
6
6
  Author-email: josh@usesynth.com
@@ -21,7 +21,6 @@ Dynamic: description
21
21
  Dynamic: description-content-type
22
22
  Dynamic: home-page
23
23
  Dynamic: license
24
- Dynamic: license-file
25
24
  Dynamic: requires-dist
26
25
 
27
26
  AI Infra used by the Synth AI Team
@@ -1,4 +1,4 @@
1
- synth_ai/__init__.py,sha256=2y79prX5jWHSuU6LWUXIQueT6y_o79P1ACvxDjNSKI0,225
1
+ synth_ai/__init__.py,sha256=x_BG2UuNMVSWKD1_1fodWkGTR-Qy2Gi-JsPgwBrXnac,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=hy6voRBO76geqG9IWWOyb_65Gay_iaEuRNblTz-gEi4,1574
14
+ synth_ai/zyk/lms/core/all.py,sha256=g8STaOhfEWpNEf-1BGlP0ufysHAdw3Rvo7XHHn0VJ6U,1714
15
15
  synth_ai/zyk/lms/core/exceptions.py,sha256=K0BVdAzxVIchsvYZAaHEH1GAWBZvpxhFi-SPcJOjyPQ,205
16
- synth_ai/zyk/lms/core/main.py,sha256=pLz7COTdvDWQivYaA1iYYF2onUOosD_sFaPJG48bdKM,10598
17
- synth_ai/zyk/lms/core/vendor_clients.py,sha256=aOON3T3OJ69U9mLF3C6-LQ9kcx6-nKZIbF2YzO_5Cl8,3948
16
+ synth_ai/zyk/lms/core/main.py,sha256=3aqxAJdHyeJQWgP6jImRu7RyLaPASzxjkpJcwzQn-Hs,11955
17
+ synth_ai/zyk/lms/core/vendor_clients.py,sha256=LBe_Mv3TPF5TF-v0LVodA-HIOFTAZn5aE8RqmpPF9ho,6455
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
@@ -26,11 +26,11 @@ synth_ai/zyk/lms/tools/__init__.py,sha256=3JM5vqZqKloaeHaxuO49C8A_0qljys3pQ1yt70
26
26
  synth_ai/zyk/lms/tools/base.py,sha256=i-AIVRlitiQ4JMJ_BBFRSpUcWgxWIUYoHxAqfxHN_7E,4056
27
27
  synth_ai/zyk/lms/vendors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  synth_ai/zyk/lms/vendors/base.py,sha256=aK4PEtkMLt_o3qD22kW-x3HJUEKdIk06zlH4kX0VkAE,760
29
- synth_ai/zyk/lms/vendors/openai_standard.py,sha256=dgHC7RWrxwaWto6_frKdfEKazKvvAMYJM1YgJgbVpb8,12279
30
- synth_ai/zyk/lms/vendors/retries.py,sha256=m-WvAiPix9ovnO2S-m53Td5VZDWBVBFuHuSK9--OVxw,38
29
+ synth_ai/zyk/lms/vendors/openai_standard.py,sha256=VP7DK2hPY5Cxu2e-qQZNaqOHTxQNjIYBdgQxjMTsMdg,11985
30
+ synth_ai/zyk/lms/vendors/retries.py,sha256=8R1UjTSwjO5O7eCf2TKCCNWYiwltb0YY_g3pilIYkNE,428
31
31
  synth_ai/zyk/lms/vendors/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  synth_ai/zyk/lms/vendors/core/anthropic_api.py,sha256=AdlKHK4jiOxb3QxS7my7EfmGCuugPljvGNN3JBkiDfQ,13689
33
- synth_ai/zyk/lms/vendors/core/gemini_api.py,sha256=f7MBvrwNr-vsFgKfV3iL-8DmTWOW9kV2ZuiXfucXuXA,11167
33
+ synth_ai/zyk/lms/vendors/core/gemini_api.py,sha256=rKuTT5qtEvxKWBssSv05tWFw2OEzI68DavZEJJxZsM8,11240
34
34
  synth_ai/zyk/lms/vendors/core/mistral_api.py,sha256=eoEaxiMuKQEY0K4rGHA2_ZG6sBnzEm-8hBWO_JqW96M,12080
35
35
  synth_ai/zyk/lms/vendors/core/openai_api.py,sha256=O5KbRpy0pDDofVjxgZdeU69ueUl6S1DAuKykcH3gThg,6784
36
36
  synth_ai/zyk/lms/vendors/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -38,12 +38,13 @@ synth_ai/zyk/lms/vendors/local/ollama.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
38
38
  synth_ai/zyk/lms/vendors/supported/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  synth_ai/zyk/lms/vendors/supported/custom_endpoint.py,sha256=awluDoUgcRROsZdH_o_Whe2D0MjQfOZOnmgWbESAbIQ,15523
40
40
  synth_ai/zyk/lms/vendors/supported/deepseek.py,sha256=BElW0NGpkSA62wOqzzMtDw8XR36rSNXK5LldeHJkQrc,2430
41
+ synth_ai/zyk/lms/vendors/supported/grok.py,sha256=k-Pg8mU8W1Nk8Dj91lHN8G7qR5BoAZMUNY7iaYa77Ac,2313
41
42
  synth_ai/zyk/lms/vendors/supported/groq.py,sha256=Fbi7QvhdLx0F-VHO5PY-uIQlPR0bo3C9h1MvIOx8nz0,388
42
43
  synth_ai/zyk/lms/vendors/supported/ollama.py,sha256=K30VBFRTd7NYyPmyBVRZS2sm0UB651AHp9i3wd55W64,469
43
44
  synth_ai/zyk/lms/vendors/supported/openrouter.py,sha256=QdpqZFVCap-0oPsKiJkWr7o-dGaX3IMPSGehS2jw1IM,2607
44
45
  synth_ai/zyk/lms/vendors/supported/together.py,sha256=Ni_jBqqGPN0PkkY-Ew64s3gNKk51k3FCpLSwlNhKbf0,342
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,,
46
+ synth_ai-0.2.0.dist-info/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
47
+ synth_ai-0.2.0.dist-info/METADATA,sha256=lhX_6xn7Gs2pNurcrgVEaqHXJzIPm5A6iNrZxtEyGNs,1062
48
+ synth_ai-0.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
49
+ synth_ai-0.2.0.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
50
+ synth_ai-0.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5