synth-ai 0.1.0.dev39__py3-none-any.whl → 0.1.0.dev49__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 +3 -1
- {synth_ai-0.1.0.dev39.dist-info → synth_ai-0.1.0.dev49.dist-info}/METADATA +12 -11
- synth_ai-0.1.0.dev49.dist-info/RECORD +6 -0
- {synth_ai-0.1.0.dev39.dist-info → synth_ai-0.1.0.dev49.dist-info}/WHEEL +1 -1
- synth_ai-0.1.0.dev49.dist-info/top_level.txt +1 -0
- private_tests/try_synth_sdk.py +0 -1
- public_tests/test_agent.py +0 -538
- public_tests/test_all_structured_outputs.py +0 -196
- public_tests/test_anthropic_structured_outputs.py +0 -0
- public_tests/test_deepseek_structured_outputs.py +0 -0
- public_tests/test_deepseek_tools.py +0 -64
- public_tests/test_gemini_output.py +0 -188
- public_tests/test_gemini_structured_outputs.py +0 -106
- public_tests/test_models.py +0 -183
- public_tests/test_openai_structured_outputs.py +0 -106
- public_tests/test_reasoning_effort.py +0 -75
- public_tests/test_reasoning_models.py +0 -92
- public_tests/test_recursive_structured_outputs.py +0 -180
- public_tests/test_structured.py +0 -137
- public_tests/test_structured_outputs.py +0 -109
- public_tests/test_synth_sdk.py +0 -384
- public_tests/test_text.py +0 -160
- public_tests/test_tools.py +0 -319
- synth_ai/zyk/__init__.py +0 -3
- synth_ai/zyk/lms/__init__.py +0 -0
- synth_ai/zyk/lms/caching/__init__.py +0 -0
- synth_ai/zyk/lms/caching/constants.py +0 -1
- synth_ai/zyk/lms/caching/dbs.py +0 -0
- synth_ai/zyk/lms/caching/ephemeral.py +0 -72
- synth_ai/zyk/lms/caching/handler.py +0 -142
- synth_ai/zyk/lms/caching/initialize.py +0 -13
- synth_ai/zyk/lms/caching/persistent.py +0 -83
- synth_ai/zyk/lms/config.py +0 -8
- synth_ai/zyk/lms/core/__init__.py +0 -0
- synth_ai/zyk/lms/core/all.py +0 -47
- synth_ai/zyk/lms/core/exceptions.py +0 -9
- synth_ai/zyk/lms/core/main.py +0 -314
- synth_ai/zyk/lms/core/vendor_clients.py +0 -85
- synth_ai/zyk/lms/cost/__init__.py +0 -0
- synth_ai/zyk/lms/cost/monitor.py +0 -1
- synth_ai/zyk/lms/cost/statefulness.py +0 -1
- synth_ai/zyk/lms/structured_outputs/__init__.py +0 -0
- synth_ai/zyk/lms/structured_outputs/handler.py +0 -442
- synth_ai/zyk/lms/structured_outputs/inject.py +0 -314
- synth_ai/zyk/lms/structured_outputs/rehabilitate.py +0 -187
- synth_ai/zyk/lms/tools/base.py +0 -104
- synth_ai/zyk/lms/vendors/__init__.py +0 -0
- synth_ai/zyk/lms/vendors/base.py +0 -31
- synth_ai/zyk/lms/vendors/constants.py +0 -22
- synth_ai/zyk/lms/vendors/core/__init__.py +0 -0
- synth_ai/zyk/lms/vendors/core/anthropic_api.py +0 -413
- synth_ai/zyk/lms/vendors/core/gemini_api.py +0 -306
- synth_ai/zyk/lms/vendors/core/mistral_api.py +0 -327
- synth_ai/zyk/lms/vendors/core/openai_api.py +0 -185
- synth_ai/zyk/lms/vendors/local/__init__.py +0 -0
- synth_ai/zyk/lms/vendors/local/ollama.py +0 -0
- synth_ai/zyk/lms/vendors/openai_standard.py +0 -374
- synth_ai/zyk/lms/vendors/retries.py +0 -3
- synth_ai/zyk/lms/vendors/supported/__init__.py +0 -0
- synth_ai/zyk/lms/vendors/supported/deepseek.py +0 -73
- synth_ai/zyk/lms/vendors/supported/groq.py +0 -16
- synth_ai/zyk/lms/vendors/supported/ollama.py +0 -14
- synth_ai/zyk/lms/vendors/supported/together.py +0 -11
- synth_ai-0.1.0.dev39.dist-info/RECORD +0 -67
- synth_ai-0.1.0.dev39.dist-info/top_level.txt +0 -4
- tests/test_agent.py +0 -538
- tests/test_recursive_structured_outputs.py +0 -180
- tests/test_structured_outputs.py +0 -100
- {synth_ai-0.1.0.dev39.dist-info → synth_ai-0.1.0.dev49.dist-info}/licenses/LICENSE +0 -0
@@ -1,185 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
from typing import Any, Dict, List, Optional, Tuple, Type
|
3
|
-
|
4
|
-
import openai
|
5
|
-
import pydantic_core
|
6
|
-
|
7
|
-
# from openai import AsyncOpenAI, OpenAI
|
8
|
-
from pydantic import BaseModel
|
9
|
-
|
10
|
-
from synth_ai.zyk.lms.caching.initialize import get_cache_handler
|
11
|
-
from synth_ai.zyk.lms.tools.base import BaseTool
|
12
|
-
from synth_ai.zyk.lms.vendors.base import BaseLMResponse
|
13
|
-
from synth_ai.zyk.lms.vendors.constants import SPECIAL_BASE_TEMPS, openai_reasoners
|
14
|
-
from synth_ai.zyk.lms.vendors.openai_standard import OpenAIStandard
|
15
|
-
|
16
|
-
OPENAI_EXCEPTIONS_TO_RETRY: Tuple[Type[Exception], ...] = (
|
17
|
-
pydantic_core._pydantic_core.ValidationError,
|
18
|
-
openai.OpenAIError,
|
19
|
-
openai.APIConnectionError,
|
20
|
-
openai.RateLimitError,
|
21
|
-
openai.APIError,
|
22
|
-
openai.Timeout,
|
23
|
-
openai.InternalServerError,
|
24
|
-
openai.APIConnectionError,
|
25
|
-
)
|
26
|
-
|
27
|
-
|
28
|
-
class OpenAIStructuredOutputClient(OpenAIStandard):
|
29
|
-
def __init__(self, synth_logging: bool = True):
|
30
|
-
if synth_logging:
|
31
|
-
# print("Using synth logging - OpenAIStructuredOutputClient")
|
32
|
-
from synth_sdk import AsyncOpenAI, OpenAI
|
33
|
-
else:
|
34
|
-
# print("Not using synth logging - OpenAIStructuredOutputClient")
|
35
|
-
from openai import AsyncOpenAI, OpenAI
|
36
|
-
|
37
|
-
super().__init__(
|
38
|
-
used_for_structured_outputs=True,
|
39
|
-
exceptions_to_retry=OPENAI_EXCEPTIONS_TO_RETRY,
|
40
|
-
sync_client=OpenAI(),
|
41
|
-
async_client=AsyncOpenAI(),
|
42
|
-
)
|
43
|
-
|
44
|
-
async def _hit_api_async_structured_output(
|
45
|
-
self,
|
46
|
-
model: str,
|
47
|
-
messages: List[Dict[str, Any]],
|
48
|
-
response_model: BaseModel,
|
49
|
-
temperature: float,
|
50
|
-
use_ephemeral_cache_only: bool = False,
|
51
|
-
tools: Optional[List[BaseTool]] = None,
|
52
|
-
reasoning_effort: str = "high",
|
53
|
-
) -> str:
|
54
|
-
if tools:
|
55
|
-
raise ValueError("Tools are not supported for async structured output")
|
56
|
-
# "Hit client")
|
57
|
-
lm_config = {"temperature": temperature, "response_model": response_model}
|
58
|
-
used_cache_handler = get_cache_handler(
|
59
|
-
use_ephemeral_cache_only=use_ephemeral_cache_only
|
60
|
-
)
|
61
|
-
cache_result = used_cache_handler.hit_managed_cache(
|
62
|
-
model, messages, lm_config=lm_config
|
63
|
-
)
|
64
|
-
if cache_result:
|
65
|
-
# print("Hit cache")
|
66
|
-
assert type(cache_result) in [
|
67
|
-
dict,
|
68
|
-
BaseLMResponse,
|
69
|
-
], f"Expected dict or BaseLMResponse, got {type(cache_result)}"
|
70
|
-
return (
|
71
|
-
cache_result["response"] if type(cache_result) == dict else cache_result
|
72
|
-
)
|
73
|
-
if model in openai_reasoners:
|
74
|
-
output = await self.async_client.chat.completions.create(
|
75
|
-
model=model,
|
76
|
-
messages=messages,
|
77
|
-
temperature=temperature,
|
78
|
-
tools=tools,
|
79
|
-
max_completion_tokens=lm_config.get("max_tokens"),
|
80
|
-
)
|
81
|
-
else:
|
82
|
-
output = await self.async_client.chat.completions.create(
|
83
|
-
model=model,
|
84
|
-
messages=messages,
|
85
|
-
temperature=temperature,
|
86
|
-
max_tokens=lm_config.get("max_tokens"),
|
87
|
-
)
|
88
|
-
# "Output", output)
|
89
|
-
api_result = response_model(**json.loads(output.choices[0].message.content))
|
90
|
-
lm_response = BaseLMResponse(
|
91
|
-
raw_response="",
|
92
|
-
structured_output=api_result,
|
93
|
-
tool_calls=None,
|
94
|
-
)
|
95
|
-
used_cache_handler.add_to_managed_cache(
|
96
|
-
model, messages, lm_config, output=lm_response
|
97
|
-
)
|
98
|
-
return lm_response
|
99
|
-
|
100
|
-
def _hit_api_sync_structured_output(
|
101
|
-
self,
|
102
|
-
model: str,
|
103
|
-
messages: List[Dict[str, Any]],
|
104
|
-
response_model: BaseModel,
|
105
|
-
temperature: float,
|
106
|
-
use_ephemeral_cache_only: bool = False,
|
107
|
-
tools: Optional[List[BaseTool]] = None,
|
108
|
-
reasoning_effort: str = "high",
|
109
|
-
) -> str:
|
110
|
-
if tools:
|
111
|
-
raise ValueError("Tools are not supported for sync structured output")
|
112
|
-
lm_config = {"temperature": temperature, "response_model": response_model}
|
113
|
-
used_cache_handler = get_cache_handler(
|
114
|
-
use_ephemeral_cache_only=use_ephemeral_cache_only
|
115
|
-
)
|
116
|
-
cache_result = used_cache_handler.hit_managed_cache(
|
117
|
-
model, messages, lm_config=lm_config
|
118
|
-
)
|
119
|
-
if cache_result:
|
120
|
-
assert type(cache_result) in [
|
121
|
-
dict,
|
122
|
-
BaseLMResponse,
|
123
|
-
], f"Expected dict or BaseLMResponse, got {type(cache_result)}"
|
124
|
-
return (
|
125
|
-
cache_result["response"] if type(cache_result) == dict else cache_result
|
126
|
-
)
|
127
|
-
if model in ["o3-mini", "o3", "o1-mini", "o1"]:
|
128
|
-
output = self.sync_client.chat.completions.create(
|
129
|
-
model=model,
|
130
|
-
messages=messages,
|
131
|
-
temperature=temperature,
|
132
|
-
tools=tools,
|
133
|
-
max_tokens=lm_config.get("max_tokens"),
|
134
|
-
)
|
135
|
-
else:
|
136
|
-
output = self.sync_client.chat.completions.create(
|
137
|
-
model=model,
|
138
|
-
messages=messages,
|
139
|
-
temperature=temperature,
|
140
|
-
max_tokens=lm_config.get("max_tokens"),
|
141
|
-
)
|
142
|
-
api_result = response_model(**json.loads(output.choices[0].message.content))
|
143
|
-
|
144
|
-
lm_response = BaseLMResponse(
|
145
|
-
raw_response="",
|
146
|
-
structured_output=api_result,
|
147
|
-
tool_calls=None,
|
148
|
-
)
|
149
|
-
used_cache_handler.add_to_managed_cache(
|
150
|
-
model, messages, lm_config=lm_config, output=lm_response
|
151
|
-
)
|
152
|
-
return lm_response
|
153
|
-
|
154
|
-
|
155
|
-
class OpenAIPrivate(OpenAIStandard):
|
156
|
-
def __init__(self, synth_logging: bool = True):
|
157
|
-
if synth_logging:
|
158
|
-
# print("Using synth logging - OpenAIPrivate")
|
159
|
-
from synth_sdk import AsyncOpenAI, OpenAI
|
160
|
-
else:
|
161
|
-
# print("Not using synth logging - OpenAIPrivate")
|
162
|
-
from openai import AsyncOpenAI, OpenAI
|
163
|
-
|
164
|
-
self.sync_client = OpenAI()
|
165
|
-
self.async_client = AsyncOpenAI()
|
166
|
-
|
167
|
-
|
168
|
-
if __name__ == "__main__":
|
169
|
-
client = OpenAIStructuredOutputClient(
|
170
|
-
sync_client=openai.OpenAI(),
|
171
|
-
async_client=openai.AsyncOpenAI(),
|
172
|
-
used_for_structured_outputs=True,
|
173
|
-
exceptions_to_retry=[],
|
174
|
-
)
|
175
|
-
|
176
|
-
class TestModel(BaseModel):
|
177
|
-
name: str
|
178
|
-
|
179
|
-
sync_model_response = client._hit_api_sync_structured_output(
|
180
|
-
model="gpt-4o-mini-2024-07-18",
|
181
|
-
messages=[{"role": "user", "content": " What is the capital of the moon?"}],
|
182
|
-
response_model=TestModel,
|
183
|
-
temperature=0.0,
|
184
|
-
)
|
185
|
-
# print(sync_model_response)
|
File without changes
|
File without changes
|
@@ -1,374 +0,0 @@
|
|
1
|
-
from typing import Any, Dict, List, Optional, Union
|
2
|
-
|
3
|
-
import groq
|
4
|
-
import openai
|
5
|
-
import pydantic_core
|
6
|
-
from pydantic import BaseModel
|
7
|
-
|
8
|
-
from synth_ai.zyk.lms.caching.initialize import (
|
9
|
-
get_cache_handler,
|
10
|
-
)
|
11
|
-
from synth_ai.zyk.lms.tools.base import BaseTool
|
12
|
-
from synth_ai.zyk.lms.vendors.base import BaseLMResponse, VendorBase
|
13
|
-
from synth_ai.zyk.lms.vendors.constants import SPECIAL_BASE_TEMPS, openai_reasoners
|
14
|
-
|
15
|
-
DEFAULT_EXCEPTIONS_TO_RETRY = (
|
16
|
-
pydantic_core._pydantic_core.ValidationError,
|
17
|
-
openai.APIConnectionError,
|
18
|
-
openai.APITimeoutError,
|
19
|
-
groq.InternalServerError,
|
20
|
-
groq.APITimeoutError,
|
21
|
-
groq.APIConnectionError,
|
22
|
-
)
|
23
|
-
|
24
|
-
|
25
|
-
def special_orion_transform(
|
26
|
-
model: str, messages: List[Dict[str, Any]]
|
27
|
-
) -> List[Dict[str, Any]]:
|
28
|
-
if "o1-" in model:
|
29
|
-
messages = [
|
30
|
-
{
|
31
|
-
"role": "user",
|
32
|
-
"content": f"<instructions>{messages[0]['content']}</instructions><information>{messages[1]}</information>",
|
33
|
-
}
|
34
|
-
]
|
35
|
-
return messages
|
36
|
-
|
37
|
-
|
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})")
|
48
|
-
|
49
|
-
|
50
|
-
class OpenAIStandard(VendorBase):
|
51
|
-
used_for_structured_outputs: bool = True
|
52
|
-
exceptions_to_retry: List = DEFAULT_EXCEPTIONS_TO_RETRY
|
53
|
-
sync_client: Any
|
54
|
-
async_client: Any
|
55
|
-
|
56
|
-
def __init__(
|
57
|
-
self,
|
58
|
-
sync_client: Any,
|
59
|
-
async_client: Any,
|
60
|
-
exceptions_to_retry: List[Exception] = DEFAULT_EXCEPTIONS_TO_RETRY,
|
61
|
-
used_for_structured_outputs: bool = False,
|
62
|
-
):
|
63
|
-
self.sync_client = sync_client
|
64
|
-
self.async_client = async_client
|
65
|
-
self.used_for_structured_outputs = used_for_structured_outputs
|
66
|
-
self.exceptions_to_retry = exceptions_to_retry
|
67
|
-
|
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
|
-
# )
|
75
|
-
async def _hit_api_async(
|
76
|
-
self,
|
77
|
-
model: str,
|
78
|
-
messages: List[Dict[str, Any]],
|
79
|
-
lm_config: Dict[str, Any],
|
80
|
-
use_ephemeral_cache_only: bool = False,
|
81
|
-
reasoning_effort: str = "high",
|
82
|
-
tools: Optional[List[BaseTool]] = None,
|
83
|
-
) -> BaseLMResponse:
|
84
|
-
assert (
|
85
|
-
lm_config.get("response_model", None) is None
|
86
|
-
), "response_model is not supported for standard calls"
|
87
|
-
messages = special_orion_transform(model, messages)
|
88
|
-
used_cache_handler = get_cache_handler(use_ephemeral_cache_only)
|
89
|
-
cache_result = used_cache_handler.hit_managed_cache(
|
90
|
-
model, messages, lm_config=lm_config, tools=tools, reasoning_effort=reasoning_effort
|
91
|
-
)
|
92
|
-
if cache_result:
|
93
|
-
return cache_result
|
94
|
-
|
95
|
-
# Common API call params
|
96
|
-
api_params = {
|
97
|
-
"model": model,
|
98
|
-
"messages": messages,
|
99
|
-
}
|
100
|
-
# Add max_tokens if present in lm_config
|
101
|
-
if "max_tokens" in lm_config:
|
102
|
-
api_params["max_completion_tokens"] = lm_config["max_tokens"]
|
103
|
-
|
104
|
-
# Add tools if provided
|
105
|
-
if tools:
|
106
|
-
api_params["tools"] = []
|
107
|
-
for tool in tools:
|
108
|
-
if isinstance(tool, BaseTool):
|
109
|
-
api_params["tools"].append(tool.to_openai_tool())
|
110
|
-
else:
|
111
|
-
api_params["tools"].append(tool)
|
112
|
-
|
113
|
-
# Only add temperature for non o1/o3 models
|
114
|
-
if model not in openai_reasoners:
|
115
|
-
api_params["temperature"] = lm_config.get(
|
116
|
-
"temperature", SPECIAL_BASE_TEMPS.get(model, 0)
|
117
|
-
)
|
118
|
-
|
119
|
-
# Add reasoning_effort only for o3-mini
|
120
|
-
if model in openai_reasoners:
|
121
|
-
api_params["reasoning_effort"] = reasoning_effort
|
122
|
-
|
123
|
-
output = await self.async_client.chat.completions.create(**api_params)
|
124
|
-
message = output.choices[0].message
|
125
|
-
|
126
|
-
# Convert tool calls to dict format
|
127
|
-
tool_calls = None
|
128
|
-
if message.tool_calls:
|
129
|
-
tool_calls = [
|
130
|
-
{
|
131
|
-
"id": tc.id,
|
132
|
-
"type": tc.type,
|
133
|
-
"function": {
|
134
|
-
"name": tc.function.name,
|
135
|
-
"arguments": tc.function.arguments,
|
136
|
-
},
|
137
|
-
}
|
138
|
-
for tc in message.tool_calls
|
139
|
-
]
|
140
|
-
|
141
|
-
lm_response = BaseLMResponse(
|
142
|
-
raw_response=message.content or "", # Use empty string if no content
|
143
|
-
structured_output=None,
|
144
|
-
tool_calls=tool_calls,
|
145
|
-
)
|
146
|
-
used_cache_handler.add_to_managed_cache(
|
147
|
-
model, messages, lm_config=lm_config, output=lm_response, tools=tools, reasoning_effort=reasoning_effort
|
148
|
-
)
|
149
|
-
return lm_response
|
150
|
-
|
151
|
-
# @backoff.on_exception(
|
152
|
-
# backoff.expo,
|
153
|
-
# exceptions_to_retry,
|
154
|
-
# max_tries=BACKOFF_TOLERANCE,
|
155
|
-
# on_backoff=on_backoff_handler_sync,
|
156
|
-
# on_giveup=lambda e: print(e),
|
157
|
-
# )
|
158
|
-
def _hit_api_sync(
|
159
|
-
self,
|
160
|
-
model: str,
|
161
|
-
messages: List[Dict[str, Any]],
|
162
|
-
lm_config: Dict[str, Any],
|
163
|
-
use_ephemeral_cache_only: bool = False,
|
164
|
-
reasoning_effort: str = "high",
|
165
|
-
tools: Optional[List[BaseTool]] = None,
|
166
|
-
) -> BaseLMResponse:
|
167
|
-
assert (
|
168
|
-
lm_config.get("response_model", None) is None
|
169
|
-
), "response_model is not supported for standard calls"
|
170
|
-
messages = special_orion_transform(model, messages)
|
171
|
-
used_cache_handler = get_cache_handler(
|
172
|
-
use_ephemeral_cache_only=use_ephemeral_cache_only
|
173
|
-
)
|
174
|
-
cache_result = used_cache_handler.hit_managed_cache(
|
175
|
-
model, messages, lm_config=lm_config, tools=tools, reasoning_effort=reasoning_effort
|
176
|
-
)
|
177
|
-
if cache_result:
|
178
|
-
return cache_result
|
179
|
-
|
180
|
-
# Common API call params
|
181
|
-
api_params = {
|
182
|
-
"model": model,
|
183
|
-
"messages": messages,
|
184
|
-
}
|
185
|
-
# Add max_tokens if present in lm_config
|
186
|
-
if "max_tokens" in lm_config:
|
187
|
-
api_params["max_tokens"] = lm_config["max_tokens"]
|
188
|
-
|
189
|
-
# Add tools if provided
|
190
|
-
if tools:
|
191
|
-
api_params["tools"] = []
|
192
|
-
for tool in tools:
|
193
|
-
if isinstance(tool, BaseTool):
|
194
|
-
api_params["tools"].append(tool.to_openai_tool())
|
195
|
-
else:
|
196
|
-
api_params["tools"].append(tool)
|
197
|
-
|
198
|
-
# Only add temperature for non o1/o3 models
|
199
|
-
if model not in openai_reasoners:
|
200
|
-
api_params["temperature"] = lm_config.get(
|
201
|
-
"temperature", SPECIAL_BASE_TEMPS.get(model, 0)
|
202
|
-
)
|
203
|
-
|
204
|
-
# Add reasoning_effort only for o3-mini
|
205
|
-
if model in openai_reasoners:
|
206
|
-
api_params["reasoning_effort"] = reasoning_effort
|
207
|
-
|
208
|
-
output = self.sync_client.chat.completions.create(**api_params)
|
209
|
-
message = output.choices[0].message
|
210
|
-
|
211
|
-
# Convert tool calls to dict format
|
212
|
-
tool_calls = None
|
213
|
-
if message.tool_calls:
|
214
|
-
tool_calls = [
|
215
|
-
{
|
216
|
-
"id": tc.id,
|
217
|
-
"type": tc.type,
|
218
|
-
"function": {
|
219
|
-
"name": tc.function.name,
|
220
|
-
"arguments": tc.function.arguments,
|
221
|
-
},
|
222
|
-
}
|
223
|
-
for tc in message.tool_calls
|
224
|
-
]
|
225
|
-
|
226
|
-
lm_response = BaseLMResponse(
|
227
|
-
raw_response=message.content or "", # Use empty string if no content
|
228
|
-
structured_output=None,
|
229
|
-
tool_calls=tool_calls,
|
230
|
-
)
|
231
|
-
used_cache_handler.add_to_managed_cache(
|
232
|
-
model, messages, lm_config=lm_config, output=lm_response, tools=tools, reasoning_effort=reasoning_effort
|
233
|
-
)
|
234
|
-
return lm_response
|
235
|
-
|
236
|
-
async def _hit_api_async_structured_output(
|
237
|
-
self,
|
238
|
-
model: str,
|
239
|
-
messages: List[Dict[str, Any]],
|
240
|
-
response_model: BaseModel,
|
241
|
-
temperature: float,
|
242
|
-
use_ephemeral_cache_only: bool = False,
|
243
|
-
reasoning_effort: str = "high",
|
244
|
-
tools: Optional[List[BaseTool]] = None,
|
245
|
-
) -> BaseLMResponse:
|
246
|
-
lm_config = {"temperature": temperature, "response_model": response_model}
|
247
|
-
used_cache_handler = get_cache_handler(use_ephemeral_cache_only)
|
248
|
-
cache_result: Union[BaseLMResponse, None] = (
|
249
|
-
used_cache_handler.hit_managed_cache(
|
250
|
-
model,
|
251
|
-
messages,
|
252
|
-
lm_config=lm_config,
|
253
|
-
tools=tools,
|
254
|
-
reasoning_effort=reasoning_effort,
|
255
|
-
)
|
256
|
-
)
|
257
|
-
if cache_result is not None:
|
258
|
-
return cache_result
|
259
|
-
|
260
|
-
# Common API call params
|
261
|
-
api_params = {
|
262
|
-
"model": model,
|
263
|
-
"messages": messages,
|
264
|
-
}
|
265
|
-
|
266
|
-
# Add tools if provided
|
267
|
-
if tools:
|
268
|
-
api_params["tools"] = []
|
269
|
-
for tool in tools:
|
270
|
-
if isinstance(tool, BaseTool):
|
271
|
-
api_params["tools"].append(tool.to_openai_tool())
|
272
|
-
else:
|
273
|
-
api_params["tools"].append(tool)
|
274
|
-
|
275
|
-
# Only add temperature for non o1/o3 models
|
276
|
-
if model not in openai_reasoners:
|
277
|
-
api_params["temperature"] = lm_config.get(
|
278
|
-
"temperature", SPECIAL_BASE_TEMPS.get(model, 0)
|
279
|
-
)
|
280
|
-
|
281
|
-
# Add reasoning_effort only for o3-mini
|
282
|
-
if model in openai_reasoners:
|
283
|
-
api_params["reasoning_effort"] = reasoning_effort
|
284
|
-
|
285
|
-
output = await self.async_client.chat.completions.create(**api_params)
|
286
|
-
|
287
|
-
structured_output_api_result = response_model(
|
288
|
-
**output.choices[0].message.content
|
289
|
-
)
|
290
|
-
tool_calls = output.choices[0].message.tool_calls
|
291
|
-
lm_response = BaseLMResponse(
|
292
|
-
raw_response=output.choices[0].message.content,
|
293
|
-
structured_output=structured_output_api_result,
|
294
|
-
tool_calls=tool_calls,
|
295
|
-
)
|
296
|
-
used_cache_handler.add_to_managed_cache(
|
297
|
-
model,
|
298
|
-
messages,
|
299
|
-
lm_config=lm_config,
|
300
|
-
output=lm_response,
|
301
|
-
tools=tools,
|
302
|
-
reasoning_effort=reasoning_effort,
|
303
|
-
)
|
304
|
-
return lm_response
|
305
|
-
|
306
|
-
def _hit_api_sync_structured_output(
|
307
|
-
self,
|
308
|
-
model: str,
|
309
|
-
messages: List[Dict[str, Any]],
|
310
|
-
response_model: BaseModel,
|
311
|
-
temperature: float,
|
312
|
-
use_ephemeral_cache_only: bool = False,
|
313
|
-
reasoning_effort: str = "high",
|
314
|
-
tools: Optional[List[BaseTool]] = None,
|
315
|
-
) -> BaseLMResponse:
|
316
|
-
lm_config = {"temperature": temperature, "response_model": response_model}
|
317
|
-
used_cache_handler = get_cache_handler(use_ephemeral_cache_only)
|
318
|
-
cache_result: Union[BaseLMResponse, None] = (
|
319
|
-
used_cache_handler.hit_managed_cache(
|
320
|
-
model,
|
321
|
-
messages,
|
322
|
-
lm_config=lm_config,
|
323
|
-
tools=tools,
|
324
|
-
reasoning_effort=reasoning_effort,
|
325
|
-
)
|
326
|
-
)
|
327
|
-
if cache_result is not None:
|
328
|
-
return cache_result
|
329
|
-
|
330
|
-
# Common API call params
|
331
|
-
api_params = {
|
332
|
-
"model": model,
|
333
|
-
"messages": messages,
|
334
|
-
}
|
335
|
-
|
336
|
-
# Add tools if provided
|
337
|
-
if tools:
|
338
|
-
api_params["tools"] = []
|
339
|
-
for tool in tools:
|
340
|
-
if isinstance(tool, BaseTool):
|
341
|
-
api_params["tools"].append(tool.to_openai_tool())
|
342
|
-
else:
|
343
|
-
api_params["tools"].append(tool)
|
344
|
-
|
345
|
-
# Only add temperature for non o1/o3 models
|
346
|
-
if model not in openai_reasoners:
|
347
|
-
api_params["temperature"] = lm_config.get(
|
348
|
-
"temperature", SPECIAL_BASE_TEMPS.get(model, 0)
|
349
|
-
)
|
350
|
-
|
351
|
-
# Add reasoning_effort only for o3-mini
|
352
|
-
if model in openai_reasoners:
|
353
|
-
api_params["reasoning_effort"] = reasoning_effort
|
354
|
-
|
355
|
-
output = self.sync_client.chat.completions.create(**api_params)
|
356
|
-
|
357
|
-
structured_output_api_result = response_model(
|
358
|
-
**output.choices[0].message.content
|
359
|
-
)
|
360
|
-
tool_calls = output.choices[0].message.tool_calls
|
361
|
-
lm_response = BaseLMResponse(
|
362
|
-
raw_response=output.choices[0].message.content,
|
363
|
-
structured_output=structured_output_api_result,
|
364
|
-
tool_calls=tool_calls,
|
365
|
-
)
|
366
|
-
used_cache_handler.add_to_managed_cache(
|
367
|
-
model,
|
368
|
-
messages,
|
369
|
-
lm_config=lm_config,
|
370
|
-
output=lm_response,
|
371
|
-
tools=tools,
|
372
|
-
reasoning_effort=reasoning_effort,
|
373
|
-
)
|
374
|
-
return lm_response
|
File without changes
|
@@ -1,73 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from typing import Any, Dict, List, Optional, Tuple
|
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 DeepSeekAPI(OpenAIStandard):
|
11
|
-
def __init__(self):
|
12
|
-
# print("Setting up DeepSeek API")
|
13
|
-
self.sync_client = OpenAI(
|
14
|
-
api_key=os.environ.get("DEEPSEEK_API_KEY"),
|
15
|
-
base_url="https://api.deepseek.com",
|
16
|
-
)
|
17
|
-
self.async_client = AsyncOpenAI(
|
18
|
-
api_key=os.environ.get("DEEPSEEK_API_KEY"),
|
19
|
-
base_url="https://api.deepseek.com",
|
20
|
-
)
|
21
|
-
|
22
|
-
def _convert_tools_to_openai_format(self, tools: List[BaseTool]) -> List[Dict]:
|
23
|
-
return [tool.to_openai_tool() for tool in tools]
|
24
|
-
|
25
|
-
async def _private_request_async(
|
26
|
-
self,
|
27
|
-
messages: List[Dict],
|
28
|
-
temperature: float = 0,
|
29
|
-
model_name: str = "deepseek-chat",
|
30
|
-
reasoning_effort: str = "high",
|
31
|
-
tools: Optional[List[BaseTool]] = None,
|
32
|
-
lm_config: Optional[Dict[str, Any]] = None,
|
33
|
-
) -> Tuple[str, Optional[List[Dict]]]:
|
34
|
-
request_params = {
|
35
|
-
"model": model_name,
|
36
|
-
"messages": messages,
|
37
|
-
"temperature": temperature,
|
38
|
-
}
|
39
|
-
|
40
|
-
if tools:
|
41
|
-
request_params["tools"] = self._convert_tools_to_openai_format(tools)
|
42
|
-
|
43
|
-
response = await self.async_client.chat.completions.create(**request_params)
|
44
|
-
message = response.choices[0].message
|
45
|
-
|
46
|
-
return message.content, message.tool_calls if hasattr(
|
47
|
-
message, "tool_calls"
|
48
|
-
) else None
|
49
|
-
|
50
|
-
def _private_request_sync(
|
51
|
-
self,
|
52
|
-
messages: List[Dict],
|
53
|
-
temperature: float = 0,
|
54
|
-
model_name: str = "deepseek-chat",
|
55
|
-
reasoning_effort: str = "high",
|
56
|
-
tools: Optional[List[BaseTool]] = None,
|
57
|
-
lm_config: Optional[Dict[str, Any]] = None,
|
58
|
-
) -> Tuple[str, Optional[List[Dict]]]:
|
59
|
-
request_params = {
|
60
|
-
"model": model_name,
|
61
|
-
"messages": messages,
|
62
|
-
"temperature": temperature,
|
63
|
-
}
|
64
|
-
|
65
|
-
if tools:
|
66
|
-
request_params["tools"] = self._convert_tools_to_openai_format(tools)
|
67
|
-
|
68
|
-
response = self.sync_client.chat.completions.create(**request_params)
|
69
|
-
message = response.choices[0].message
|
70
|
-
|
71
|
-
return message.content, message.tool_calls if hasattr(
|
72
|
-
message, "tool_calls"
|
73
|
-
) else None
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
|
3
|
-
from dotenv import load_dotenv
|
4
|
-
from groq import AsyncGroq, Groq
|
5
|
-
|
6
|
-
from synth_ai.zyk.lms.vendors.openai_standard import OpenAIStandard
|
7
|
-
|
8
|
-
load_dotenv()
|
9
|
-
|
10
|
-
|
11
|
-
class GroqAPI(OpenAIStandard):
|
12
|
-
def __init__(self):
|
13
|
-
super().__init__(
|
14
|
-
sync_client=Groq(api_key=os.getenv("GROQ_API_KEY")),
|
15
|
-
async_client=AsyncGroq(api_key=os.getenv("GROQ_API_KEY")),
|
16
|
-
)
|
@@ -1,14 +0,0 @@
|
|
1
|
-
from openai import OpenAI, AsyncOpenAI
|
2
|
-
from synth_ai.zyk.lms.vendors.openai_standard import OpenAIStandard
|
3
|
-
|
4
|
-
|
5
|
-
class OllamaAPI(OpenAIStandard):
|
6
|
-
def __init__(self):
|
7
|
-
self.sync_client = OpenAI(
|
8
|
-
base_url="http://localhost:11434/v1",
|
9
|
-
api_key="ollama", # required, but unused
|
10
|
-
)
|
11
|
-
self.async_client = AsyncOpenAI(
|
12
|
-
base_url="http://localhost:11434/v1",
|
13
|
-
api_key="ollama", # required, but unused
|
14
|
-
)
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
|
3
|
-
from together import AsyncTogether, Together
|
4
|
-
|
5
|
-
from synth_ai.zyk.lms.vendors.openai_standard import OpenAIStandard
|
6
|
-
|
7
|
-
|
8
|
-
class TogetherAPI(OpenAIStandard):
|
9
|
-
def __init__(self):
|
10
|
-
self.sync_client = Together(api_key=os.getenv("TOGETHER_API_KEY"))
|
11
|
-
self.async_client = AsyncTogether(api_key=os.getenv("TOGETHER_API_KEY"))
|