synth-ai 0.2.16__py3-none-any.whl ā 0.2.19__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.
- examples/analyze_semantic_words.sh +2 -2
- examples/baseline/banking77_baseline.py +204 -0
- examples/baseline/crafter_baseline.py +407 -0
- examples/baseline/pokemon_red_baseline.py +326 -0
- examples/baseline/simple_baseline.py +56 -0
- examples/baseline/warming_up_to_rl_baseline.py +239 -0
- examples/blog_posts/gepa/README.md +355 -0
- examples/blog_posts/gepa/configs/banking77_gepa_local.toml +95 -0
- examples/blog_posts/gepa/configs/banking77_gepa_test.toml +82 -0
- examples/blog_posts/gepa/configs/banking77_mipro_local.toml +52 -0
- examples/blog_posts/gepa/configs/hotpotqa_gepa_local.toml +59 -0
- examples/blog_posts/gepa/configs/hotpotqa_gepa_qwen.toml +36 -0
- examples/blog_posts/gepa/configs/hotpotqa_mipro_local.toml +53 -0
- examples/blog_posts/gepa/configs/hover_gepa_local.toml +59 -0
- examples/blog_posts/gepa/configs/hover_gepa_qwen.toml +36 -0
- examples/blog_posts/gepa/configs/hover_mipro_local.toml +53 -0
- examples/blog_posts/gepa/configs/ifbench_gepa_local.toml +59 -0
- examples/blog_posts/gepa/configs/ifbench_gepa_qwen.toml +36 -0
- examples/blog_posts/gepa/configs/ifbench_mipro_local.toml +53 -0
- examples/blog_posts/gepa/configs/pupa_gepa_local.toml +60 -0
- examples/blog_posts/gepa/configs/pupa_mipro_local.toml +54 -0
- examples/blog_posts/gepa/deploy_banking77_task_app.sh +41 -0
- examples/blog_posts/gepa/gepa_baseline.py +204 -0
- examples/blog_posts/gepa/query_prompts_example.py +97 -0
- examples/blog_posts/gepa/run_gepa_banking77.sh +87 -0
- examples/blog_posts/gepa/task_apps.py +105 -0
- examples/blog_posts/gepa/test_gepa_local.sh +67 -0
- examples/blog_posts/gepa/verify_banking77_setup.sh +123 -0
- examples/blog_posts/pokemon_vl/README.md +98 -0
- examples/blog_posts/pokemon_vl/configs/eval_gpt5nano.toml +26 -0
- examples/blog_posts/pokemon_vl/configs/eval_qwen3_vl.toml +27 -0
- examples/blog_posts/pokemon_vl/configs/eval_rl_final.toml +24 -0
- examples/blog_posts/pokemon_vl/configs/filter_high_reward.toml +10 -0
- examples/blog_posts/pokemon_vl/configs/train_rl_from_sft.toml +43 -0
- examples/blog_posts/pokemon_vl/configs/train_sft_qwen4b_vl.toml +40 -0
- examples/blog_posts/pokemon_vl/extract_images.py +239 -0
- examples/blog_posts/pokemon_vl/pokemon_vl_baseline.py +326 -0
- examples/blog_posts/pokemon_vl/run_eval_extract_images.py +209 -0
- examples/blog_posts/pokemon_vl/run_qwen_eval_extract_images.py +212 -0
- examples/blog_posts/pokemon_vl/text_box_analysis.md +106 -0
- examples/blog_posts/warming_up_to_rl/ARCHITECTURE.md +195 -0
- examples/blog_posts/warming_up_to_rl/FINAL_TEST_RESULTS.md +127 -0
- examples/blog_posts/warming_up_to_rl/INFERENCE_SUCCESS.md +132 -0
- examples/blog_posts/warming_up_to_rl/README.md +158 -0
- examples/blog_posts/warming_up_to_rl/SMOKE_TESTING.md +164 -0
- examples/blog_posts/warming_up_to_rl/SMOKE_TEST_COMPLETE.md +253 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_baseline_qwen32b_10x20.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b_10x20.toml +26 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_groq_qwen32b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_openai_gpt_oss_120b.toml +29 -0
- examples/blog_posts/warming_up_to_rl/configs/filter_high_reward_dataset.toml +10 -0
- examples/blog_posts/warming_up_to_rl/configs/smoke_test.toml +75 -0
- examples/blog_posts/warming_up_to_rl/configs/train_rl_from_sft.toml +91 -0
- examples/blog_posts/warming_up_to_rl/configs/train_sft_qwen4b.toml +40 -0
- examples/blog_posts/warming_up_to_rl/warming_up_to_rl_baseline.py +187 -0
- examples/dev/qwen3_32b_qlora_4xh100.toml +5 -0
- examples/multi_step/configs/VERILOG_REWARDS.md +4 -0
- examples/multi_step/configs/VERILOG_RL_CHECKLIST.md +4 -0
- examples/multi_step/configs/crafter_rl_outcome.toml +2 -1
- examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +65 -107
- examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +2 -1
- examples/multi_step/configs/crafter_rl_stepwise_simple.toml +2 -1
- examples/multi_step/configs/crafter_rl_stepwise_simple_NEW_FORMAT.toml +105 -0
- examples/multi_step/configs/verilog_rl_lora.toml +80 -123
- examples/qwen_coder/configs/coder_lora_30b.toml +1 -3
- examples/qwen_coder/configs/coder_lora_4b.toml +4 -1
- examples/qwen_coder/configs/coder_lora_small.toml +1 -3
- examples/qwen_vl/README.md +10 -12
- examples/qwen_vl/SETUP_COMPLETE.md +7 -8
- examples/qwen_vl/VISION_TESTS_COMPLETE.md +2 -3
- examples/qwen_vl/collect_data_via_cli.md +76 -84
- examples/qwen_vl/collect_vision_traces.py +4 -4
- examples/qwen_vl/configs/crafter_rl_vision_qwen3vl4b.toml +40 -57
- examples/qwen_vl/configs/crafter_vlm_sft_example.toml +1 -2
- examples/qwen_vl/configs/eval_gpt4o_mini_vision.toml +20 -37
- examples/qwen_vl/configs/eval_gpt5nano_vision.toml +21 -40
- examples/qwen_vl/configs/eval_qwen3vl_vision.toml +26 -0
- examples/qwen_vl/configs/{filter_qwen2vl_sft.toml ā filter_qwen3vl_sft.toml} +4 -5
- examples/qwen_vl/configs/filter_vision_sft.toml +2 -3
- examples/qwen_vl/crafter_qwen_vl_agent.py +5 -5
- examples/qwen_vl/run_vision_comparison.sh +6 -7
- examples/rl/README.md +5 -5
- examples/rl/configs/rl_from_base_qwen.toml +26 -1
- examples/rl/configs/rl_from_base_qwen17.toml +6 -2
- examples/rl/task_app/README.md +1 -2
- examples/rl/task_app/math_single_step.py +2 -2
- examples/run_crafter_demo.sh +2 -2
- examples/sft/README.md +1 -1
- examples/sft/configs/crafter_fft_qwen0p6b.toml +4 -1
- examples/sft/configs/crafter_lora_qwen0p6b.toml +4 -1
- examples/swe/task_app/README.md +32 -2
- examples/swe/task_app/grpo_swe_mini.py +4 -0
- examples/swe/task_app/hosted/envs/crafter/react_agent.py +1 -1
- examples/swe/task_app/hosted/envs/mini_swe/environment.py +37 -10
- examples/swe/task_app/hosted/inference/openai_client.py +4 -38
- examples/swe/task_app/hosted/policy_routes.py +17 -0
- examples/swe/task_app/hosted/rollout.py +4 -2
- examples/swe/task_app/morph_backend.py +178 -0
- examples/task_apps/banking77/__init__.py +6 -0
- examples/task_apps/banking77/banking77_task_app.py +841 -0
- examples/task_apps/banking77/deploy_wrapper.py +46 -0
- examples/task_apps/crafter/CREATE_SFT_DATASET.md +4 -0
- examples/task_apps/crafter/FILTER_COMMAND_STATUS.md +4 -0
- examples/task_apps/crafter/FILTER_COMMAND_SUCCESS.md +4 -0
- examples/task_apps/crafter/task_app/README.md +1 -1
- examples/task_apps/crafter/task_app/grpo_crafter.py +90 -5
- examples/task_apps/crafter/task_app/grpo_crafter_task_app.py +1 -1
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/policy.py +4 -26
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/react_agent.py +1 -2
- examples/task_apps/crafter/task_app/synth_envs_hosted/hosted_app.py +49 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/openai_client.py +372 -107
- examples/task_apps/crafter/task_app/synth_envs_hosted/policy_routes.py +81 -12
- examples/task_apps/crafter/task_app/synth_envs_hosted/rollout.py +82 -11
- examples/task_apps/crafter/task_app/synth_envs_hosted/utils.py +194 -1
- examples/task_apps/enron/task_app/grpo_enron_task_app.py +1 -1
- examples/task_apps/gepa_benchmarks/__init__.py +7 -0
- examples/task_apps/gepa_benchmarks/common.py +260 -0
- examples/task_apps/gepa_benchmarks/hotpotqa_task_app.py +507 -0
- examples/task_apps/gepa_benchmarks/hover_task_app.py +436 -0
- examples/task_apps/gepa_benchmarks/ifbench_task_app.py +563 -0
- examples/task_apps/gepa_benchmarks/pupa_task_app.py +460 -0
- examples/task_apps/math/README.md +1 -2
- examples/task_apps/pokemon_red/README.md +3 -4
- examples/task_apps/pokemon_red/README_IMAGE_ONLY_EVAL.md +4 -0
- examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +6 -5
- examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +1 -2
- examples/task_apps/pokemon_red/task_app.py +288 -39
- examples/task_apps/sokoban/README.md +2 -3
- examples/task_apps/verilog/eval_groq_qwen32b.toml +12 -14
- examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +1 -1
- examples/vlm/configs/crafter_vlm_gpt4o.toml +4 -1
- examples/warming_up_to_rl/configs/crafter_fft.toml +4 -1
- examples/warming_up_to_rl/configs/crafter_fft_4b.toml +0 -2
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +3 -2
- examples/warming_up_to_rl/run_local_rollout_traced.py +1 -1
- examples/warming_up_to_rl/task_app/README.md +1 -1
- examples/warming_up_to_rl/task_app/grpo_crafter.py +185 -5
- examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +3 -27
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +1 -1
- examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +49 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +156 -45
- examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +37 -4
- examples/warming_up_to_rl/task_app/synth_envs_hosted/rollout.py +33 -3
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +67 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen.toml +27 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen17.toml +6 -0
- synth_ai/api/train/builders.py +99 -4
- synth_ai/api/train/cli.py +516 -26
- synth_ai/api/train/config_finder.py +13 -2
- synth_ai/api/train/configs/__init__.py +23 -2
- synth_ai/api/train/configs/prompt_learning.py +442 -0
- synth_ai/api/train/configs/rl.py +61 -7
- synth_ai/api/train/configs/sft.py +6 -2
- synth_ai/api/train/configs/shared.py +59 -2
- synth_ai/api/train/task_app.py +1 -1
- synth_ai/api/train/validators.py +277 -0
- synth_ai/auth/credentials.py +119 -0
- synth_ai/baseline/__init__.py +25 -0
- synth_ai/baseline/config.py +209 -0
- synth_ai/baseline/discovery.py +214 -0
- synth_ai/baseline/execution.py +146 -0
- synth_ai/cli/__init__.py +94 -18
- synth_ai/cli/__main__.py +0 -0
- synth_ai/cli/claude.py +70 -0
- synth_ai/cli/codex.py +84 -0
- synth_ai/cli/commands/__init__.py +18 -0
- synth_ai/cli/commands/baseline/__init__.py +12 -0
- synth_ai/cli/commands/baseline/core.py +637 -0
- synth_ai/cli/commands/baseline/list.py +93 -0
- synth_ai/cli/commands/demo/__init__.py +6 -0
- synth_ai/cli/commands/demo/core.py +163 -0
- synth_ai/cli/commands/eval/__init__.py +19 -0
- synth_ai/cli/commands/eval/core.py +1112 -0
- synth_ai/cli/commands/eval/errors.py +81 -0
- synth_ai/cli/commands/eval/validation.py +133 -0
- synth_ai/cli/commands/filter/__init__.py +12 -0
- synth_ai/cli/commands/filter/core.py +424 -0
- synth_ai/cli/commands/filter/errors.py +55 -0
- synth_ai/cli/commands/filter/validation.py +77 -0
- synth_ai/cli/commands/help/__init__.py +177 -0
- synth_ai/cli/commands/help/core.py +72 -0
- synth_ai/cli/commands/smoke/__init__.py +7 -0
- synth_ai/cli/commands/smoke/core.py +1436 -0
- synth_ai/cli/commands/status/__init__.py +64 -0
- synth_ai/cli/commands/status/client.py +192 -0
- synth_ai/cli/commands/status/config.py +92 -0
- synth_ai/cli/commands/status/errors.py +20 -0
- synth_ai/cli/commands/status/formatters.py +164 -0
- synth_ai/cli/commands/status/subcommands/__init__.py +9 -0
- synth_ai/cli/commands/status/subcommands/files.py +79 -0
- synth_ai/cli/commands/status/subcommands/jobs.py +334 -0
- synth_ai/cli/commands/status/subcommands/models.py +79 -0
- synth_ai/cli/commands/status/subcommands/pricing.py +22 -0
- synth_ai/cli/commands/status/subcommands/runs.py +81 -0
- synth_ai/cli/commands/status/subcommands/summary.py +47 -0
- synth_ai/cli/commands/status/subcommands/usage.py +203 -0
- synth_ai/cli/commands/status/utils.py +114 -0
- synth_ai/cli/commands/train/__init__.py +53 -0
- synth_ai/cli/commands/train/core.py +21 -0
- synth_ai/cli/commands/train/errors.py +117 -0
- synth_ai/cli/commands/train/judge_schemas.py +200 -0
- synth_ai/cli/commands/train/judge_validation.py +305 -0
- synth_ai/cli/commands/train/validation.py +386 -0
- synth_ai/cli/demo.py +30 -158
- synth_ai/cli/deploy/__init__.py +43 -0
- synth_ai/cli/deploy.py +162 -0
- synth_ai/cli/eval/__init__.py +36 -0
- synth_ai/cli/eval/core.py +5 -0
- synth_ai/cli/eval/errors.py +31 -0
- synth_ai/cli/eval/validation.py +5 -0
- synth_ai/cli/filter/__init__.py +28 -0
- synth_ai/cli/filter/core.py +5 -0
- synth_ai/cli/filter/errors.py +23 -0
- synth_ai/cli/filter/validation.py +5 -0
- synth_ai/cli/legacy_root_backup.py +14 -8
- synth_ai/cli/modal_serve/__init__.py +12 -0
- synth_ai/cli/modal_serve/core.py +14 -0
- synth_ai/cli/modal_serve/errors.py +8 -0
- synth_ai/cli/modal_serve/validation.py +11 -0
- synth_ai/cli/opencode.py +107 -0
- synth_ai/cli/root.py +9 -5
- synth_ai/cli/serve/__init__.py +12 -0
- synth_ai/cli/serve/core.py +14 -0
- synth_ai/cli/serve/errors.py +8 -0
- synth_ai/cli/serve/validation.py +11 -0
- synth_ai/cli/setup.py +20 -265
- synth_ai/cli/status.py +7 -126
- synth_ai/cli/task_app_deploy.py +1 -10
- synth_ai/cli/task_app_modal_serve.py +4 -9
- synth_ai/cli/task_app_serve.py +4 -11
- synth_ai/cli/task_apps.py +51 -1480
- synth_ai/cli/train/__init__.py +12 -0
- synth_ai/cli/train/core.py +21 -0
- synth_ai/cli/train/errors.py +8 -0
- synth_ai/cli/train/validation.py +24 -0
- synth_ai/cli/train.py +1 -14
- synth_ai/demos/crafter/grpo_crafter_task_app.py +1 -1
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +1 -1
- synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +7 -4
- synth_ai/environments/examples/crafter_classic/engine_serialization_patch_v3.py +9 -5
- synth_ai/environments/examples/crafter_classic/world_config_patch_simple.py +4 -3
- synth_ai/environments/examples/red/engine.py +33 -12
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +151 -179
- synth_ai/environments/examples/red/environment.py +26 -0
- synth_ai/environments/examples/red/trace_hooks_v3.py +168 -0
- synth_ai/http.py +12 -0
- synth_ai/judge_schemas.py +10 -10
- synth_ai/learning/__init__.py +10 -0
- synth_ai/learning/prompt_learning_client.py +276 -0
- synth_ai/learning/prompt_learning_types.py +184 -0
- synth_ai/learning/rl/client.py +3 -1
- synth_ai/pricing/__init__.py +2 -0
- synth_ai/pricing/model_pricing.py +57 -0
- synth_ai/streaming/__init__.py +29 -0
- synth_ai/streaming/config.py +94 -0
- synth_ai/streaming/handlers.py +518 -0
- synth_ai/streaming/streamer.py +320 -0
- synth_ai/streaming/types.py +95 -0
- synth_ai/task/apps/__init__.py +1 -0
- synth_ai/task/config.py +2 -0
- synth_ai/task/tracing_utils.py +25 -25
- synth_ai/task/validators.py +45 -9
- synth_ai/task_app_cfgs.py +21 -0
- synth_ai/tracing_v3/config.py +162 -19
- synth_ai/tracing_v3/constants.py +1 -1
- synth_ai/tracing_v3/db_config.py +24 -38
- synth_ai/tracing_v3/migration_helper.py +1 -2
- synth_ai/tracing_v3/storage/config.py +47 -13
- synth_ai/tracing_v3/storage/factory.py +3 -3
- synth_ai/tracing_v3/turso/daemon.py +113 -11
- synth_ai/tracing_v3/turso/native_manager.py +92 -16
- synth_ai/types.py +8 -0
- synth_ai/urls.py +11 -0
- synth_ai/utils/__init__.py +30 -1
- synth_ai/utils/agents.py +74 -0
- synth_ai/utils/bin.py +39 -0
- synth_ai/utils/cli.py +149 -5
- synth_ai/utils/env.py +40 -33
- synth_ai/utils/http.py +4 -1
- synth_ai/utils/json.py +72 -0
- synth_ai/utils/modal.py +285 -3
- synth_ai/utils/paths.py +48 -0
- synth_ai/utils/uvicorn.py +113 -0
- {synth_ai-0.2.16.dist-info ā synth_ai-0.2.19.dist-info}/METADATA +109 -6
- {synth_ai-0.2.16.dist-info ā synth_ai-0.2.19.dist-info}/RECORD +291 -142
- examples/qwen_vl/configs/eval_qwen2vl_vision.toml +0 -44
- synth_ai/cli/tui.py +0 -62
- synth_ai/tui/__init__.py +0 -5
- synth_ai/tui/__main__.py +0 -13
- synth_ai/tui/cli/__init__.py +0 -1
- synth_ai/tui/cli/query_experiments.py +0 -164
- synth_ai/tui/cli/query_experiments_v3.py +0 -164
- synth_ai/tui/dashboard.py +0 -911
- {synth_ai-0.2.16.dist-info ā synth_ai-0.2.19.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.16.dist-info ā synth_ai-0.2.19.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.16.dist-info ā synth_ai-0.2.19.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.16.dist-info ā synth_ai-0.2.19.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""List command for baseline discovery."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
from synth_ai.baseline.config import BaselineConfig
|
|
10
|
+
from synth_ai.baseline.discovery import (
|
|
11
|
+
BaselineChoice,
|
|
12
|
+
discover_baseline_files,
|
|
13
|
+
load_baseline_config_from_file,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command("list")
|
|
18
|
+
@click.option(
|
|
19
|
+
"--tag",
|
|
20
|
+
multiple=True,
|
|
21
|
+
help="Filter baselines by tag (can be specified multiple times)",
|
|
22
|
+
)
|
|
23
|
+
@click.option(
|
|
24
|
+
"--metadata",
|
|
25
|
+
type=str,
|
|
26
|
+
help="Filter by metadata key-value pair (format: key=value)",
|
|
27
|
+
)
|
|
28
|
+
@click.option(
|
|
29
|
+
"--verbose",
|
|
30
|
+
is_flag=True,
|
|
31
|
+
help="Show detailed information about each baseline",
|
|
32
|
+
)
|
|
33
|
+
def list_command(tag: tuple[str, ...], metadata: Optional[str], verbose: bool) -> None:
|
|
34
|
+
"""List all available baseline files."""
|
|
35
|
+
search_roots = [Path.cwd()]
|
|
36
|
+
choices = discover_baseline_files(search_roots)
|
|
37
|
+
|
|
38
|
+
if not choices:
|
|
39
|
+
click.echo("No baseline files found.", err=True)
|
|
40
|
+
click.echo("Create baseline files in examples/baseline/ or */*_baseline.py")
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
# Load configs for filtering
|
|
44
|
+
configs: list[tuple[BaselineChoice, BaselineConfig]] = []
|
|
45
|
+
for choice in choices:
|
|
46
|
+
try:
|
|
47
|
+
config = load_baseline_config_from_file(choice.baseline_id, choice.path)
|
|
48
|
+
configs.append((choice, config))
|
|
49
|
+
except Exception as e:
|
|
50
|
+
if verbose:
|
|
51
|
+
click.echo(f"Warning: Could not load {choice.baseline_id}: {e}", err=True)
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
# Apply filters
|
|
55
|
+
filtered_configs = configs
|
|
56
|
+
|
|
57
|
+
if tag:
|
|
58
|
+
tag_set = {t.lower() for t in tag}
|
|
59
|
+
filtered_configs = [
|
|
60
|
+
(c, config) for c, config in filtered_configs
|
|
61
|
+
if any(config.matches_tag(t) for t in tag_set)
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
if metadata:
|
|
65
|
+
if "=" not in metadata:
|
|
66
|
+
raise click.ClickException("--metadata must be in format key=value")
|
|
67
|
+
key, value = metadata.split("=", 1)
|
|
68
|
+
filtered_configs = [
|
|
69
|
+
(c, config) for c, config in filtered_configs
|
|
70
|
+
if config.matches_metadata(key.strip(), value.strip())
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
if not filtered_configs:
|
|
74
|
+
click.echo("No baselines match the specified filters.")
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
# Display results
|
|
78
|
+
click.echo(f"Found {len(filtered_configs)} baseline(s):\n")
|
|
79
|
+
|
|
80
|
+
for choice, config in filtered_configs:
|
|
81
|
+
click.echo(f" {config.baseline_id}")
|
|
82
|
+
click.echo(f" Name: {config.name}")
|
|
83
|
+
if config.description:
|
|
84
|
+
click.echo(f" Description: {config.description}")
|
|
85
|
+
if config.tags:
|
|
86
|
+
click.echo(f" Tags: {', '.join(config.tags)}")
|
|
87
|
+
click.echo(f" Splits: {', '.join(config.splits.keys())}")
|
|
88
|
+
if verbose:
|
|
89
|
+
click.echo(f" Path: {choice.path}")
|
|
90
|
+
if config.metadata:
|
|
91
|
+
click.echo(f" Metadata: {config.metadata}")
|
|
92
|
+
click.echo()
|
|
93
|
+
|
|
@@ -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,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .errors import EvalCliError
|
|
4
|
+
from .validation import validate_eval_options
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"command",
|
|
8
|
+
"get_command",
|
|
9
|
+
"EvalCliError",
|
|
10
|
+
"validate_eval_options",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def __getattr__(name: str):
|
|
15
|
+
if name in {"command", "get_command"}:
|
|
16
|
+
from .core import command, get_command
|
|
17
|
+
|
|
18
|
+
return command if name == "command" else get_command
|
|
19
|
+
raise AttributeError(name)
|