synth-ai 0.2.6.dev6__py3-none-any.whl → 0.2.8.dev1__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.

@@ -294,22 +294,32 @@ def load_env() -> DemoEnv:
294
294
  env.task_app_name = task_app_name
295
295
  env.task_app_secret_name = task_app_secret_name
296
296
 
297
- print("ENV:")
298
- print(f" DEV_BACKEND_URL={env.dev_backend_url}")
299
- print(f" SYNTH_API_KEY={_mask(env.synth_api_key)}")
300
- print(f" ENVIRONMENT_API_KEY={_mask(env.env_api_key)}")
301
- print(f" TASK_APP_BASE_URL={env.task_app_base_url}")
302
- if task_app_name:
303
- print(f" TASK_APP_NAME={task_app_name}")
304
- if task_app_secret_name:
305
- print(f" TASK_APP_SECRET_NAME={task_app_secret_name}")
297
+ # Suppress environment echo by default for cleaner CLI output.
298
+ # If needed for debugging, set SYNTH_CLI_VERBOSE=1 to print resolved values.
299
+ if os.getenv("SYNTH_CLI_VERBOSE", "0") == "1":
300
+ print("ENV:")
301
+ print(f" DEV_BACKEND_URL={env.dev_backend_url}")
302
+ print(f" SYNTH_API_KEY={_mask(env.synth_api_key)}")
303
+ print(f" ENVIRONMENT_API_KEY={_mask(env.env_api_key)}")
304
+ print(f" TASK_APP_BASE_URL={env.task_app_base_url}")
305
+ if task_app_name:
306
+ print(f" TASK_APP_NAME={task_app_name}")
307
+ if task_app_secret_name:
308
+ print(f" TASK_APP_SECRET_NAME={task_app_secret_name}")
306
309
  return env
307
310
 
308
311
 
309
312
  def assert_http_ok(url: str, method: str = "GET", allow_redirects: bool = True, timeout: float = 10.0) -> bool:
310
313
  try:
314
+ import ssl
315
+
311
316
  req = urllib.request.Request(url, method=method)
312
- with urllib.request.urlopen(req, timeout=timeout) as resp: # nosec - controlled URL
317
+ # Default: disable SSL verification for local/dev convenience.
318
+ # Set SYNTH_SSL_VERIFY=1 to enable verification.
319
+ ctx = ssl._create_unverified_context() # nosec: disabled by default for dev
320
+ if os.getenv("SYNTH_SSL_VERIFY", "0") == "1":
321
+ ctx = None
322
+ with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp: # nosec - controlled URL
313
323
  code = getattr(resp, "status", 200)
314
324
  return 200 <= int(code) < 400
315
325
  except Exception:
@@ -2,43 +2,128 @@
2
2
  name = "Qwen/Qwen3-0.6B"
3
3
  dtype = "bfloat16"
4
4
  seed = 42
5
+ trainer_mode = "full"
6
+
7
+ [lora]
8
+ r = 16
9
+ alpha = 32
10
+ dropout = 0.05
11
+ target_modules = [
12
+ "q_proj", "k_proj", "v_proj", "o_proj",
13
+ "gate_proj", "up_proj", "down_proj",
14
+ ]
15
+
16
+ [rdma]
17
+ enabled = false
18
+ ifname = "eth0"
19
+ ip_type = "ipv4"
20
+ p2p_disable = 0
21
+ shm_disable = 0
22
+ fast_nccl = false
23
+
24
+ gid_index = 3
25
+ cross_nic = 0
26
+ collnet_enable = 0
27
+ net_gdr_level = 2
28
+
29
+ nsocks_perthread = 4
30
+ socket_nthreads = 2
31
+
32
+ algo = "Ring"
33
+ proto = "Simple"
34
+ p2p_level = "SYS"
35
+ debug = "INFO"
5
36
 
6
37
  [reference]
7
38
  placement = "dedicated"
39
+ gpu_index = 1
8
40
  port = 8002
41
+ tp = 1
42
+ health_max_wait_s = 180
43
+ health_interval_ms = 300
9
44
 
10
45
  [topology]
11
46
  type = "single_node_split"
12
- gpus_for_vllm = 1
47
+ gpu_type = "H100:4"
48
+ use_rdma = false
49
+ gpus_for_vllm = 2
13
50
  gpus_for_training = 1
14
51
  gpus_for_ref = 1
52
+ tensor_parallel = 2
15
53
 
16
54
  [training]
17
- num_epochs = 5
18
- iterations_per_epoch = 1
19
- batch_size = 4
20
- group_size = 16
55
+ num_epochs = 1
56
+ iterations_per_epoch = 2
57
+ batch_size = 1
58
+ group_size = 8
21
59
  learning_rate = 5e-6
22
60
  max_grad_norm = 0.5
23
61
  log_interval = 1
24
62
  update_reference_interval = 0
25
63
  weight_sync_interval = 1
26
64
 
65
+ [training.weight_sync]
66
+ enable = true
67
+ targets = ["policy"]
68
+
69
+ [vllm]
70
+ tensor_parallel_size = 2
71
+ gpu_memory_utilization = 0.9
72
+ max_model_len = 8192
73
+ max_num_seqs = 32
74
+ enforce_eager = false
75
+ max_parallel_generations = 4
76
+
27
77
  [evaluation]
28
- seeds = [0, 1, 2, 3]
78
+ seeds = [0, 1, 2, 3, 4, 5, 6, 7]
29
79
  rollouts_per_seed = 1
30
- instances = 1
80
+ instances = 0
31
81
  max_concurrent_rollouts = 4
32
- thinking_mode = "none"
33
- every_n_iters = 2
82
+ thinking_mode = "think"
83
+ every_n_iters = 5
34
84
 
35
85
  [rollout]
36
86
  env_name = "math"
37
87
  policy_name = "math-react"
38
- max_steps_per_episode = 1
88
+ env_config = {}
89
+ max_steps_per_episode = 5
39
90
  sampling_temperature = 0.3
40
91
  sampling_top_p = 0.95
41
- max_tokens = 256
42
- max_concurrent_rollouts = 8
43
- ops_per_rollout = 2
92
+ max_tokens = 1024
93
+ max_concurrent_rollouts = 4
94
+ ops_per_rollout = 14
44
95
  on_done = "reset"
96
+ thinking_mode = "think"
97
+ thinking_budget = 512
98
+
99
+ [policy]
100
+ config = {}
101
+
102
+ [hyperparams]
103
+ epsilon_low = 0.1
104
+ epsilon_high = 0.3
105
+ delta = 5.0
106
+ beta = 0.01
107
+ kl_penalty = 0.01
108
+ advantage_normalization = true
109
+ group_normalization = true
110
+ num_inner_steps = 1
111
+ clip_epsilon = 0.2
112
+ completion_only = false
113
+
114
+ [step_rewards]
115
+ enabled = false
116
+ mode = "off"
117
+ step_beta = 0.0
118
+ indicator_lambda = 0.0
119
+
120
+ [trainer]
121
+ allow_ref_fallback = false
122
+
123
+ [checkpoint]
124
+ interval = 10
125
+ directory = "/checkpoints"
126
+ keep_last_n = 3
127
+ save_optimizer = true
128
+ save_scheduler = true
129
+ enabled = true
synth_ai/handshake.py ADDED
@@ -0,0 +1,63 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import time
6
+ import webbrowser
7
+ from typing import Any, Dict, Tuple
8
+
9
+ import requests
10
+
11
+
12
+ class HandshakeError(Exception):
13
+ pass
14
+
15
+
16
+ def _origin() -> str:
17
+ # Prefer explicit env; fallback to localhost dashboard
18
+ return (os.getenv("SYNTH_CANONICAL_ORIGIN", "") or "http://localhost:3000").rstrip("/")
19
+
20
+
21
+ def start_handshake_session(origin: str | None = None) -> Tuple[str, str, int, int]:
22
+ base = (origin or _origin()).rstrip("/")
23
+ url = f"{base}/api/sdk/handshake/init"
24
+ r = requests.post(url, timeout=10)
25
+ if r.status_code != 200:
26
+ raise HandshakeError(f"init failed: {r.status_code} {r.text}")
27
+ data = r.json()
28
+ return (
29
+ str(data.get("device_code")),
30
+ str(data.get("verification_uri")),
31
+ int(data.get("expires_in", 600)),
32
+ int(data.get("interval", 3)),
33
+ )
34
+
35
+
36
+ def poll_handshake_token(device_code: str, origin: str | None = None, *, timeout_s: int | None = None) -> Dict[str, Any]:
37
+ base = (origin or _origin()).rstrip("/")
38
+ url = f"{base}/api/sdk/handshake/token"
39
+ deadline = time.time() + (timeout_s or 600)
40
+ while True:
41
+ if time.time() > deadline:
42
+ raise HandshakeError("handshake timed out")
43
+ try:
44
+ r = requests.post(url, json={"device_code": device_code}, timeout=10)
45
+ except Exception as e:
46
+ time.sleep(2)
47
+ continue
48
+ if r.status_code == 200:
49
+ return r.json()
50
+ elif r.status_code in (404, 410):
51
+ raise HandshakeError(f"handshake failed: {r.status_code}")
52
+ # 428 authorization_pending or others → wait and retry
53
+ time.sleep(2)
54
+
55
+
56
+ def run_handshake(origin: str | None = None) -> Dict[str, Any]:
57
+ device_code, verification_uri, expires_in, interval = start_handshake_session(origin)
58
+ try:
59
+ webbrowser.open(verification_uri)
60
+ except Exception:
61
+ pass
62
+ return poll_handshake_token(device_code, origin, timeout_s=expires_in)
63
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synth-ai
3
- Version: 0.2.6.dev6
3
+ Version: 0.2.8.dev1
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
@@ -14,6 +14,7 @@ Requires-Dist: pydantic>=2.0.0
14
14
  Requires-Dist: python-dotenv>=1.0.1
15
15
  Requires-Dist: requests>=2.32.3
16
16
  Requires-Dist: urllib3>=2.3.0
17
+ Requires-Dist: certifi>=2024.8.30
17
18
  Requires-Dist: tqdm>=4.66.4
18
19
  Requires-Dist: jsonschema>=4.23.0
19
20
  Requires-Dist: backoff>=2.0.0
@@ -97,10 +98,31 @@ synth-ai comes with a built-in RL example tailored for training Qwen/Qwen3-0.6B
97
98
  Please create an account at [Synth](https://usesynth.ai) and [Modal](https://modal.com) for the Math hello‑world test run. Then run:
98
99
 
99
100
  ```bash
100
- uvx synth-ai rl_demo check
101
+ uvx synth-ai rl_demo setup
101
102
  uvx synth-ai rl_demo deploy
102
- uvx synth-ai rl_demo configure
103
- uvx synth-ai rl_demo run
103
+ uvx synth-ai run
104
104
  ```
105
105
 
106
106
  To walk through kicking off your first RL run, see the [Synth‑AI Documentation](https://docs.usesynth.ai/synth-ai/introduction).
107
+
108
+ ### What `rl_demo setup` does now
109
+
110
+ When you run `uvx synth-ai rl_demo setup`, the SDK opens your browser to the Synth dashboard for a one‑time pairing (handshake) with your signed‑in session. The SDK will automatically:
111
+
112
+ - Detect your current user and organization
113
+ - Ensure both API keys exist for that user+org
114
+ - Write the keys to your project’s `.env` file as `SYNTH_API_KEY` and `ENVIRONMENT_API_KEY`
115
+
116
+ No keys are printed or requested interactively. You’ll see a confirmation like:
117
+
118
+ ```
119
+ Connecting SDK to your browser session…
120
+ Connected to Acme Labs via browser.
121
+ ```
122
+
123
+ If your browser isn’t already signed in, sign in when prompted and the pairing completes automatically. The dashboard’s welcome modal will reflect a successful pairing.
124
+
125
+ Environment variables:
126
+
127
+ - `SYNTH_CANONICAL_ORIGIN` (optional): override the dashboard base URL the SDK uses for the handshake (defaults to `http://localhost:3000`).
128
+ - Keys are stored only in your project’s `.env` file, not exported to your shell.
@@ -1,17 +1,18 @@
1
1
  synth_ai/__init__.py,sha256=NixuXddy4lS2Wmj0F8eMt0HS_oYCTnq3iVVq5VYwWIc,1341
2
2
  synth_ai/__main__.py,sha256=Kh1xBKkTE5Vs2qNMtDuuOXerHUptMcOiF3YziOpC6DA,146
3
+ synth_ai/handshake.py,sha256=AJR0GFFAkdAga8CXRLYbQl90-s0AQzTGxy5tQzPQb0E,1994
3
4
  synth_ai/http.py,sha256=lqjFXDmAP_xgfywK_rDSOVxuMy4rDH9S3Rtu9k1tLmk,1028
4
5
  synth_ai/http_client.py,sha256=_9J8rUGoItUMnJLGZw7r0uXiJeLWR939kByRkvtP1XM,4429
5
6
  synth_ai/install_sqld.sh,sha256=AMBhlfq661PxeTTc6D4K_Nei_qwMvA84ei4NhQzmUUk,928
6
7
  synth_ai/cli/__init__.py,sha256=ThBK5FykxAqX8Mz0E4gj94_PX9EwMEtXcmm-A8krv7E,1559
7
8
  synth_ai/cli/balance.py,sha256=z4h1MQSyFX60k-13L9IT0rtOCI16iKNGJeNjFMZuv_k,8010
8
9
  synth_ai/cli/calc.py,sha256=RJyQJ41e02xn-V0vRRCAVkL59UHDqyz8XpYGsenfdm4,2085
9
- synth_ai/cli/demo.py,sha256=GNVBxVtscxfAITFObyTOK8XPP2WGb-pv9LL4CiV_g6Q,4843
10
+ synth_ai/cli/demo.py,sha256=NeRiLv9ZQyX9tVxvZ6uV5YmucQ8fu5gyL5qZE0GfBZY,5496
10
11
  synth_ai/cli/legacy_root_backup.py,sha256=KSMADyJ2g5OVpsq_CeBzqIeDC2Um-9GyINzsJH-75uw,15872
11
12
  synth_ai/cli/man.py,sha256=JQDon73ZkuKP9xr1_vRh5fjV9_b5xiUb7zNjny7ArB8,3765
12
13
  synth_ai/cli/recent.py,sha256=mHhM-QrR_MfjfKSzBvvPUEC-lkXTWUZrQwqYTmb2x0Y,4173
13
- synth_ai/cli/rl_demo.py,sha256=thFzIlOIXqJ_kFwaek0JMjaCH_Jq5Lpp2nOZ3A3t-3k,5980
14
- synth_ai/cli/root.py,sha256=YAr7H2WYfnRt6_yxLix9O01-UnSy7OtYBVyNy4l5xIo,9614
14
+ synth_ai/cli/rl_demo.py,sha256=HAZqHaGFKAu7yXtjglmmNcHp4js77wCYSpa2WTcjyUE,8050
15
+ synth_ai/cli/root.py,sha256=7YgAxsefqscE4QEaa3kuKqBnaHbQLa4ZyXJ5l8eVl7Y,9741
15
16
  synth_ai/cli/status.py,sha256=M_bt7U58Ubi-q-ZlrIpgCASKq9_k6uMjpx926f6kLLA,4591
16
17
  synth_ai/cli/traces.py,sha256=_QBdCR92u0Gv51U4DH0Ws1d5yCrbJRpaYKe7pmcHrHs,6484
17
18
  synth_ai/cli/watch.py,sha256=HBKbAcpUkkPhGvsPRofckbu8oILiVqp35NXHkIEpTTc,17808
@@ -20,13 +21,13 @@ synth_ai/config/base_url.py,sha256=c85LaABBrvsl8Fp8KH0LNtJJrpnUwlzA5Ywbuth8fHE,3
20
21
  synth_ai/core/experiment.py,sha256=hLkPtzUFA7iY3-QpeJ5K8YjvQeyfqnjab5P2CFaojys,236
21
22
  synth_ai/core/system.py,sha256=s-Z7np2ISYmYc1r9YN-y2yb3cgRlOalrh0iaqnxeo84,206
22
23
  synth_ai/demos/core/__init__.py,sha256=A2FjhY7KXGtyzdQXqeTPCkEhHfrH-eQg6bvP8HaYhZM,36
23
- synth_ai/demos/core/cli.py,sha256=MuJELXFRxtyucek9b05Oo54pmJs5QGo45SV3hDZTFO0,44729
24
+ synth_ai/demos/core/cli.py,sha256=KkIm7nhKxHN26UQAjh-5wW-y__Z481UR23JmFl2GpM4,56329
24
25
  synth_ai/demos/demo_task_apps/__init__.py,sha256=8aUGEGpWUw11GRb3wQXRAmQ99yjAt5qd5FCTDJpXWjI,44
25
- synth_ai/demos/demo_task_apps/core.py,sha256=RsPRA_4p97_h0im33C-eJr2hryRFNdj54Zd9bdBcDsw,14005
26
+ synth_ai/demos/demo_task_apps/core.py,sha256=ifKxxRKqC-y43MaqLHNuerXAlBHO8MI8ZBo2CzYcOoU,14563
26
27
  synth_ai/demos/demo_task_apps/math/__init__.py,sha256=WBzpZwSn7pRarBmhopQi34i9bEm05-71eM3siboOavY,43
27
28
  synth_ai/demos/demo_task_apps/math/_common.py,sha256=SgtVW1pne4pgwGS2gYYQWkmG9BvU2sQTYzlncmUJ0NM,533
28
29
  synth_ai/demos/demo_task_apps/math/app.py,sha256=gNopoAhwM0vzdKuCa7AwQqSwiV2xagrjMxMH9YIniv4,1160
29
- synth_ai/demos/demo_task_apps/math/config.toml,sha256=atyeLq8tJsm4BST2NwlKUMum5D_gxEAWBqYsQGLQimI,757
30
+ synth_ai/demos/demo_task_apps/math/config.toml,sha256=Kxrzuyj7Az5mvzXaipPIyngKTDqphohf6uSWOHCF5cw,2105
30
31
  synth_ai/demos/demo_task_apps/math/deploy_modal.py,sha256=O4745sFuGEZTsygl-mz6ZOFJ7mog8CquXMgMyjFKr_c,2288
31
32
  synth_ai/demos/demo_task_apps/math/deploy_task_app.sh,sha256=qVffbAmsiCAxzFDzcxNVF4f7yyLWnmqPc1cNydHT5BQ,791
32
33
  synth_ai/demos/demo_task_apps/math/modal_task_app.py,sha256=DcjhzNj6hwaY4Me-kJPiGKPoVED9eW4dHoaPeMD4vzQ,18808
@@ -411,9 +412,9 @@ synth_ai/v0/tracing_v1/events/manage.py,sha256=ZDXXP-ZwLH9LCsmw7Ru9o55d7bl_diPtJ
411
412
  synth_ai/v0/tracing_v1/events/scope.py,sha256=BuBkhSpVHUJt8iGT9HJZF82rbb88mQcd2vM2shg-w2I,2550
412
413
  synth_ai/v0/tracing_v1/events/store.py,sha256=0342lvAcalyJbVEIzQFaPuMQGgwiFm7M5rE6gr-G0E8,9041
413
414
  synth_ai/zyk/__init__.py,sha256=htVLnzTYQ5rxzYpzSYBm7_o6uNKZ3pB_PrqkBrgTRS4,771
414
- synth_ai-0.2.6.dev6.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
415
- synth_ai-0.2.6.dev6.dist-info/METADATA,sha256=DTrV1I4ushAH4IrpGgfn1qCvmsqEAXlZbxdHjT1lHFw,3980
416
- synth_ai-0.2.6.dev6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
417
- synth_ai-0.2.6.dev6.dist-info/entry_points.txt,sha256=Neq-3bT7TAijjgOIR77pKL-WYg6TWBDeO8pp_nL4vGY,91
418
- synth_ai-0.2.6.dev6.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
419
- synth_ai-0.2.6.dev6.dist-info/RECORD,,
415
+ synth_ai-0.2.8.dev1.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
416
+ synth_ai-0.2.8.dev1.dist-info/METADATA,sha256=fvfulLHeAJH3XRKXDBAhNQbb2vRtCXvzh4qXu06PsmI,4980
417
+ synth_ai-0.2.8.dev1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
418
+ synth_ai-0.2.8.dev1.dist-info/entry_points.txt,sha256=Neq-3bT7TAijjgOIR77pKL-WYg6TWBDeO8pp_nL4vGY,91
419
+ synth_ai-0.2.8.dev1.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
420
+ synth_ai-0.2.8.dev1.dist-info/RECORD,,