synth-ai 0.2.6.dev1__py3-none-any.whl → 0.2.6.dev3__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.

Potentially problematic release.


This version of synth-ai might be problematic. Click here for more details.

@@ -0,0 +1,104 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ from dataclasses import dataclass
5
+ from typing import Any, Dict, Optional
6
+
7
+ import aiohttp
8
+
9
+
10
+ @dataclass
11
+ class HTTPError(Exception):
12
+ status: int
13
+ url: str
14
+ message: str
15
+ body_snippet: str | None = None
16
+ detail: Any | None = None
17
+
18
+ def __str__(self) -> str: # pragma: no cover - trivial
19
+ base = f"HTTP {self.status} for {self.url}: {self.message}"
20
+ if self.body_snippet:
21
+ base += f" | body[0:200]={self.body_snippet[:200]}"
22
+ return base
23
+
24
+
25
+ class AsyncHttpClient:
26
+ def __init__(self, base_url: str, api_key: str, timeout: float = 30.0) -> None:
27
+ self._base_url = base_url.rstrip("/")
28
+ self._api_key = api_key
29
+ self._timeout = aiohttp.ClientTimeout(total=timeout)
30
+ self._session: Optional[aiohttp.ClientSession] = None
31
+
32
+ async def __aenter__(self) -> "AsyncHttpClient":
33
+ if self._session is None:
34
+ headers = {"authorization": f"Bearer {self._api_key}"}
35
+ self._session = aiohttp.ClientSession(headers=headers, timeout=self._timeout)
36
+ return self
37
+
38
+ async def __aexit__(self, exc_type, exc, tb) -> None: # noqa: ANN001
39
+ if self._session is not None:
40
+ await self._session.close()
41
+ self._session = None
42
+
43
+ def _abs(self, path: str) -> str:
44
+ if path.startswith("http://") or path.startswith("https://"):
45
+ return path
46
+ # If base_url already ends with /api and path starts with /api, remove duplicate
47
+ if self._base_url.endswith("/api") and path.startswith("/api"):
48
+ path = path[4:] # Remove leading /api
49
+ return f"{self._base_url}/{path.lstrip('/')}"
50
+
51
+ async def get(self, path: str, *, params: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None) -> Any:
52
+ url = self._abs(path)
53
+ assert self._session is not None, "AsyncHttpClient must be used as an async context manager"
54
+ async with self._session.get(url, params=params, headers=headers) as resp:
55
+ return await self._handle_response(resp, url)
56
+
57
+ async def post_json(self, path: str, *, json: Dict[str, Any], headers: Optional[Dict[str, str]] = None) -> Any:
58
+ url = self._abs(path)
59
+ assert self._session is not None, "AsyncHttpClient must be used as an async context manager"
60
+ async with self._session.post(url, json=json, headers=headers) as resp:
61
+ return await self._handle_response(resp, url)
62
+
63
+ async def post_multipart(self, path: str, *, data: Dict[str, Any], files: Dict[str, tuple[str, bytes, str | None]], headers: Optional[Dict[str, str]] = None) -> Any:
64
+ url = self._abs(path)
65
+ assert self._session is not None, "AsyncHttpClient must be used as an async context manager"
66
+ form = aiohttp.FormData()
67
+ for k, v in data.items():
68
+ form.add_field(k, str(v))
69
+ for field, (filename, content, content_type) in files.items():
70
+ form.add_field(field, content, filename=filename, content_type=content_type or "application/octet-stream")
71
+ async with self._session.post(url, data=form, headers=headers) as resp:
72
+ return await self._handle_response(resp, url)
73
+
74
+ async def delete(self, path: str, *, headers: Optional[Dict[str, str]] = None) -> Any:
75
+ url = self._abs(path)
76
+ assert self._session is not None, "AsyncHttpClient must be used as an async context manager"
77
+ async with self._session.delete(url, headers=headers) as resp:
78
+ return await self._handle_response(resp, url)
79
+
80
+ async def _handle_response(self, resp: aiohttp.ClientResponse, url: str) -> Any:
81
+ text = await resp.text()
82
+ body_snippet = text[:200] if text else None
83
+ if 200 <= resp.status < 300:
84
+ ctype = resp.headers.get("content-type", "")
85
+ if "application/json" in ctype:
86
+ try:
87
+ return await resp.json()
88
+ except Exception:
89
+ # Fallback to text
90
+ return text
91
+ return text
92
+ # error
93
+ detail: Any | None = None
94
+ try:
95
+ detail = await resp.json()
96
+ except Exception:
97
+ detail = None
98
+ raise HTTPError(status=resp.status, url=url, message="request_failed", body_snippet=body_snippet, detail=detail)
99
+
100
+
101
+ async def sleep(seconds: float) -> None:
102
+ await asyncio.sleep(seconds)
103
+
104
+
@@ -29,7 +29,7 @@ QWEN3_MODELS: List[str] = [
29
29
  "Qwen/Qwen3-32B",
30
30
 
31
31
  # Qwen3 specialized variants
32
- "Qwen/Qwen3-4B-Instruct-2507",
32
+ "Qwen/Qwen3-4B-2507",
33
33
  "Qwen/Qwen3-4B-Thinking-2507",
34
34
  ]
35
35
 
@@ -38,7 +38,7 @@ QWEN3_MODELS: List[str] = [
38
38
  FINE_TUNED_MODELS: List[str] = [
39
39
  # Add specific fine-tuned models that are known to work with Synth
40
40
  # Examples:
41
- # "ft:Qwen/Qwen3-4B-Instruct-2507:ftjob-22",
41
+ # "ft:Qwen/Qwen3-4B-2507:ftjob-22",
42
42
  ]
43
43
 
44
44
  # Combine all Synth-supported models
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synth-ai
3
- Version: 0.2.6.dev1
3
+ Version: 0.2.6.dev3
4
4
  Summary: RL as a service SDK - Core AI functionality and tracing
5
5
  Author-email: Synth AI <josh@usesynth.ai>
6
6
  License-Expression: MIT
@@ -1,6 +1,7 @@
1
1
  synth_ai/__init__.py,sha256=1mIN_hDsscPcKTV1ciH5N12pONnczGV-RmR8EqroksI,1341
2
2
  synth_ai/__main__.py,sha256=Kh1xBKkTE5Vs2qNMtDuuOXerHUptMcOiF3YziOpC6DA,146
3
- synth_ai/http.py,sha256=aKIGsGwMBi7S0Tg57Q1Nxdoxjh2sn9xzNziLYhfSA3c,4427
3
+ synth_ai/http.py,sha256=lqjFXDmAP_xgfywK_rDSOVxuMy4rDH9S3Rtu9k1tLmk,1028
4
+ synth_ai/http_client.py,sha256=_9J8rUGoItUMnJLGZw7r0uXiJeLWR939kByRkvtP1XM,4429
4
5
  synth_ai/install_sqld.sh,sha256=AMBhlfq661PxeTTc6D4K_Nei_qwMvA84ei4NhQzmUUk,928
5
6
  synth_ai/cli/__init__.py,sha256=ThBK5FykxAqX8Mz0E4gj94_PX9EwMEtXcmm-A8krv7E,1559
6
7
  synth_ai/cli/balance.py,sha256=dlxGKCZ2kDeuHMZ5m8n5SHRWW-2CIWs3JcY5xpnWRVA,7798
@@ -9,7 +10,7 @@ synth_ai/cli/demo.py,sha256=GNVBxVtscxfAITFObyTOK8XPP2WGb-pv9LL4CiV_g6Q,4843
9
10
  synth_ai/cli/legacy_root_backup.py,sha256=KSMADyJ2g5OVpsq_CeBzqIeDC2Um-9GyINzsJH-75uw,15872
10
11
  synth_ai/cli/man.py,sha256=JQDon73ZkuKP9xr1_vRh5fjV9_b5xiUb7zNjny7ArB8,3765
11
12
  synth_ai/cli/recent.py,sha256=mHhM-QrR_MfjfKSzBvvPUEC-lkXTWUZrQwqYTmb2x0Y,4173
12
- synth_ai/cli/rl_demo.py,sha256=78GRff4kwi2RImwI5KjSMGXIfgoKR3Ckfc_EU0GZI8k,5349
13
+ synth_ai/cli/rl_demo.py,sha256=thFzIlOIXqJ_kFwaek0JMjaCH_Jq5Lpp2nOZ3A3t-3k,5980
13
14
  synth_ai/cli/root.py,sha256=YAr7H2WYfnRt6_yxLix9O01-UnSy7OtYBVyNy4l5xIo,9614
14
15
  synth_ai/cli/status.py,sha256=M_bt7U58Ubi-q-ZlrIpgCASKq9_k6uMjpx926f6kLLA,4591
15
16
  synth_ai/cli/traces.py,sha256=_QBdCR92u0Gv51U4DH0Ws1d5yCrbJRpaYKe7pmcHrHs,6484
@@ -19,14 +20,16 @@ synth_ai/config/base_url.py,sha256=Bk7Bd9jKJP-LF0SW--WE01JhMfvOB6NUkFMRgPMnJuQ,3
19
20
  synth_ai/core/experiment.py,sha256=hLkPtzUFA7iY3-QpeJ5K8YjvQeyfqnjab5P2CFaojys,236
20
21
  synth_ai/core/system.py,sha256=s-Z7np2ISYmYc1r9YN-y2yb3cgRlOalrh0iaqnxeo84,206
21
22
  synth_ai/demos/core/__init__.py,sha256=A2FjhY7KXGtyzdQXqeTPCkEhHfrH-eQg6bvP8HaYhZM,36
22
- synth_ai/demos/core/cli.py,sha256=MAZ_gFdJriYPp0v8jiNGHM13Pl4OkI4Ue5CVYYMz3Q8,28795
23
+ synth_ai/demos/core/cli.py,sha256=Q7vgPuDRSb2V_TWsiBtzEIn8ujr3awDu3X02wBRovYk,46052
23
24
  synth_ai/demos/demo_task_apps/__init__.py,sha256=8aUGEGpWUw11GRb3wQXRAmQ99yjAt5qd5FCTDJpXWjI,44
24
25
  synth_ai/demos/demo_task_apps/core.py,sha256=3-C2dGdaqVqrVjnsxU2n6kGcuaprwuszBcTHePBypwo,13580
25
26
  synth_ai/demos/demo_task_apps/math/__init__.py,sha256=WBzpZwSn7pRarBmhopQi34i9bEm05-71eM3siboOavY,43
27
+ synth_ai/demos/demo_task_apps/math/_common.py,sha256=SgtVW1pne4pgwGS2gYYQWkmG9BvU2sQTYzlncmUJ0NM,533
26
28
  synth_ai/demos/demo_task_apps/math/app.py,sha256=gNopoAhwM0vzdKuCa7AwQqSwiV2xagrjMxMH9YIniv4,1160
27
29
  synth_ai/demos/demo_task_apps/math/config.toml,sha256=atyeLq8tJsm4BST2NwlKUMum5D_gxEAWBqYsQGLQimI,757
28
30
  synth_ai/demos/demo_task_apps/math/deploy_modal.py,sha256=O4745sFuGEZTsygl-mz6ZOFJ7mog8CquXMgMyjFKr_c,2288
29
31
  synth_ai/demos/demo_task_apps/math/deploy_task_app.sh,sha256=qVffbAmsiCAxzFDzcxNVF4f7yyLWnmqPc1cNydHT5BQ,791
32
+ synth_ai/demos/demo_task_apps/math/modal_task_app.py,sha256=DcjhzNj6hwaY4Me-kJPiGKPoVED9eW4dHoaPeMD4vzQ,18808
30
33
  synth_ai/environments/__init__.py,sha256=BQW0Nc_BFQq_N-pcqTyJVjW56kSEXu7XZyaSer-U95Q,1032
31
34
  synth_ai/environments/environment/__init__.py,sha256=EBol9AKxPTIPXWcbH9Tja-l3yL-N2kB8e5atyf6F66c,31
32
35
  synth_ai/environments/environment/core.py,sha256=0jd0CZ88_s_qqA3d1lOgVsnv-ucw_1lJDAIUj1gTSt0,2201
@@ -67,7 +70,7 @@ synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluat
67
70
  synth_ai/environments/examples/crafter_classic/agent_demos/example_v3_usage.py,sha256=V0S6U_D9b-VVYkrCblylv3usA4ouV9YL3blki6vc1fs,6916
68
71
  synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/crafter_synth_config.toml,sha256=xUAL54kT5ThnZPmMQI0eGWXoVe8Gn1_imnB0-DMOlo4,1104
69
72
  synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_config_modal.toml,sha256=Hws5eQUBSG00w825BgBgQDrUeuOq2KXwUsnDrkOC-2g,748
70
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py,sha256=TECpDH6a33Wk6ThsBpWSWsnl952OSxUFZmGvrU_rprg,27192
73
+ synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py,sha256=n3UAq9LvZHpTZ7RlC0it3bPOZfOuUojHbP4abe6T9HQ,27753
71
74
  synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/kick_off_ft_modal.py,sha256=6NXSzpAXsKw3-NdKvZXCtXFA-9tZFHOlN2QVksygHFY,15284
72
75
  synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_action_results.py,sha256=6n2xKD8VBFn5EKrtFNYQgR9nSxfK6jcpavrGnUgi4Eo,1550
73
76
  synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_agent_actions.py,sha256=eUoPNPE2hMUhDTOkYJyLWeJCOrpQfEc5GtcgedUczKk,6302
@@ -235,7 +238,7 @@ synth_ai/environments/examples/wordle/helpers/generate_instances_wordfreq.py,sha
235
238
  synth_ai/environments/reproducibility/core.py,sha256=jDhG1EARROJH7-Y7eKuMYdjbi4-t1QUbxddHbbG1Dxc,1499
236
239
  synth_ai/environments/reproducibility/helpers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
237
240
  synth_ai/environments/reproducibility/tree.py,sha256=LMVTrKpPkBDjkZOfA5ptl3_n8JPc9GCnP49itPKL8zc,13703
238
- synth_ai/environments/service/app.py,sha256=qVKqZcR9TE-3HXaQgMnYVVZKMmfP2iU5EmCkQZ32BLs,3266
241
+ synth_ai/environments/service/app.py,sha256=uwLT3R9N7eYmIKiJFGroaUkCQj3hm88QKNAMETRu3Tk,3559
239
242
  synth_ai/environments/service/core_routes.py,sha256=D3KMH6eIWxbcW0F8jIgdfYe7PF8Nb7kmKz1a9z0GwR8,38412
240
243
  synth_ai/environments/service/external_registry.py,sha256=3PiWCsZr0PburC6K-IBjO9uHGVa-qnT0JHTFyyN4sZE,1765
241
244
  synth_ai/environments/service/registry.py,sha256=R4bvjdEW1GtYJdZL4Vl9ogNCQc0iGCxmjs-NuzCo5f4,405
@@ -299,7 +302,7 @@ synth_ai/lm/core/all.py,sha256=sRSuXgdXMrG46DbL7LeBA2g9PcnNgMKV0RhLkWecR1o,1765
299
302
  synth_ai/lm/core/exceptions.py,sha256=YZ3dgwb--ZyLoa4gI9uDGkuWoGfh-TS4yFanSwQd-CM,98
300
303
  synth_ai/lm/core/main.py,sha256=V1b-v8aySJwcilS_uziHyIVF-RUpOj8QK2_F828pHJ8,12801
301
304
  synth_ai/lm/core/main_v3.py,sha256=TJQHZ0kg7B1jM6deZSF21gVM-u-X-zkr-Zs4GiGfxTw,24602
302
- synth_ai/lm/core/synth_models.py,sha256=XEogTWiXbpyeznb0Px_WAkRUmKlT2WIS4nFrtnEm6-c,1646
305
+ synth_ai/lm/core/synth_models.py,sha256=Zo5Roj7HmJC4E3kOaZju5LhiExKRV05WB2-KqMxJRY4,1628
303
306
  synth_ai/lm/core/vendor_clients.py,sha256=yDJ4KxIP4sdxIaUkXJqF4G4_VS-47YA_OBQscj9v0B0,6890
304
307
  synth_ai/lm/cost/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
305
308
  synth_ai/lm/cost/monitor.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
@@ -408,9 +411,9 @@ synth_ai/v0/tracing_v1/events/manage.py,sha256=ZDXXP-ZwLH9LCsmw7Ru9o55d7bl_diPtJ
408
411
  synth_ai/v0/tracing_v1/events/scope.py,sha256=BuBkhSpVHUJt8iGT9HJZF82rbb88mQcd2vM2shg-w2I,2550
409
412
  synth_ai/v0/tracing_v1/events/store.py,sha256=0342lvAcalyJbVEIzQFaPuMQGgwiFm7M5rE6gr-G0E8,9041
410
413
  synth_ai/zyk/__init__.py,sha256=htVLnzTYQ5rxzYpzSYBm7_o6uNKZ3pB_PrqkBrgTRS4,771
411
- synth_ai-0.2.6.dev1.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
412
- synth_ai-0.2.6.dev1.dist-info/METADATA,sha256=1tLa4AfGbb3RBUBWAZ7f8x36dqeZuAGumXp-dQnMZEo,3980
413
- synth_ai-0.2.6.dev1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
414
- synth_ai-0.2.6.dev1.dist-info/entry_points.txt,sha256=Neq-3bT7TAijjgOIR77pKL-WYg6TWBDeO8pp_nL4vGY,91
415
- synth_ai-0.2.6.dev1.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
416
- synth_ai-0.2.6.dev1.dist-info/RECORD,,
414
+ synth_ai-0.2.6.dev3.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
415
+ synth_ai-0.2.6.dev3.dist-info/METADATA,sha256=oXQEoe8kmLWZ79-GLOG9uJCc38TMoquqHTwyihkd-W0,3980
416
+ synth_ai-0.2.6.dev3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
417
+ synth_ai-0.2.6.dev3.dist-info/entry_points.txt,sha256=Neq-3bT7TAijjgOIR77pKL-WYg6TWBDeO8pp_nL4vGY,91
418
+ synth_ai-0.2.6.dev3.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
419
+ synth_ai-0.2.6.dev3.dist-info/RECORD,,