synth-ai 0.2.16__py3-none-any.whl → 0.2.17__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 (192) hide show
  1. examples/analyze_semantic_words.sh +2 -2
  2. examples/blog_posts/pokemon_vl/README.md +98 -0
  3. examples/blog_posts/pokemon_vl/configs/eval_qwen3_vl.toml +25 -0
  4. examples/blog_posts/pokemon_vl/configs/eval_rl_final.toml +24 -0
  5. examples/blog_posts/pokemon_vl/configs/filter_high_reward.toml +10 -0
  6. examples/blog_posts/pokemon_vl/configs/train_rl_from_sft.toml +42 -0
  7. examples/blog_posts/pokemon_vl/configs/train_sft_qwen4b_vl.toml +40 -0
  8. examples/blog_posts/warming_up_to_rl/README.md +158 -0
  9. examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b.toml +25 -0
  10. examples/blog_posts/warming_up_to_rl/configs/eval_groq_qwen32b.toml +25 -0
  11. examples/blog_posts/warming_up_to_rl/configs/eval_openai_gpt_oss_120b.toml +29 -0
  12. examples/blog_posts/warming_up_to_rl/configs/filter_high_reward_dataset.toml +10 -0
  13. examples/blog_posts/warming_up_to_rl/configs/train_rl_from_sft.toml +41 -0
  14. examples/blog_posts/warming_up_to_rl/configs/train_sft_qwen4b.toml +40 -0
  15. examples/dev/qwen3_32b_qlora_4xh100.toml +5 -0
  16. examples/multi_step/configs/crafter_rl_outcome.toml +1 -1
  17. examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +65 -107
  18. examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +1 -1
  19. examples/multi_step/configs/crafter_rl_stepwise_simple.toml +1 -1
  20. examples/multi_step/configs/crafter_rl_stepwise_simple_NEW_FORMAT.toml +105 -0
  21. examples/multi_step/configs/verilog_rl_lora.toml +80 -123
  22. examples/qwen_coder/configs/coder_lora_30b.toml +1 -3
  23. examples/qwen_coder/configs/coder_lora_4b.toml +4 -1
  24. examples/qwen_coder/configs/coder_lora_small.toml +1 -3
  25. examples/qwen_vl/README.md +10 -12
  26. examples/qwen_vl/SETUP_COMPLETE.md +7 -8
  27. examples/qwen_vl/VISION_TESTS_COMPLETE.md +2 -3
  28. examples/qwen_vl/collect_data_via_cli.md +76 -84
  29. examples/qwen_vl/collect_vision_traces.py +4 -4
  30. examples/qwen_vl/configs/crafter_rl_vision_qwen3vl4b.toml +40 -57
  31. examples/qwen_vl/configs/crafter_vlm_sft_example.toml +1 -2
  32. examples/qwen_vl/configs/eval_gpt4o_mini_vision.toml +20 -37
  33. examples/qwen_vl/configs/eval_gpt5nano_vision.toml +21 -40
  34. examples/qwen_vl/configs/eval_qwen3vl_vision.toml +26 -0
  35. examples/qwen_vl/configs/{filter_qwen2vl_sft.toml → filter_qwen3vl_sft.toml} +4 -5
  36. examples/qwen_vl/configs/filter_vision_sft.toml +2 -3
  37. examples/qwen_vl/crafter_qwen_vl_agent.py +5 -5
  38. examples/qwen_vl/run_vision_comparison.sh +6 -7
  39. examples/rl/README.md +5 -5
  40. examples/rl/configs/rl_from_base_qwen.toml +26 -1
  41. examples/rl/configs/rl_from_base_qwen17.toml +5 -2
  42. examples/rl/task_app/README.md +1 -2
  43. examples/rl/task_app/math_single_step.py +2 -2
  44. examples/run_crafter_demo.sh +2 -2
  45. examples/sft/README.md +1 -1
  46. examples/sft/configs/crafter_fft_qwen0p6b.toml +4 -1
  47. examples/sft/configs/crafter_lora_qwen0p6b.toml +4 -1
  48. examples/swe/task_app/README.md +32 -2
  49. examples/swe/task_app/grpo_swe_mini.py +4 -0
  50. examples/swe/task_app/hosted/envs/crafter/react_agent.py +1 -1
  51. examples/swe/task_app/hosted/envs/mini_swe/environment.py +37 -10
  52. examples/swe/task_app/hosted/inference/openai_client.py +4 -4
  53. examples/swe/task_app/morph_backend.py +178 -0
  54. examples/task_apps/crafter/task_app/README.md +1 -1
  55. examples/task_apps/crafter/task_app/grpo_crafter.py +66 -3
  56. examples/task_apps/crafter/task_app/grpo_crafter_task_app.py +1 -1
  57. examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/policy.py +4 -26
  58. examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/react_agent.py +1 -2
  59. examples/task_apps/crafter/task_app/synth_envs_hosted/inference/openai_client.py +17 -49
  60. examples/task_apps/crafter/task_app/synth_envs_hosted/policy_routes.py +13 -5
  61. examples/task_apps/crafter/task_app/synth_envs_hosted/rollout.py +15 -1
  62. examples/task_apps/enron/task_app/grpo_enron_task_app.py +1 -1
  63. examples/task_apps/math/README.md +1 -2
  64. examples/task_apps/pokemon_red/README.md +3 -4
  65. examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +6 -5
  66. examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +1 -2
  67. examples/task_apps/pokemon_red/task_app.py +36 -5
  68. examples/task_apps/sokoban/README.md +2 -3
  69. examples/task_apps/verilog/eval_groq_qwen32b.toml +12 -14
  70. examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +1 -1
  71. examples/vlm/configs/crafter_vlm_gpt4o.toml +4 -1
  72. examples/warming_up_to_rl/configs/crafter_fft.toml +4 -1
  73. examples/warming_up_to_rl/configs/crafter_fft_4b.toml +0 -2
  74. examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +2 -2
  75. examples/warming_up_to_rl/run_local_rollout_traced.py +1 -1
  76. examples/warming_up_to_rl/task_app/README.md +1 -1
  77. examples/warming_up_to_rl/task_app/grpo_crafter.py +134 -3
  78. examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +1 -1
  79. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +3 -27
  80. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +1 -1
  81. examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +4 -4
  82. examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +6 -3
  83. examples/workflows/math_rl/configs/rl_from_base_qwen.toml +27 -0
  84. examples/workflows/math_rl/configs/rl_from_base_qwen17.toml +5 -0
  85. synth_ai/api/train/builders.py +9 -3
  86. synth_ai/api/train/cli.py +125 -10
  87. synth_ai/api/train/configs/__init__.py +8 -1
  88. synth_ai/api/train/configs/rl.py +32 -7
  89. synth_ai/api/train/configs/sft.py +6 -2
  90. synth_ai/api/train/configs/shared.py +59 -2
  91. synth_ai/auth/credentials.py +119 -0
  92. synth_ai/cli/__init__.py +12 -4
  93. synth_ai/cli/commands/__init__.py +17 -0
  94. synth_ai/cli/commands/demo/__init__.py +6 -0
  95. synth_ai/cli/commands/demo/core.py +163 -0
  96. synth_ai/cli/commands/deploy/__init__.py +23 -0
  97. synth_ai/cli/commands/deploy/core.py +614 -0
  98. synth_ai/cli/commands/deploy/errors.py +72 -0
  99. synth_ai/cli/commands/deploy/validation.py +11 -0
  100. synth_ai/cli/commands/eval/__init__.py +19 -0
  101. synth_ai/cli/commands/eval/core.py +1109 -0
  102. synth_ai/cli/commands/eval/errors.py +81 -0
  103. synth_ai/cli/commands/eval/validation.py +133 -0
  104. synth_ai/cli/commands/filter/__init__.py +12 -0
  105. synth_ai/cli/commands/filter/core.py +388 -0
  106. synth_ai/cli/commands/filter/errors.py +55 -0
  107. synth_ai/cli/commands/filter/validation.py +77 -0
  108. synth_ai/cli/commands/help/__init__.py +177 -0
  109. synth_ai/cli/commands/help/core.py +73 -0
  110. synth_ai/cli/commands/status/__init__.py +64 -0
  111. synth_ai/cli/commands/status/client.py +192 -0
  112. synth_ai/cli/commands/status/config.py +92 -0
  113. synth_ai/cli/commands/status/errors.py +20 -0
  114. synth_ai/cli/commands/status/formatters.py +164 -0
  115. synth_ai/cli/commands/status/subcommands/__init__.py +9 -0
  116. synth_ai/cli/commands/status/subcommands/files.py +79 -0
  117. synth_ai/cli/commands/status/subcommands/jobs.py +334 -0
  118. synth_ai/cli/commands/status/subcommands/models.py +79 -0
  119. synth_ai/cli/commands/status/subcommands/runs.py +81 -0
  120. synth_ai/cli/commands/status/subcommands/summary.py +47 -0
  121. synth_ai/cli/commands/status/utils.py +114 -0
  122. synth_ai/cli/commands/train/__init__.py +53 -0
  123. synth_ai/cli/commands/train/core.py +21 -0
  124. synth_ai/cli/commands/train/errors.py +117 -0
  125. synth_ai/cli/commands/train/judge_schemas.py +199 -0
  126. synth_ai/cli/commands/train/judge_validation.py +304 -0
  127. synth_ai/cli/commands/train/validation.py +443 -0
  128. synth_ai/cli/demo.py +2 -162
  129. synth_ai/cli/deploy/__init__.py +28 -0
  130. synth_ai/cli/deploy/core.py +5 -0
  131. synth_ai/cli/deploy/errors.py +23 -0
  132. synth_ai/cli/deploy/validation.py +5 -0
  133. synth_ai/cli/eval/__init__.py +36 -0
  134. synth_ai/cli/eval/core.py +5 -0
  135. synth_ai/cli/eval/errors.py +31 -0
  136. synth_ai/cli/eval/validation.py +5 -0
  137. synth_ai/cli/filter/__init__.py +28 -0
  138. synth_ai/cli/filter/core.py +5 -0
  139. synth_ai/cli/filter/errors.py +23 -0
  140. synth_ai/cli/filter/validation.py +5 -0
  141. synth_ai/cli/modal_serve/__init__.py +12 -0
  142. synth_ai/cli/modal_serve/core.py +14 -0
  143. synth_ai/cli/modal_serve/errors.py +8 -0
  144. synth_ai/cli/modal_serve/validation.py +11 -0
  145. synth_ai/cli/serve/__init__.py +12 -0
  146. synth_ai/cli/serve/core.py +14 -0
  147. synth_ai/cli/serve/errors.py +8 -0
  148. synth_ai/cli/serve/validation.py +11 -0
  149. synth_ai/cli/setup.py +20 -265
  150. synth_ai/cli/status.py +7 -126
  151. synth_ai/cli/task_app_deploy.py +1 -10
  152. synth_ai/cli/task_app_modal_serve.py +4 -9
  153. synth_ai/cli/task_app_serve.py +4 -11
  154. synth_ai/cli/task_apps.py +58 -1487
  155. synth_ai/cli/train/__init__.py +12 -0
  156. synth_ai/cli/train/core.py +21 -0
  157. synth_ai/cli/train/errors.py +8 -0
  158. synth_ai/cli/train/validation.py +24 -0
  159. synth_ai/cli/train.py +1 -14
  160. synth_ai/demos/crafter/grpo_crafter_task_app.py +1 -1
  161. synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +1 -1
  162. synth_ai/environments/examples/red/engine.py +33 -12
  163. synth_ai/environments/examples/red/engine_helpers/reward_components.py +151 -179
  164. synth_ai/environments/examples/red/environment.py +26 -0
  165. synth_ai/environments/examples/red/trace_hooks_v3.py +168 -0
  166. synth_ai/http.py +12 -0
  167. synth_ai/judge_schemas.py +10 -11
  168. synth_ai/learning/rl/client.py +3 -1
  169. synth_ai/streaming/__init__.py +29 -0
  170. synth_ai/streaming/config.py +94 -0
  171. synth_ai/streaming/handlers.py +469 -0
  172. synth_ai/streaming/streamer.py +301 -0
  173. synth_ai/streaming/types.py +95 -0
  174. synth_ai/task/validators.py +2 -2
  175. synth_ai/tracing_v3/migration_helper.py +1 -2
  176. synth_ai/utils/env.py +25 -18
  177. synth_ai/utils/http.py +4 -1
  178. synth_ai/utils/modal.py +2 -2
  179. {synth_ai-0.2.16.dist-info → synth_ai-0.2.17.dist-info}/METADATA +8 -3
  180. {synth_ai-0.2.16.dist-info → synth_ai-0.2.17.dist-info}/RECORD +184 -109
  181. examples/qwen_vl/configs/eval_qwen2vl_vision.toml +0 -44
  182. synth_ai/cli/tui.py +0 -62
  183. synth_ai/tui/__init__.py +0 -5
  184. synth_ai/tui/__main__.py +0 -13
  185. synth_ai/tui/cli/__init__.py +0 -1
  186. synth_ai/tui/cli/query_experiments.py +0 -164
  187. synth_ai/tui/cli/query_experiments_v3.py +0 -164
  188. synth_ai/tui/dashboard.py +0 -911
  189. {synth_ai-0.2.16.dist-info → synth_ai-0.2.17.dist-info}/WHEEL +0 -0
  190. {synth_ai-0.2.16.dist-info → synth_ai-0.2.17.dist-info}/entry_points.txt +0 -0
  191. {synth_ai-0.2.16.dist-info → synth_ai-0.2.17.dist-info}/licenses/LICENSE +0 -0
  192. {synth_ai-0.2.16.dist-info → synth_ai-0.2.17.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,163 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ import os
5
+ import subprocess
6
+ from pathlib import Path
7
+ from typing import Any, cast
8
+
9
+ import click
10
+ from click.exceptions import Exit
11
+
12
+ __all__ = ["command", "register"]
13
+
14
+ _demo_cli = cast(Any, importlib.import_module("synth_ai.demos.core.cli"))
15
+
16
+
17
+ def _find_demo_scripts(root: Path) -> list[Path]:
18
+ if not root.exists():
19
+ return []
20
+ return sorted(path for path in root.rglob("run_demo.sh") if path.is_file())
21
+
22
+
23
+ def _run_demo_command(func: Any, *args: Any, **kwargs: Any) -> None:
24
+ """Invoke a demo command and map non-zero exits to Click exits."""
25
+
26
+ try:
27
+ result = func(*args, **kwargs)
28
+ except SystemExit as exc: # pragma: no cover - defensive shim
29
+ raise Exit(exc.code or 1) from exc
30
+
31
+ if result is None:
32
+ return
33
+
34
+ try:
35
+ code = int(result)
36
+ except (TypeError, ValueError):
37
+ return
38
+ if code != 0:
39
+ raise Exit(code)
40
+
41
+
42
+ @click.group(
43
+ "demo",
44
+ invoke_without_command=True,
45
+ help="Demo helpers for the math RL pipeline.",
46
+ )
47
+ @click.option(
48
+ "--force",
49
+ is_flag=True,
50
+ help="Overwrite existing files in the current directory when initializing demo assets.",
51
+ )
52
+ @click.option("--list", "list_only", is_flag=True, help="List available legacy demos and exit.")
53
+ @click.option("-f", "filter_term", default="", help="Filter legacy demos by substring.")
54
+ @click.pass_context
55
+ def command(ctx: click.Context, force: bool, list_only: bool, filter_term: str) -> None:
56
+ """Default command: initialize RL demo files into ./synth_demo/ (alias of `demo init`)."""
57
+ if ctx.invoked_subcommand is not None:
58
+ return
59
+
60
+ if list_only:
61
+ repo_root = Path(os.getcwd())
62
+ examples_dir = repo_root / "examples"
63
+ demos = _find_demo_scripts(examples_dir)
64
+ if filter_term:
65
+ term = filter_term.lower()
66
+ demos = [path for path in demos if term in str(path).lower()]
67
+
68
+ if not demos:
69
+ click.echo("No run_demo.sh scripts found under examples/.")
70
+ return
71
+
72
+ click.echo("Available demos:")
73
+ for idx, path in enumerate(demos, start=1):
74
+ click.echo(f" {idx}. {path.relative_to(repo_root)}")
75
+ click.echo("")
76
+
77
+ def _validate_choice(val: str) -> int:
78
+ try:
79
+ selection = int(val)
80
+ except Exception as err: # pragma: no cover - Click handles prompt errors
81
+ raise click.BadParameter("Enter a number from the list") from err
82
+ if selection < 1 or selection > len(demos):
83
+ raise click.BadParameter(f"Choose a number between 1 and {len(demos)}")
84
+ return selection
85
+
86
+ choice = click.prompt("Select a demo to run", value_proc=_validate_choice)
87
+ script = demos[choice - 1]
88
+
89
+ click.echo("")
90
+ click.echo(f"šŸš€ Running {script.relative_to(repo_root)}\n")
91
+
92
+ try:
93
+ subprocess.run(["bash", str(script)], check=True)
94
+ except subprocess.CalledProcessError as exc:
95
+ click.echo(f"āŒ Demo exited with non-zero status: {exc.returncode}")
96
+ except KeyboardInterrupt:
97
+ click.echo("\nšŸ›‘ Demo interrupted by user")
98
+ return
99
+
100
+ _run_demo_command(_demo_cli.init, force=force)
101
+
102
+
103
+ @command.command("deploy")
104
+ @click.option("--local", is_flag=True, help="Run the local FastAPI app instead of deploying to Modal.")
105
+ @click.option("--app", type=click.Path(), default=None, help="Path to Modal app.py for `uv run modal deploy`.")
106
+ @click.option("--name", type=str, default="synth-math-demo", help="Modal app name.")
107
+ @click.option(
108
+ "--script",
109
+ type=click.Path(),
110
+ default=None,
111
+ help="Path to deploy_task_app.sh (optional legacy helper).",
112
+ )
113
+ def demo_deploy(local: bool, app: str | None, name: str, script: str | None) -> None:
114
+ _run_demo_command(
115
+ _demo_cli.deploy,
116
+ local=local,
117
+ app=app,
118
+ name=name,
119
+ script=script,
120
+ )
121
+
122
+
123
+ @command.command("configure")
124
+ def demo_configure() -> None:
125
+ _run_demo_command(_demo_cli.run)
126
+
127
+
128
+ @command.command("setup")
129
+ def demo_setup() -> None:
130
+ _run_demo_command(_demo_cli.setup)
131
+
132
+
133
+ @command.command("run")
134
+ @click.option("--batch-size", type=int, default=None)
135
+ @click.option("--group-size", type=int, default=None)
136
+ @click.option("--model", type=str, default=None)
137
+ @click.option("--timeout", type=int, default=600)
138
+ def demo_run(
139
+ batch_size: int | None,
140
+ group_size: int | None,
141
+ model: str | None,
142
+ timeout: int,
143
+ ) -> None:
144
+ _run_demo_command(
145
+ _demo_cli.run,
146
+ batch_size=batch_size,
147
+ group_size=group_size,
148
+ model=model,
149
+ timeout=timeout,
150
+ )
151
+
152
+
153
+ @click.command("setup")
154
+ def setup_alias() -> None:
155
+ """Perform SDK handshake and write keys to .env."""
156
+ _run_demo_command(_demo_cli.setup)
157
+
158
+
159
+ def register(cli: click.Group) -> None:
160
+ """Attach the demo command group and related aliases to the CLI."""
161
+ cli.add_command(command)
162
+ cli.add_command(setup_alias)
163
+
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from .core import (
4
+ command,
5
+ get_command,
6
+ modal_serve_command,
7
+ register_task_app_commands,
8
+ run_modal_runtime,
9
+ run_uvicorn_runtime,
10
+ )
11
+ from .errors import DeployCliError
12
+ from .validation import validate_deploy_options
13
+
14
+ __all__ = [
15
+ "command",
16
+ "get_command",
17
+ "modal_serve_command",
18
+ "register_task_app_commands",
19
+ "run_modal_runtime",
20
+ "run_uvicorn_runtime",
21
+ "DeployCliError",
22
+ "validate_deploy_options",
23
+ ]