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

Files changed (226) hide show
  1. examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +12 -1
  2. examples/swe/task_app/grpo_swe_mini.py +55 -26
  3. examples/swe/task_app/hosted/rollout.py +40 -0
  4. examples/swe/task_app/hosted/test_service.py +5 -6
  5. examples/task_apps/TESTING.md +275 -0
  6. examples/task_apps/__init__.py +0 -0
  7. examples/task_apps/crafter/__init__.py +0 -0
  8. examples/task_apps/crafter/task_app/__init__.py +2 -0
  9. examples/{warming_up_to_rl → task_apps/crafter}/task_app/grpo_crafter.py +18 -13
  10. examples/{warming_up_to_rl → task_apps/crafter}/task_app/grpo_crafter_task_app.py +1 -1
  11. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/policy.py +60 -4
  12. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/policy_routes.py +25 -3
  13. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/rollout.py +10 -0
  14. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/test_service.py +5 -6
  15. examples/task_apps/dev/pokemon_emerald/__init__.py +2 -0
  16. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/README.md +811 -0
  17. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/__init__.py +120 -0
  18. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/action.py +160 -0
  19. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/memory.py +155 -0
  20. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/perception.py +69 -0
  21. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/planning.py +96 -0
  22. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/simple.py +1502 -0
  23. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/system_prompt.py +4 -0
  24. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/grab_map.py +68 -0
  25. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/manual.py +216 -0
  26. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/__init__.py +35 -0
  27. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emerald_utils.py +631 -0
  28. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emulator.py +1544 -0
  29. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/enums.py +1428 -0
  30. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/memory_reader.py +4848 -0
  31. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/types.py +41 -0
  32. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/utils.py +298 -0
  33. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pyproject.toml +95 -0
  34. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/run.py +204 -0
  35. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/__init__.py +0 -0
  36. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/app.py +2152 -0
  37. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/client.py +429 -0
  38. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/frame_server.py +155 -0
  39. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/README.md +78 -0
  40. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/__init__.py +0 -0
  41. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/run_tests.py +122 -0
  42. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_direct.py +76 -0
  43. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_prompts.py +413 -0
  44. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_battle_state_formatting.py +204 -0
  45. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection.py +133 -0
  46. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection_comprehensive.py +229 -0
  47. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_direct_agent_emulator.py +300 -0
  48. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_fps_adjustment_pytest.py +205 -0
  49. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_direct.py +200 -0
  50. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_transition.py +284 -0
  51. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_map_ground_truth_comparison.py +468 -0
  52. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_memory_map.py +575 -0
  53. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_server_map_validation.py +311 -0
  54. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_torchic_state.py +259 -0
  55. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/__init__.py +0 -0
  56. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/anticheat.py +372 -0
  57. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/checkpoint.py +296 -0
  58. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/error_handler.py +275 -0
  59. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/get_local_ip.py +22 -0
  60. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/helpers.py +44 -0
  61. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/llm_logger.py +514 -0
  62. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_formatter.py +415 -0
  63. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher.py +1763 -0
  64. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher_singleton.py +33 -0
  65. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_trimmer.py +106 -0
  66. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_visualizer.py +334 -0
  67. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/ocr_dialogue.py +1020 -0
  68. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/recording.py +188 -0
  69. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/state_formatter.py +1481 -0
  70. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/vlm.py +862 -0
  71. examples/task_apps/dev/pokemon_emerald/modal_app.py +114 -0
  72. examples/task_apps/dev/pokemon_emerald/task_app/README.md +81 -0
  73. examples/task_apps/dev/pokemon_emerald/task_app/__init__.py +6 -0
  74. examples/task_apps/dev/pokemon_emerald/task_app/pokemon_emerald.py +685 -0
  75. examples/task_apps/enron/__init__.py +1 -0
  76. examples/task_apps/enron/eval_groq_qwen32.toml +16 -0
  77. examples/task_apps/enron/task_app/README.md +14 -0
  78. examples/task_apps/enron/task_app/__init__.py +1 -0
  79. examples/task_apps/enron/task_app/grpo_enron.py +906 -0
  80. examples/task_apps/enron/task_app/grpo_enron_task_app.py +146 -0
  81. examples/task_apps/enron/tests/__init__.py +2 -0
  82. examples/task_apps/enron/tests/conftest.py +115 -0
  83. examples/task_apps/enron/tests/integration/__init__.py +2 -0
  84. examples/task_apps/enron/tests/integration/test_enron_eval.py +177 -0
  85. examples/task_apps/enron/tests/integration/test_enron_rollout.py +135 -0
  86. examples/task_apps/enron/tests/unit/__init__.py +2 -0
  87. examples/task_apps/enron/tests/unit/test_enron_environment.py +126 -0
  88. examples/task_apps/math/__init__.py +0 -0
  89. examples/{rl/task_app → task_apps/math}/math_single_step.py +19 -10
  90. examples/task_apps/pokemon_battle/__init__.py +2 -0
  91. examples/task_apps/pokemon_battle/modal_app.py +104 -0
  92. examples/task_apps/pokemon_battle/task_app/README.md +68 -0
  93. examples/task_apps/pokemon_battle/task_app/__init__.py +6 -0
  94. examples/task_apps/pokemon_battle/task_app/pokemon_showdown.py +932 -0
  95. examples/task_apps/pokemon_red/README.md +357 -0
  96. examples/task_apps/pokemon_red/__init__.py +3 -0
  97. examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +225 -0
  98. examples/task_apps/pokemon_red/pallet_town_rl_config.toml +73 -0
  99. examples/task_apps/pokemon_red/task_app.py +606 -0
  100. examples/task_apps/pokemon_red/test_pallet_town_rewards.py +191 -0
  101. examples/task_apps/sokoban/README.md +307 -0
  102. examples/task_apps/sokoban/__init__.py +3 -0
  103. examples/task_apps/sokoban/eval_groq_qwen32.toml +16 -0
  104. examples/task_apps/sokoban/eval_openai_gpt5.toml +16 -0
  105. examples/task_apps/sokoban/task_app.py +1058 -0
  106. examples/task_apps/sokoban/tests/__init__.py +2 -0
  107. examples/task_apps/sokoban/tests/conftest.py +113 -0
  108. examples/task_apps/sokoban/tests/integration/__init__.py +2 -0
  109. examples/task_apps/sokoban/tests/integration/test_sokoban_eval.py +57 -0
  110. examples/task_apps/sokoban/tests/integration/test_sokoban_rollout.py +198 -0
  111. examples/task_apps/sokoban/tests/unit/__init__.py +2 -0
  112. examples/task_apps/sokoban/tests/unit/test_sokoban_environment.py +114 -0
  113. examples/task_apps/verilog/__init__.py +1 -0
  114. examples/task_apps/verilog/eval_groq_qwen32b.toml +20 -0
  115. examples/task_apps/verilog/task_app/README.md +12 -0
  116. examples/task_apps/verilog/task_app/__init__.py +1 -0
  117. examples/task_apps/verilog/task_app/grpo_verilog.py +931 -0
  118. examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +145 -0
  119. examples/task_apps/verilog/tests/__init__.py +2 -0
  120. examples/task_apps/verilog/tests/conftest.py +115 -0
  121. examples/task_apps/verilog/tests/integration/__init__.py +2 -0
  122. examples/task_apps/verilog/tests/integration/test_verilog_eval.py +179 -0
  123. examples/task_apps/verilog/tests/integration/test_verilog_rollout.py +55 -0
  124. examples/task_apps/verilog/tests/unit/__init__.py +2 -0
  125. examples/task_apps/verilog/tests/unit/test_verilog_scoring.py +118 -0
  126. examples/vlm/crafter_openai_vlm_agent.py +4 -4
  127. examples/vlm/run_crafter_vlm_benchmark.py +4 -4
  128. examples/workflows/__init__.py +0 -0
  129. examples/workflows/math_rl/__init__.py +0 -0
  130. examples/workflows/math_rl/download_dataset.py +80 -0
  131. synth_ai/__init__.py +2 -2
  132. synth_ai/api/train/builders.py +25 -11
  133. synth_ai/api/train/cli.py +12 -6
  134. synth_ai/api/train/configs/__init__.py +10 -10
  135. synth_ai/api/train/configs/rl.py +5 -4
  136. synth_ai/api/train/configs/sft.py +4 -3
  137. synth_ai/api/train/env_resolver.py +5 -2
  138. synth_ai/api/train/supported_algos.py +10 -5
  139. synth_ai/api/train/utils.py +7 -4
  140. synth_ai/cli/__init__.py +7 -51
  141. synth_ai/cli/_storage.py +4 -3
  142. synth_ai/cli/_validate_task_app.py +11 -0
  143. synth_ai/cli/balance.py +4 -3
  144. synth_ai/cli/calc.py +2 -2
  145. synth_ai/cli/demo.py +14 -7
  146. synth_ai/cli/legacy_root_backup.py +1 -1
  147. synth_ai/cli/rl_demo.py +8 -7
  148. synth_ai/cli/root.py +0 -97
  149. synth_ai/cli/task_apps.py +1707 -186
  150. synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +28 -16
  151. synth_ai/environments/examples/enron/engine.py +7 -2
  152. synth_ai/environments/examples/enron/environment.py +68 -0
  153. synth_ai/environments/examples/red/engine.py +27 -0
  154. synth_ai/environments/examples/red/engine_helpers/memory_map.py +7 -0
  155. synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_progression.py +477 -0
  156. synth_ai/environments/examples/red/engine_helpers/state_extraction.py +32 -0
  157. synth_ai/environments/examples/red/environment.py +60 -0
  158. synth_ai/environments/examples/sokoban/taskset.py +116 -0
  159. synth_ai/environments/examples/verilog/engine.py +30 -4
  160. synth_ai/evals/client.py +58 -61
  161. synth_ai/jobs/client.py +16 -4
  162. synth_ai/judge_schemas.py +16 -16
  163. synth_ai/py.typed +0 -0
  164. synth_ai/task/__init__.py +14 -5
  165. synth_ai/task/contracts.py +124 -38
  166. synth_ai/task/proxy.py +48 -56
  167. synth_ai/task/rubrics/__init__.py +53 -0
  168. synth_ai/task/rubrics/loaders.py +133 -0
  169. synth_ai/task/rubrics/models.py +57 -0
  170. synth_ai/task/rubrics/scoring.py +113 -0
  171. synth_ai/{rubrics/validators.py → task/rubrics/strict.py} +53 -30
  172. synth_ai/task/server.py +8 -7
  173. synth_ai/task/validators.py +269 -6
  174. synth_ai/tracing_v3/decorators.py +7 -3
  175. synth_ai/tracing_v3/replica_sync.py +4 -4
  176. synth_ai/tracing_v3/serialization.py +5 -5
  177. synth_ai/tracing_v3/trace_utils.py +317 -0
  178. synth_ai/tracing_v3/turso/native_manager.py +3 -3
  179. {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.13.dev2.dist-info}/METADATA +4 -1
  180. {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.13.dev2.dist-info}/RECORD +214 -101
  181. examples/agora_ex/README_MoE.md +0 -224
  182. examples/agora_ex/__init__.py +0 -7
  183. examples/agora_ex/agora_ex.py +0 -65
  184. examples/agora_ex/agora_ex_task_app.py +0 -590
  185. examples/agora_ex/configs/rl_lora_qwen3_moe_2xh200.toml +0 -121
  186. examples/agora_ex/reward_fn_grpo-human.py +0 -129
  187. examples/agora_ex/system_prompt_CURRENT.md +0 -63
  188. examples/agora_ex/task_app/agora_ex_task_app.py +0 -590
  189. examples/agora_ex/task_app/reward_fn_grpo-human.py +0 -129
  190. examples/agora_ex/task_app/system_prompt_CURRENT.md +0 -63
  191. synth_ai/rubrics/__init__.py +0 -22
  192. synth_ai/task/rubrics.py +0 -219
  193. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/README.md +0 -0
  194. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/README.md +0 -0
  195. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/__init__.py +0 -0
  196. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/branching.py +0 -0
  197. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/environment_routes.py +0 -0
  198. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/__init__.py +0 -0
  199. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/__init__.py +0 -0
  200. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/app.py +0 -0
  201. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/environment.py +0 -0
  202. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/react_agent.py +0 -0
  203. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/shared.py +0 -0
  204. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/tools.py +0 -0
  205. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/hosted_app.py +0 -0
  206. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/inference/__init__.py +0 -0
  207. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/inference/openai_client.py +0 -0
  208. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/main.py +0 -0
  209. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/registry.py +0 -0
  210. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/storage/__init__.py +0 -0
  211. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/storage/volume.py +0 -0
  212. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/test_agents.py +0 -0
  213. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/utils.py +0 -0
  214. /examples/{rl/task_app → task_apps/math}/README.md +0 -0
  215. /examples/{rl/task_app → task_apps/math}/math_task_app.py +0 -0
  216. /examples/{rl → workflows/math_rl}/configs/eval_base_qwen.toml +0 -0
  217. /examples/{rl → workflows/math_rl}/configs/eval_rl_qwen.toml +0 -0
  218. /examples/{rl → workflows/math_rl}/configs/rl_from_base_qwen.toml +0 -0
  219. /examples/{rl → workflows/math_rl}/configs/rl_from_base_qwen17.toml +0 -0
  220. /examples/{rl → workflows/math_rl}/configs/rl_from_ft_qwen.toml +0 -0
  221. /examples/{rl → workflows/math_rl}/run_eval.py +0 -0
  222. /examples/{rl → workflows/math_rl}/run_rl_and_save.py +0 -0
  223. {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.13.dev2.dist-info}/WHEEL +0 -0
  224. {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.13.dev2.dist-info}/entry_points.txt +0 -0
  225. {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.13.dev2.dist-info}/licenses/LICENSE +0 -0
  226. {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.13.dev2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env python3
2
+ """Download subsets of the MATH dataset to local JSONL files."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ from datasets import load_dataset
12
+
13
+
14
+ def extract_examples(dataset: Any, *, limit: int | None) -> list[dict[str, str]]:
15
+ if limit is not None:
16
+ dataset = dataset.select(range(min(limit, len(dataset))))
17
+ examples: list[dict[str, str]] = []
18
+ for item in dataset:
19
+ problem = (item.get("problem") or "").strip()
20
+ solution = item.get("solution") or ""
21
+ if isinstance(solution, list):
22
+ solution = "\n".join(str(part) for part in solution)
23
+ examples.append(
24
+ {
25
+ "problem": problem,
26
+ "solution": solution,
27
+ }
28
+ )
29
+ return examples
30
+
31
+
32
+ def write_jsonl(path: Path, rows: list[dict[str, str]]) -> None:
33
+ path.parent.mkdir(parents=True, exist_ok=True)
34
+ with path.open("w", encoding="utf-8") as fh:
35
+ for row in rows:
36
+ fh.write(json.dumps(row, ensure_ascii=False) + "\n")
37
+
38
+
39
+ def main() -> None:
40
+ parser = argparse.ArgumentParser(
41
+ description="Download MATH dataset splits to JSONL for offline use"
42
+ )
43
+ parser.add_argument(
44
+ "--output-dir", default="examples/rl/data", help="Directory to write <split>.jsonl files"
45
+ )
46
+ parser.add_argument(
47
+ "--dataset",
48
+ default="nlile/hendrycks-MATH-benchmark",
49
+ help="Hugging Face dataset identifier",
50
+ )
51
+ parser.add_argument(
52
+ "--config", default="algebra", help="Hugging Face dataset config (if required)"
53
+ )
54
+ parser.add_argument(
55
+ "--splits", nargs="*", default=["train", "validation", "test"], help="Splits to download"
56
+ )
57
+ parser.add_argument(
58
+ "--limit", type=int, default=None, help="Optional cap on examples per split"
59
+ )
60
+ args = parser.parse_args()
61
+
62
+ output_dir = Path(args.output_dir).expanduser()
63
+ output_dir.mkdir(parents=True, exist_ok=True)
64
+
65
+ for split in args.splits:
66
+ print(f"[INFO] Downloading {args.dataset} ({args.config}) split={split}")
67
+ if args.config:
68
+ dataset = load_dataset(args.dataset, args.config, split=split)
69
+ else:
70
+ dataset = load_dataset(args.dataset, split=split)
71
+ rows = extract_examples(dataset, limit=args.limit)
72
+ out_path = output_dir / f"{split}.jsonl"
73
+ write_jsonl(out_path, rows)
74
+ print(f"[INFO] Wrote {len(rows)} examples to {out_path}")
75
+
76
+ print("Done. Set MATH_DATASET_LOCAL_DIR to the output directory when serving the task app.")
77
+
78
+
79
+ if __name__ == "__main__":
80
+ main()
synth_ai/__init__.py CHANGED
@@ -45,13 +45,13 @@ except Exception:
45
45
 
46
46
  # Judge API contract schemas
47
47
  from synth_ai.judge_schemas import (
48
+ CriterionScorePayload,
49
+ JudgeOptions,
48
50
  JudgeScoreRequest,
49
51
  JudgeScoreResponse,
50
- JudgeOptions,
51
52
  JudgeTaskApp,
52
53
  JudgeTracePayload,
53
54
  ReviewPayload,
54
- CriterionScorePayload,
55
55
  )
56
56
 
57
57
  # Legacy tracing v1 is not required for v3 usage and can be unavailable in minimal envs.
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import importlib
4
+ from collections.abc import Callable
4
5
  from dataclasses import dataclass
5
6
  from pathlib import Path
6
7
  from typing import Any, cast
@@ -9,25 +10,36 @@ import click
9
10
  from pydantic import ValidationError
10
11
 
11
12
  try:
12
- _models_module = importlib.import_module("synth_ai.api.models.supported")
13
- UnsupportedModelError = _models_module.UnsupportedModelError
14
- ensure_allowed_model = _models_module.ensure_allowed_model
15
- normalize_model_identifier = _models_module.normalize_model_identifier
13
+ _models_module = cast(
14
+ Any, importlib.import_module("synth_ai.api.models.supported")
15
+ )
16
+ UnsupportedModelError = cast(type[Exception], _models_module.UnsupportedModelError)
17
+ ensure_allowed_model = cast(
18
+ Callable[..., None], _models_module.ensure_allowed_model
19
+ )
20
+ normalize_model_identifier = cast(
21
+ Callable[[str], str], _models_module.normalize_model_identifier
22
+ )
16
23
  except Exception as exc: # pragma: no cover - critical dependency
17
24
  raise RuntimeError("Unable to load supported model helpers") from exc
18
25
 
19
26
  try:
20
- prepare_sft_job_payload = importlib.import_module("synth_ai.learning.sft.config").prepare_sft_job_payload
27
+ _sft_module = cast(
28
+ Any, importlib.import_module("synth_ai.learning.sft.config")
29
+ )
30
+ prepare_sft_job_payload = cast(
31
+ Callable[..., dict[str, Any]], _sft_module.prepare_sft_job_payload
32
+ )
21
33
  except Exception as exc: # pragma: no cover - critical dependency
22
34
  raise RuntimeError("Unable to load SFT payload helpers") from exc
23
35
 
36
+ from .configs import RLConfig, SFTConfig
24
37
  from .supported_algos import (
25
38
  AlgorithmValidationError,
26
39
  ensure_model_supported_for_algorithm,
27
40
  validate_algorithm_config,
28
41
  )
29
42
  from .utils import TrainError, ensure_api_base
30
- from .configs import RLConfig, SFTConfig
31
43
 
32
44
 
33
45
  @dataclass(slots=True)
@@ -125,7 +137,7 @@ def build_rl_payload(
125
137
  if model_source:
126
138
  model_source = normalize_model_identifier(model_source)
127
139
  if model_base:
128
- model_base = normalize_model_identifier(model_base, allow_finetuned_prefixes=False)
140
+ model_base = normalize_model_identifier(model_base)
129
141
  except UnsupportedModelError as exc:
130
142
  raise click.ClickException(str(exc)) from exc
131
143
 
@@ -304,10 +316,12 @@ def build_sft_payload(
304
316
  )
305
317
  except UnsupportedModelError as exc:
306
318
  raise TrainError(str(exc)) from exc
307
- try:
308
- ensure_model_supported_for_algorithm(base_model, spec)
309
- except AlgorithmValidationError as exc:
310
- raise TrainError(str(exc)) from exc
319
+
320
+ if base_model:
321
+ try:
322
+ ensure_model_supported_for_algorithm(base_model, spec)
323
+ except AlgorithmValidationError as exc:
324
+ raise TrainError(str(exc)) from exc
311
325
 
312
326
  try:
313
327
  payload = prepare_sft_job_payload(
synth_ai/api/train/cli.py CHANGED
@@ -2,15 +2,17 @@ from __future__ import annotations
2
2
 
3
3
  import importlib
4
4
  import os
5
- from collections.abc import Mapping
5
+ from collections.abc import Callable, Mapping
6
6
  from pathlib import Path
7
- from typing import Any
7
+ from typing import Any, cast
8
8
 
9
9
  import click
10
10
 
11
11
  try:
12
- _config_module = importlib.import_module("synth_ai.config.base_url")
13
- get_backend_from_env = _config_module.get_backend_from_env
12
+ _config_module = cast(
13
+ Any, importlib.import_module("synth_ai.config.base_url")
14
+ )
15
+ get_backend_from_env = cast(Callable[[], str], _config_module.get_backend_from_env)
14
16
  except Exception as exc: # pragma: no cover - critical dependency
15
17
  raise RuntimeError("Unable to load backend configuration helpers") from exc
16
18
 
@@ -238,8 +240,12 @@ def train_command(
238
240
  ]
239
241
  if missing_keys:
240
242
  try:
241
- _task_apps_module = importlib.import_module("synth_ai.cli.task_apps")
242
- _interactive_fill_env = _task_apps_module._interactive_fill_env
243
+ _task_apps_module = cast(
244
+ Any, importlib.import_module("synth_ai.cli.task_apps")
245
+ )
246
+ _interactive_fill_env = cast(
247
+ Callable[[Path], Path | None], _task_apps_module._interactive_fill_env
248
+ )
243
249
  except Exception as exc: # pragma: no cover - protective fallback
244
250
  raise click.ClickException(f"Unable to prompt for env values: {exc}") from exc
245
251
 
@@ -1,15 +1,5 @@
1
1
  """Typed training config loaders for RL and SFT jobs."""
2
2
 
3
- from .shared import AlgorithmConfig, ComputeConfig
4
- from .sft import (
5
- HyperparametersConfig,
6
- HyperparametersParallelism,
7
- JobConfig,
8
- SFTConfig,
9
- SFTDataConfig,
10
- TrainingConfig,
11
- TrainingValidationConfig,
12
- )
13
3
  from .rl import (
14
4
  EvaluationConfig,
15
5
  JudgeConfig,
@@ -21,6 +11,16 @@ from .rl import (
21
11
  RolloutConfig,
22
12
  WeightSyncConfig,
23
13
  )
14
+ from .sft import (
15
+ HyperparametersConfig,
16
+ HyperparametersParallelism,
17
+ JobConfig,
18
+ SFTConfig,
19
+ SFTDataConfig,
20
+ TrainingConfig,
21
+ TrainingValidationConfig,
22
+ )
23
+ from .shared import AlgorithmConfig, ComputeConfig
24
24
 
25
25
  __all__ = [
26
26
  "AlgorithmConfig",
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Mapping
3
4
  from pathlib import Path
4
- from typing import Any, Mapping
5
+ from typing import Any
5
6
 
6
7
  from pydantic import model_validator
7
8
 
@@ -21,7 +22,7 @@ class ModelConfig(ExtraModel):
21
22
  label: str
22
23
 
23
24
  @model_validator(mode="after")
24
- def _ensure_exactly_one_source_or_base(self) -> "ModelConfig":
25
+ def _ensure_exactly_one_source_or_base(self) -> ModelConfig:
25
26
  if bool(self.source) == bool(self.base):
26
27
  raise ValueError("Config must set exactly one of [model].source or [model].base")
27
28
  return self
@@ -111,11 +112,11 @@ class RLConfig(ExtraModel):
111
112
  return self.model_dump(mode="python", exclude_none=True)
112
113
 
113
114
  @classmethod
114
- def from_mapping(cls, data: Mapping[str, Any]) -> "RLConfig":
115
+ def from_mapping(cls, data: Mapping[str, Any]) -> RLConfig:
115
116
  return cls.model_validate(dict(data))
116
117
 
117
118
  @classmethod
118
- def from_path(cls, path: Path) -> "RLConfig":
119
+ def from_path(cls, path: Path) -> RLConfig:
119
120
  content = load_toml(path)
120
121
  return cls.from_mapping(content)
121
122
 
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Mapping
3
4
  from pathlib import Path
4
- from typing import Any, Mapping
5
+ from typing import Any
5
6
 
6
7
  from pydantic import Field
7
8
 
@@ -74,11 +75,11 @@ class SFTConfig(ExtraModel):
74
75
  return self.model_dump(mode="python", exclude_none=True)
75
76
 
76
77
  @classmethod
77
- def from_mapping(cls, data: Mapping[str, Any]) -> "SFTConfig":
78
+ def from_mapping(cls, data: Mapping[str, Any]) -> SFTConfig:
78
79
  return cls.model_validate(dict(data))
79
80
 
80
81
  @classmethod
81
- def from_path(cls, path: Path) -> "SFTConfig":
82
+ def from_path(cls, path: Path) -> SFTConfig:
82
83
  content = load_toml(path)
83
84
  return cls.from_mapping(content)
84
85
 
@@ -5,6 +5,7 @@ import os
5
5
  from collections.abc import Callable, Iterable, MutableMapping
6
6
  from dataclasses import dataclass
7
7
  from pathlib import Path
8
+ from typing import Any, cast
8
9
 
9
10
  import click
10
11
 
@@ -14,8 +15,10 @@ from .utils import REPO_ROOT, mask_value, read_env_file, write_env_value
14
15
 
15
16
  def _load_saved_env_path() -> Path | None:
16
17
  try:
17
- module = importlib.import_module("synth_ai.demos.demo_task_apps.core")
18
- loader = module.load_env_file_path
18
+ module = cast(
19
+ Any, importlib.import_module("synth_ai.demos.demo_task_apps.core")
20
+ )
21
+ loader = cast(Callable[[], str | None], module.load_env_file_path)
19
22
  saved_path = loader()
20
23
  if saved_path:
21
24
  return Path(saved_path)
@@ -1,14 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import importlib
4
- from collections.abc import Mapping
4
+ from collections.abc import Callable, Mapping
5
5
  from dataclasses import dataclass
6
+ from typing import Any, cast
6
7
 
7
8
  try:
8
- _models_module = importlib.import_module("synth_ai.api.models.supported")
9
- RL_SUPPORTED_MODELS = _models_module.RL_SUPPORTED_MODELS
10
- SFT_SUPPORTED_MODELS = _models_module.SFT_SUPPORTED_MODELS
11
- training_modes_for_model = _models_module.training_modes_for_model
9
+ _models_module = cast(
10
+ Any, importlib.import_module("synth_ai.api.models.supported")
11
+ )
12
+ RL_SUPPORTED_MODELS = cast(tuple[str, ...], _models_module.RL_SUPPORTED_MODELS)
13
+ SFT_SUPPORTED_MODELS = cast(tuple[str, ...], _models_module.SFT_SUPPORTED_MODELS)
14
+ training_modes_for_model = cast(
15
+ Callable[[str], tuple[str, ...]], _models_module.training_modes_for_model
16
+ )
12
17
  except Exception as exc: # pragma: no cover - critical dependency
13
18
  raise RuntimeError("Unable to load supported model metadata") from exc
14
19
 
@@ -8,15 +8,18 @@ import subprocess
8
8
  import tempfile
9
9
  import time
10
10
  import tomllib
11
- from collections.abc import Iterable, Mapping
11
+ from collections.abc import Callable, Iterable, Mapping
12
12
  from dataclasses import dataclass
13
13
  from pathlib import Path
14
- from typing import Any
14
+ from typing import Any, cast
15
15
 
16
16
  import requests
17
17
 
18
18
  try:
19
- collect_sft_jsonl_errors = importlib.import_module("synth_ai.learning.sft").collect_sft_jsonl_errors
19
+ sft_module = cast(Any, importlib.import_module("synth_ai.learning.sft"))
20
+ collect_sft_jsonl_errors = cast(
21
+ Callable[..., list[dict[str, Any]]], sft_module.collect_sft_jsonl_errors
22
+ )
20
23
  except Exception as exc: # pragma: no cover - critical dependency
21
24
  raise RuntimeError("Unable to load SFT JSONL helpers") from exc
22
25
 
@@ -154,7 +157,7 @@ def validate_sft_jsonl(path: Path, *, max_errors: int = 20) -> None:
154
157
 
155
158
  truncated = max_errors is not None and len(issues) >= max_errors
156
159
  suffix = "" if not truncated else f" (showing first {max_errors} issues)"
157
- details = "\n - ".join(issues)
160
+ details = "\n - ".join(cast("list[str]", issues))
158
161
  raise TrainError(f"{path}: Dataset validation failed{suffix}:\n - {details}")
159
162
 
160
163
 
synth_ai/cli/__init__.py CHANGED
@@ -8,6 +8,8 @@ pyproject entry point `synth_ai.cli:cli`.
8
8
  from __future__ import annotations
9
9
 
10
10
  import importlib
11
+ from collections.abc import Callable
12
+ from typing import Any, cast
11
13
 
12
14
  # Load environment variables from a local .env if present (repo root)
13
15
  try:
@@ -30,48 +32,8 @@ except Exception:
30
32
  from .root import cli # new canonical CLI entrypoint
31
33
 
32
34
  # Register subcommands from this package onto the group
33
- try:
34
- from . import watch as _watch
35
-
36
- _watch.register(cli)
37
- except Exception:
38
- pass
39
- try:
40
- from . import balance as _balance
41
-
42
- _balance.register(cli)
43
- except Exception:
44
- pass
45
- try:
46
- from . import man as _man
47
-
48
- _man.register(cli)
49
- except Exception:
50
- pass
51
- try:
52
- from . import traces as _traces
53
-
54
- _traces.register(cli)
55
- except Exception:
56
- pass
57
- try:
58
- from . import recent as _recent
59
-
60
- _recent.register(cli)
61
- except Exception:
62
- pass
63
- try:
64
- from . import calc as _calc
65
-
66
- _calc.register(cli)
67
- except Exception:
68
- pass
69
- try:
70
- from . import status as _status
71
-
72
- _status.register(cli)
73
- except Exception:
74
- pass
35
+ # Deprecated/legacy commands intentionally not registered: watch/experiments, balance, calc,
36
+ # man, recent, status, traces
75
37
  try:
76
38
  from . import demo as _demo
77
39
 
@@ -85,14 +47,8 @@ try:
85
47
  except Exception:
86
48
  pass
87
49
  try:
88
- from . import rl_demo as _rl_demo
89
-
90
- _rl_demo.register(cli)
91
- except Exception:
92
- pass
93
- try:
94
- _train_module = importlib.import_module("synth_ai.api.train")
95
- _train_register = _train_module.register
50
+ _train_module = cast(Any, importlib.import_module("synth_ai.api.train"))
51
+ _train_register = cast(Callable[[Any], None], _train_module.register)
96
52
  _train_register(cli)
97
53
  except Exception:
98
54
  pass
@@ -114,4 +70,4 @@ cli.add_command(task_app_group.commands["serve"], name="serve")
114
70
  cli.add_command(task_app_group.commands["deploy"], name="deploy")
115
71
 
116
72
  cli.add_command(task_app_group.commands["modal-serve"], name="modal-serve")
117
- cli.add_command(task_app_group.commands["info"], name="info")
73
+ # Top-level 'info' alias removed; use `synth-ai task-app info` instead
synth_ai/cli/_storage.py CHANGED
@@ -8,12 +8,13 @@ allowing type checkers to resolve the symbols dynamically.
8
8
  from __future__ import annotations
9
9
 
10
10
  import importlib
11
- from typing import Any
11
+ from collections.abc import Callable
12
+ from typing import Any, cast
12
13
 
13
14
 
14
15
  def load_storage() -> tuple[Any, Any]:
15
16
  """Return (create_storage, StorageConfig) from tracing_v3.storage."""
16
- storage_module = importlib.import_module("synth_ai.tracing_v3.storage")
17
- create_storage = storage_module.create_storage
17
+ storage_module = cast(Any, importlib.import_module("synth_ai.tracing_v3.storage"))
18
+ create_storage = cast(Callable[..., Any], storage_module.create_storage)
18
19
  storage_config = storage_module.StorageConfig
19
20
  return create_storage, storage_config
@@ -0,0 +1,11 @@
1
+ """Task app validation utilities - imported by task_apps.py"""
2
+
3
+ # This module provides the validate_task_app function for CLI use
4
+ # The actual implementation is imported from the task module
5
+
6
+ from synth_ai.task.validators import (
7
+ validate_task_app_endpoint as validate_task_app, # type: ignore[attr-defined]
8
+ )
9
+
10
+ __all__ = ["validate_task_app"]
11
+
synth_ai/cli/balance.py CHANGED
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
  import importlib
9
9
  import os
10
10
  from collections.abc import Callable
11
+ from typing import Any, cast
11
12
 
12
13
  import click
13
14
  import requests
@@ -19,9 +20,9 @@ from rich.table import Table
19
20
 
20
21
  def _load_base_url_module() -> tuple[str, Callable[[], tuple[str, str]]]:
21
22
  try:
22
- module = importlib.import_module("synth_ai.config.base_url")
23
- default = module.PROD_BASE_URL_DEFAULT
24
- getter = module.get_backend_from_env
23
+ module = cast(Any, importlib.import_module("synth_ai.config.base_url"))
24
+ default = cast(str, module.PROD_BASE_URL_DEFAULT)
25
+ getter = cast(Callable[[], tuple[str, str]], module.get_backend_from_env)
25
26
  return str(default), getter
26
27
  except Exception:
27
28
  return "https://agent-learning.onrender.com", lambda: ("https://agent-learning.onrender.com", "")
synth_ai/cli/calc.py CHANGED
@@ -35,13 +35,13 @@ def _safe_eval(expr: str) -> float:
35
35
  if isinstance(n, ast.Expression):
36
36
  return _eval(n.body)
37
37
  if isinstance(n, ast.Constant):
38
- if isinstance(n.value, (int, float)):
38
+ if isinstance(n.value, int | float):
39
39
  return float(n.value)
40
40
  raise ValueError("Only numeric constants are allowed")
41
41
  num_node = getattr(ast, "Num", None)
42
42
  if num_node is not None and isinstance(n, num_node): # pragma: no cover
43
43
  numeric_value = getattr(n, "n", None)
44
- if isinstance(numeric_value, (int, float)):
44
+ if isinstance(numeric_value, int | float):
45
45
  return float(numeric_value)
46
46
  raise ValueError("Only numeric constants are allowed")
47
47
  if isinstance(n, ast.BinOp):
synth_ai/cli/demo.py CHANGED
@@ -8,13 +8,18 @@ CLI: interactive launcher for example demos and RL demo helpers.
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
+ import importlib
11
12
  import os
12
13
  import subprocess
13
14
  from pathlib import Path
15
+ from typing import Any, cast
14
16
 
15
17
  import click
18
+ from click.exceptions import Exit
16
19
 
17
- from synth_ai.demos.core import cli as demo_commands
20
+ demo_commands = cast(
21
+ Any, importlib.import_module("synth_ai.demos.core.cli")
22
+ )
18
23
 
19
24
 
20
25
  def _find_demo_scripts(root: Path) -> list[Path]:
@@ -29,7 +34,7 @@ def _run_demo_command(func, *args, **kwargs) -> None:
29
34
  try:
30
35
  result = func(*args, **kwargs)
31
36
  except SystemExit as exc: # pragma: no cover - defensive
32
- raise click.exceptions.Exit(exc.code or 1) from exc
37
+ raise Exit(exc.code or 1) from exc
33
38
 
34
39
  if result is None:
35
40
  return
@@ -39,7 +44,7 @@ def _run_demo_command(func, *args, **kwargs) -> None:
39
44
  except (TypeError, ValueError):
40
45
  return
41
46
  if code != 0:
42
- raise click.exceptions.Exit(code)
47
+ raise Exit(code)
43
48
 
44
49
 
45
50
  def register(cli):
@@ -106,10 +111,7 @@ def register(cli):
106
111
  # (prepare command removed; configure now prepares baseline TOML)
107
112
 
108
113
  # Help pyright understand dynamic Click group attributes
109
- from typing import Any
110
- from typing import cast as _cast
111
-
112
- _dg = _cast(Any, demo)
114
+ _dg = cast(Any, demo)
113
115
 
114
116
  @_dg.command("deploy")
115
117
  @click.option("--local", is_flag=True, help="Run local FastAPI instead of Modal deploy")
@@ -156,3 +158,8 @@ def register(cli):
156
158
  model=model,
157
159
  timeout=timeout,
158
160
  )
161
+
162
+ @cli.command("setup")
163
+ def setup_alias():
164
+ """Perform SDK handshake and write keys to .env."""
165
+ _run_demo_command(demo_commands.setup)
@@ -235,7 +235,7 @@ def view(url: str):
235
235
  """Launch the interactive TUI dashboard."""
236
236
  try:
237
237
  module = importlib.import_module(".tui.dashboard", __package__)
238
- synth_dashboard_cls = module.SynthDashboard
238
+ synth_dashboard_cls = getattr(module, "SynthDashboard")
239
239
  app = synth_dashboard_cls(db_url=url)
240
240
  app.run()
241
241
  except ImportError:
synth_ai/cli/rl_demo.py CHANGED
@@ -15,9 +15,13 @@ For convenience, dotted aliases are also exposed:
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
+ import importlib
19
+ from typing import Any, cast
20
+
18
21
  import click
22
+ from click.exceptions import Exit
19
23
 
20
- from synth_ai.demos.core import cli as demo_commands
24
+ demo_commands = cast(Any, importlib.import_module("synth_ai.demos.core.cli"))
21
25
 
22
26
 
23
27
  def _run_demo_command(func, *args, **kwargs) -> None:
@@ -26,7 +30,7 @@ def _run_demo_command(func, *args, **kwargs) -> None:
26
30
  try:
27
31
  result = func(*args, **kwargs)
28
32
  except SystemExit as exc: # pragma: no cover - defensive
29
- raise click.exceptions.Exit(exc.code or 1) from exc
33
+ raise Exit(exc.code or 1) from exc
30
34
 
31
35
  if result is None:
32
36
  return
@@ -35,7 +39,7 @@ def _run_demo_command(func, *args, **kwargs) -> None:
35
39
  except (TypeError, ValueError):
36
40
  return
37
41
  if code != 0:
38
- raise click.exceptions.Exit(code)
42
+ raise Exit(code)
39
43
 
40
44
 
41
45
  def register(cli):
@@ -44,10 +48,7 @@ def register(cli):
44
48
  """RL Demo commands (separate from legacy demo)."""
45
49
 
46
50
  # Help pyright understand dynamic Click group attributes
47
- from typing import Any
48
- from typing import cast as _cast
49
-
50
- _rlg = _cast(Any, rl_demo)
51
+ _rlg = cast(Any, rl_demo)
51
52
 
52
53
  @_rlg.command("setup")
53
54
  def rl_setup():