synth-ai 0.2.8.dev2__py3-none-any.whl → 0.4.3__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.
- synth_ai/__init__.py +44 -24
- synth_ai/__main__.py +30 -3
- synth_ai/cli/__init__.py +103 -48
- synth_ai/cli/__main__.py +42 -0
- synth_ai/cli/_internal/__init__.py +5 -0
- synth_ai/cli/_internal/modal_wrapper.py +31 -0
- synth_ai/cli/_internal/storage.py +20 -0
- synth_ai/cli/_internal/typer_patch.py +47 -0
- synth_ai/cli/_internal/validate_task_app.py +29 -0
- synth_ai/cli/agents/__init__.py +17 -0
- synth_ai/cli/agents/claude.py +77 -0
- synth_ai/cli/agents/codex.py +265 -0
- synth_ai/cli/agents/opencode.py +253 -0
- synth_ai/cli/commands/__init__.py +18 -0
- synth_ai/cli/commands/artifacts/__init__.py +13 -0
- synth_ai/cli/commands/artifacts/client.py +119 -0
- synth_ai/cli/commands/artifacts/config.py +57 -0
- synth_ai/cli/commands/artifacts/core.py +24 -0
- synth_ai/cli/commands/artifacts/download.py +188 -0
- synth_ai/cli/commands/artifacts/export.py +186 -0
- synth_ai/cli/commands/artifacts/list.py +156 -0
- synth_ai/cli/commands/artifacts/parsing.py +250 -0
- synth_ai/cli/commands/artifacts/show.py +336 -0
- synth_ai/cli/commands/demo/__init__.py +3 -0
- synth_ai/cli/commands/demo/core.py +153 -0
- synth_ai/cli/commands/eval/__init__.py +10 -0
- synth_ai/cli/commands/eval/config.py +338 -0
- synth_ai/cli/commands/eval/core.py +256 -0
- synth_ai/cli/commands/eval/runner.py +704 -0
- synth_ai/cli/commands/eval/validation.py +60 -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 +185 -0
- synth_ai/cli/commands/help/core.py +72 -0
- synth_ai/cli/commands/scan/__init__.py +19 -0
- synth_ai/cli/commands/scan/cloudflare_scanner.py +403 -0
- synth_ai/cli/commands/scan/core.py +344 -0
- synth_ai/cli/commands/scan/health_checker.py +242 -0
- synth_ai/cli/commands/scan/local_scanner.py +278 -0
- synth_ai/cli/commands/scan/models.py +83 -0
- synth_ai/cli/commands/smoke/__init__.py +7 -0
- synth_ai/cli/commands/smoke/core.py +1428 -0
- synth_ai/cli/commands/status/__init__.py +3 -0
- synth_ai/cli/commands/status/client.py +91 -0
- synth_ai/cli/commands/status/config.py +12 -0
- synth_ai/cli/commands/status/errors.py +11 -0
- synth_ai/cli/commands/status/subcommands/__init__.py +3 -0
- synth_ai/cli/commands/status/subcommands/config.py +13 -0
- synth_ai/cli/commands/status/subcommands/files.py +34 -0
- synth_ai/cli/commands/status/subcommands/jobs.py +51 -0
- synth_ai/cli/commands/status/subcommands/models.py +35 -0
- synth_ai/cli/commands/status/subcommands/runs.py +34 -0
- synth_ai/cli/commands/status/subcommands/session.py +77 -0
- synth_ai/cli/commands/status/subcommands/summary.py +39 -0
- synth_ai/cli/commands/status/subcommands/utils.py +41 -0
- synth_ai/cli/commands/status/utils.py +23 -0
- synth_ai/cli/commands/train/__init__.py +53 -0
- synth_ai/cli/commands/train/core.py +22 -0
- synth_ai/cli/commands/train/errors.py +117 -0
- synth_ai/cli/commands/train/judge_schemas.py +201 -0
- synth_ai/cli/commands/train/judge_validation.py +305 -0
- synth_ai/cli/commands/train/prompt_learning_validation.py +633 -0
- synth_ai/cli/commands/train/validation.py +392 -0
- synth_ai/cli/demo_apps/__init__.py +10 -0
- synth_ai/cli/demo_apps/core/__init__.py +28 -0
- synth_ai/{demos → cli/demo_apps}/core/cli.py +783 -441
- synth_ai/cli/demo_apps/crafter/__init__.py +1 -0
- synth_ai/cli/demo_apps/crafter/crafter_fft_4b.toml +55 -0
- synth_ai/cli/demo_apps/crafter/grpo_crafter_task_app.py +186 -0
- synth_ai/cli/demo_apps/crafter/rl_from_base_qwen4b.toml +74 -0
- synth_ai/cli/demo_apps/demo_registry.py +176 -0
- synth_ai/cli/demo_apps/demo_task_apps/__init__.py +7 -0
- synth_ai/{demos → cli/demo_apps}/demo_task_apps/core.py +75 -37
- synth_ai/cli/demo_apps/demo_task_apps/crafter/__init__.py +1 -0
- synth_ai/cli/demo_apps/demo_task_apps/crafter/configs/crafter_fft_4b.toml +53 -0
- synth_ai/cli/demo_apps/demo_task_apps/crafter/configs/rl_from_base_qwen4b.toml +73 -0
- synth_ai/cli/demo_apps/demo_task_apps/crafter/grpo_crafter_task_app.py +185 -0
- synth_ai/{demos → cli/demo_apps}/demo_task_apps/math/_common.py +1 -2
- synth_ai/{demos → cli/demo_apps}/demo_task_apps/math/app.py +2 -1
- synth_ai/cli/demo_apps/demo_task_apps/math/config.toml +73 -0
- synth_ai/{demos → cli/demo_apps}/demo_task_apps/math/deploy_modal.py +3 -6
- synth_ai/cli/demo_apps/demo_task_apps/math/modal_task_app.py +738 -0
- synth_ai/cli/demo_apps/demo_task_apps/math/task_app_entry.py +39 -0
- synth_ai/cli/demo_apps/math/__init__.py +1 -0
- synth_ai/cli/demo_apps/math/_common.py +16 -0
- synth_ai/cli/demo_apps/math/app.py +38 -0
- synth_ai/cli/demo_apps/math/config.toml +75 -0
- synth_ai/cli/demo_apps/math/deploy_modal.py +54 -0
- synth_ai/cli/demo_apps/math/modal_task_app.py +698 -0
- synth_ai/cli/demo_apps/math/task_app_entry.py +53 -0
- synth_ai/cli/demo_apps/mipro/main.py +271 -0
- synth_ai/cli/demo_apps/mipro/task_app.py +922 -0
- synth_ai/cli/demo_apps/mipro/train_cfg.toml +92 -0
- synth_ai/cli/demos/__init__.py +12 -0
- synth_ai/cli/demos/demo.py +32 -0
- synth_ai/cli/demos/rl_demo.py +254 -0
- synth_ai/cli/deploy.py +216 -0
- synth_ai/cli/infra/__init__.py +14 -0
- synth_ai/cli/{balance.py → infra/balance.py} +16 -4
- synth_ai/cli/infra/mcp.py +35 -0
- synth_ai/cli/infra/modal_app.py +36 -0
- synth_ai/cli/infra/setup.py +69 -0
- synth_ai/cli/infra/status.py +16 -0
- synth_ai/cli/infra/turso.py +77 -0
- synth_ai/cli/lib/__init__.py +10 -0
- synth_ai/cli/lib/agents.py +76 -0
- synth_ai/cli/lib/apps/modal_app.py +101 -0
- synth_ai/cli/lib/apps/task_app.py +642 -0
- synth_ai/cli/lib/bin.py +39 -0
- synth_ai/cli/lib/env.py +375 -0
- synth_ai/cli/lib/errors.py +85 -0
- synth_ai/cli/lib/modal.py +315 -0
- synth_ai/cli/lib/plotting.py +126 -0
- synth_ai/cli/lib/prompt_args.py +39 -0
- synth_ai/cli/lib/prompts.py +284 -0
- synth_ai/cli/lib/sqld.py +122 -0
- synth_ai/cli/lib/task_app_discovery.py +884 -0
- synth_ai/cli/lib/task_app_env.py +295 -0
- synth_ai/cli/lib/train_cfgs.py +300 -0
- synth_ai/cli/lib/tunnel_records.py +207 -0
- synth_ai/cli/local/__init__.py +14 -0
- synth_ai/cli/local/experiment_queue/__init__.py +72 -0
- synth_ai/cli/local/experiment_queue/api_schemas.py +221 -0
- synth_ai/cli/local/experiment_queue/celery_app.py +208 -0
- synth_ai/cli/local/experiment_queue/config.py +128 -0
- synth_ai/cli/local/experiment_queue/config_utils.py +272 -0
- synth_ai/cli/local/experiment_queue/database.py +175 -0
- synth_ai/cli/local/experiment_queue/dispatcher.py +119 -0
- synth_ai/cli/local/experiment_queue/models.py +231 -0
- synth_ai/cli/local/experiment_queue/progress_info.py +160 -0
- synth_ai/cli/local/experiment_queue/results.py +373 -0
- synth_ai/cli/local/experiment_queue/schemas.py +131 -0
- synth_ai/cli/local/experiment_queue/service.py +344 -0
- synth_ai/cli/local/experiment_queue/status.py +372 -0
- synth_ai/cli/local/experiment_queue/status_tracker.py +360 -0
- synth_ai/cli/local/experiment_queue/tasks.py +1984 -0
- synth_ai/cli/local/experiment_queue/trace_storage.py +65 -0
- synth_ai/cli/local/experiment_queue/validation.py +157 -0
- synth_ai/cli/local/session/__init__.py +92 -0
- synth_ai/cli/local/session/client.py +383 -0
- synth_ai/cli/local/session/constants.py +63 -0
- synth_ai/cli/local/session/exceptions.py +105 -0
- synth_ai/cli/local/session/manager.py +139 -0
- synth_ai/cli/local/session/models.py +89 -0
- synth_ai/cli/local/session/query.py +110 -0
- synth_ai/cli/root.py +150 -108
- synth_ai/cli/task_apps/__init__.py +37 -0
- synth_ai/cli/task_apps/commands.py +3145 -0
- synth_ai/cli/task_apps/deploy.py +7 -0
- synth_ai/cli/task_apps/list.py +26 -0
- synth_ai/cli/task_apps/main.py +36 -0
- synth_ai/cli/task_apps/modal_serve.py +11 -0
- synth_ai/cli/task_apps/serve.py +11 -0
- synth_ai/cli/training/__init__.py +8 -0
- synth_ai/cli/training/train.py +5 -0
- synth_ai/cli/training/train_cfg.py +34 -0
- synth_ai/cli/{watch.py → training/watch.py} +13 -18
- synth_ai/cli/turso.py +52 -0
- synth_ai/cli/utils/__init__.py +8 -0
- synth_ai/cli/utils/experiments.py +235 -0
- synth_ai/cli/utils/queue.py +504 -0
- synth_ai/cli/{recent.py → utils/recent.py} +13 -7
- synth_ai/cli/{traces.py → utils/traces.py} +9 -5
- synth_ai/contracts/__init__.py +67 -0
- synth_ai/core/__init__.py +100 -0
- synth_ai/core/_utils/__init__.py +54 -0
- synth_ai/core/_utils/base_url.py +10 -0
- synth_ai/core/_utils/http.py +10 -0
- synth_ai/core/_utils/prompts.py +14 -0
- synth_ai/core/_utils/task_app_state.py +12 -0
- synth_ai/core/_utils/user_config.py +10 -0
- synth_ai/core/apps/common.py +116 -0
- synth_ai/core/auth.py +95 -0
- synth_ai/core/cfgs.py +240 -0
- synth_ai/core/config/__init__.py +16 -0
- synth_ai/core/config/base.py +168 -0
- synth_ai/core/config/resolver.py +89 -0
- synth_ai/core/env.py +231 -0
- synth_ai/core/errors.py +126 -0
- synth_ai/core/http.py +230 -0
- synth_ai/core/integrations/__init__.py +11 -0
- synth_ai/core/integrations/cloudflare.py +1710 -0
- synth_ai/core/integrations/mcp/__init__.py +6 -0
- synth_ai/core/integrations/mcp/__main__.py +8 -0
- synth_ai/core/integrations/mcp/claude.py +36 -0
- synth_ai/core/integrations/mcp/main.py +254 -0
- synth_ai/core/integrations/mcp/setup.py +100 -0
- synth_ai/core/integrations/modal.py +277 -0
- synth_ai/core/json.py +72 -0
- synth_ai/core/log_filter.py +99 -0
- synth_ai/core/logging.py +82 -0
- synth_ai/core/paths.py +107 -0
- synth_ai/core/pricing.py +109 -0
- synth_ai/core/process.py +233 -0
- synth_ai/core/ssl.py +25 -0
- synth_ai/core/storage/__init__.py +71 -0
- synth_ai/core/task_app_state.py +318 -0
- synth_ai/core/telemetry.py +282 -0
- synth_ai/{tracing_v3 → core/tracing_v3}/__init__.py +5 -1
- synth_ai/{tracing_v3 → core/tracing_v3}/abstractions.py +21 -4
- synth_ai/core/tracing_v3/config.py +229 -0
- synth_ai/core/tracing_v3/constants.py +21 -0
- synth_ai/{tracing_v3 → core/tracing_v3}/db_config.py +42 -29
- synth_ai/{tracing_v3 → core/tracing_v3}/decorators.py +80 -45
- synth_ai/{tracing_v3 → core/tracing_v3}/examples/basic_usage.py +15 -9
- synth_ai/{tracing_v3 → core/tracing_v3}/hooks.py +6 -4
- synth_ai/{tracing_v3 → core/tracing_v3}/llm_call_record_helpers.py +161 -61
- synth_ai/{tracing_v3 → core/tracing_v3}/migration_helper.py +1 -2
- synth_ai/{tracing_v3 → core/tracing_v3}/replica_sync.py +12 -7
- synth_ai/core/tracing_v3/serialization.py +130 -0
- synth_ai/{tracing_v3 → core/tracing_v3}/session_tracer.py +88 -21
- synth_ai/{tracing_v3 → core/tracing_v3}/storage/base.py +99 -12
- synth_ai/core/tracing_v3/storage/config.py +109 -0
- synth_ai/{tracing_v3 → core/tracing_v3}/storage/factory.py +11 -9
- synth_ai/{tracing_v3 → core/tracing_v3}/storage/utils.py +15 -11
- synth_ai/core/tracing_v3/trace_utils.py +326 -0
- synth_ai/core/tracing_v3/turso/__init__.py +12 -0
- synth_ai/core/tracing_v3/turso/daemon.py +278 -0
- synth_ai/{tracing_v3 → core/tracing_v3}/turso/models.py +7 -3
- synth_ai/core/tracing_v3/turso/native_manager.py +1385 -0
- synth_ai/{tracing_v3 → core/tracing_v3}/utils.py +5 -4
- synth_ai/core/urls.py +18 -0
- synth_ai/core/user_config.py +137 -0
- synth_ai/core/uvicorn.py +222 -0
- synth_ai/data/__init__.py +83 -0
- synth_ai/data/enums.py +123 -0
- synth_ai/data/rewards.py +152 -0
- synth_ai/data/traces.py +35 -0
- synth_ai/products/__init__.py +6 -0
- synth_ai/products/graph_evolve/__init__.py +46 -0
- synth_ai/products/graph_evolve/client.py +226 -0
- synth_ai/products/graph_evolve/config.py +591 -0
- synth_ai/products/graph_evolve/converters/__init__.py +42 -0
- synth_ai/products/graph_evolve/converters/openai_sft.py +484 -0
- synth_ai/products/graph_evolve/examples/hotpotqa/config.toml +109 -0
- synth_ai/products/graph_evolve/run.py +222 -0
- synth_ai/products/graph_gepa/__init__.py +23 -0
- synth_ai/products/graph_gepa/converters/__init__.py +19 -0
- synth_ai/products/graph_gepa/converters/openai_sft.py +29 -0
- synth_ai/sdk/__init__.py +123 -0
- synth_ai/sdk/api/__init__.py +1 -0
- synth_ai/sdk/api/models/supported.py +514 -0
- synth_ai/sdk/api/research_agent/__init__.py +296 -0
- synth_ai/sdk/api/train/__init__.py +85 -0
- synth_ai/sdk/api/train/builders.py +895 -0
- synth_ai/sdk/api/train/cli.py +2199 -0
- synth_ai/sdk/api/train/config_finder.py +267 -0
- synth_ai/sdk/api/train/configs/__init__.py +65 -0
- synth_ai/sdk/api/train/configs/prompt_learning.py +1706 -0
- synth_ai/sdk/api/train/configs/rl.py +187 -0
- synth_ai/sdk/api/train/configs/sft.py +99 -0
- synth_ai/sdk/api/train/configs/shared.py +81 -0
- synth_ai/sdk/api/train/context_learning.py +312 -0
- synth_ai/sdk/api/train/env_resolver.py +418 -0
- synth_ai/sdk/api/train/graph_validators.py +216 -0
- synth_ai/sdk/api/train/graphgen.py +984 -0
- synth_ai/sdk/api/train/graphgen_models.py +823 -0
- synth_ai/sdk/api/train/graphgen_validators.py +109 -0
- synth_ai/sdk/api/train/local_api.py +10 -0
- synth_ai/sdk/api/train/pollers.py +124 -0
- synth_ai/sdk/api/train/progress/__init__.py +97 -0
- synth_ai/sdk/api/train/progress/dataclasses.py +569 -0
- synth_ai/sdk/api/train/progress/events.py +326 -0
- synth_ai/sdk/api/train/progress/results.py +428 -0
- synth_ai/sdk/api/train/progress/tracker.py +641 -0
- synth_ai/sdk/api/train/prompt_learning.py +469 -0
- synth_ai/sdk/api/train/rl.py +441 -0
- synth_ai/sdk/api/train/sft.py +396 -0
- synth_ai/sdk/api/train/summary.py +522 -0
- synth_ai/sdk/api/train/supported_algos.py +147 -0
- synth_ai/sdk/api/train/task_app.py +351 -0
- synth_ai/sdk/api/train/utils.py +279 -0
- synth_ai/sdk/api/train/validators.py +2424 -0
- synth_ai/sdk/graphs/__init__.py +15 -0
- synth_ai/sdk/graphs/completions.py +570 -0
- synth_ai/{inference → sdk/inference}/__init__.py +0 -1
- synth_ai/sdk/inference/client.py +128 -0
- synth_ai/sdk/jobs/__init__.py +16 -0
- synth_ai/sdk/jobs/client.py +371 -0
- synth_ai/sdk/judging/__init__.py +14 -0
- synth_ai/sdk/judging/base.py +24 -0
- synth_ai/sdk/judging/client.py +40 -0
- synth_ai/sdk/judging/schemas.py +222 -0
- synth_ai/sdk/judging/types.py +42 -0
- synth_ai/sdk/learning/__init__.py +99 -0
- synth_ai/sdk/learning/algorithms.py +14 -0
- synth_ai/{learning → sdk/learning}/client.py +121 -30
- synth_ai/sdk/learning/config.py +5 -0
- synth_ai/{learning → sdk/learning}/constants.py +0 -2
- synth_ai/sdk/learning/context_learning_client.py +531 -0
- synth_ai/sdk/learning/context_learning_types.py +292 -0
- synth_ai/sdk/learning/ft_client.py +7 -0
- synth_ai/{learning → sdk/learning}/health.py +15 -9
- synth_ai/{learning → sdk/learning}/jobs.py +44 -47
- synth_ai/sdk/learning/prompt_extraction.py +334 -0
- synth_ai/sdk/learning/prompt_learning_client.py +455 -0
- synth_ai/sdk/learning/prompt_learning_types.py +186 -0
- synth_ai/{rl → sdk/learning/rl}/__init__.py +13 -8
- synth_ai/{learning/rl_client.py → sdk/learning/rl/client.py} +89 -77
- synth_ai/sdk/learning/rl/config.py +31 -0
- synth_ai/{rl → sdk/learning/rl}/contracts.py +5 -14
- synth_ai/{rl → sdk/learning/rl}/env_keys.py +45 -16
- synth_ai/sdk/learning/rl/secrets.py +13 -0
- synth_ai/sdk/learning/rl_client.py +5 -0
- synth_ai/sdk/learning/sft/__init__.py +29 -0
- synth_ai/sdk/learning/sft/client.py +95 -0
- synth_ai/sdk/learning/sft/config.py +270 -0
- synth_ai/sdk/learning/sft/data.py +698 -0
- synth_ai/sdk/learning/sse.py +57 -0
- synth_ai/sdk/learning/validators.py +52 -0
- synth_ai/sdk/localapi/__init__.py +40 -0
- synth_ai/sdk/localapi/apps/__init__.py +28 -0
- synth_ai/sdk/localapi/client.py +10 -0
- synth_ai/sdk/localapi/contracts.py +10 -0
- synth_ai/sdk/localapi/helpers.py +519 -0
- synth_ai/sdk/localapi/rollouts.py +87 -0
- synth_ai/sdk/localapi/server.py +29 -0
- synth_ai/sdk/localapi/template.py +70 -0
- synth_ai/sdk/streaming/__init__.py +35 -0
- synth_ai/sdk/streaming/config.py +94 -0
- synth_ai/sdk/streaming/handlers.py +1997 -0
- synth_ai/sdk/streaming/streamer.py +713 -0
- synth_ai/sdk/streaming/types.py +112 -0
- synth_ai/sdk/task/__init__.py +164 -0
- synth_ai/sdk/task/apps/__init__.py +169 -0
- synth_ai/sdk/task/auth.py +165 -0
- synth_ai/sdk/task/client.py +175 -0
- synth_ai/sdk/task/config.py +257 -0
- synth_ai/sdk/task/contracts.py +219 -0
- synth_ai/sdk/task/datasets.py +108 -0
- synth_ai/sdk/task/errors.py +50 -0
- synth_ai/sdk/task/health.py +34 -0
- synth_ai/sdk/task/in_process.py +1190 -0
- synth_ai/sdk/task/in_process_runner.py +314 -0
- synth_ai/sdk/task/inference_api.py +299 -0
- synth_ai/sdk/task/json.py +111 -0
- synth_ai/sdk/task/proxy.py +287 -0
- synth_ai/sdk/task/rubrics/__init__.py +55 -0
- synth_ai/sdk/task/rubrics/loaders.py +156 -0
- synth_ai/sdk/task/rubrics/models.py +57 -0
- synth_ai/sdk/task/rubrics/scoring.py +116 -0
- synth_ai/sdk/task/rubrics/strict.py +149 -0
- synth_ai/sdk/task/rubrics.py +219 -0
- synth_ai/sdk/task/server.py +631 -0
- synth_ai/sdk/task/trace_correlation_helpers.py +539 -0
- synth_ai/sdk/task/tracing_utils.py +95 -0
- synth_ai/sdk/task/validators.py +441 -0
- synth_ai/sdk/task/vendors.py +59 -0
- synth_ai/sdk/training/__init__.py +102 -0
- synth_ai/sdk/tunnels/__init__.py +83 -0
- synth_ai/sdk/tunnels/cleanup.py +83 -0
- synth_ai/sdk/tunnels/ports.py +120 -0
- synth_ai/utils/__init__.py +213 -0
- synth_ai-0.4.3.dist-info/METADATA +262 -0
- synth_ai-0.4.3.dist-info/RECORD +370 -0
- {synth_ai-0.2.8.dev2.dist-info → synth_ai-0.4.3.dist-info}/entry_points.txt +0 -1
- synth_ai/cli/calc.py +0 -69
- synth_ai/cli/demo.py +0 -144
- synth_ai/cli/legacy_root_backup.py +0 -470
- synth_ai/cli/man.py +0 -106
- synth_ai/cli/rl_demo.py +0 -202
- synth_ai/cli/status.py +0 -133
- synth_ai/config/base_url.py +0 -107
- synth_ai/core/experiment.py +0 -15
- synth_ai/core/system.py +0 -15
- synth_ai/demos/core/__init__.py +0 -1
- synth_ai/demos/demo_task_apps/__init__.py +0 -1
- synth_ai/demos/demo_task_apps/math/config.toml +0 -129
- synth_ai/demos/demo_task_apps/math/deploy_task_app.sh +0 -22
- synth_ai/demos/demo_task_apps/math/modal_task_app.py +0 -415
- synth_ai/environments/__init__.py +0 -31
- synth_ai/environments/environment/__init__.py +0 -1
- synth_ai/environments/environment/artifacts/__init__.py +0 -1
- synth_ai/environments/environment/artifacts/base.py +0 -52
- synth_ai/environments/environment/core.py +0 -67
- synth_ai/environments/environment/db/__init__.py +0 -1
- synth_ai/environments/environment/db/sqlite.py +0 -45
- synth_ai/environments/environment/registry.py +0 -233
- synth_ai/environments/environment/resources/sqlite.py +0 -45
- synth_ai/environments/environment/results.py +0 -1
- synth_ai/environments/environment/rewards/__init__.py +0 -1
- synth_ai/environments/environment/rewards/core.py +0 -29
- synth_ai/environments/environment/shared_engine.py +0 -26
- synth_ai/environments/environment/tools/__init__.py +0 -200
- synth_ai/environments/examples/__init__.py +0 -1
- synth_ai/environments/examples/bandit/__init__.py +0 -33
- synth_ai/environments/examples/bandit/engine.py +0 -294
- synth_ai/environments/examples/bandit/environment.py +0 -194
- synth_ai/environments/examples/bandit/taskset.py +0 -200
- synth_ai/environments/examples/crafter_classic/__init__.py +0 -8
- synth_ai/environments/examples/crafter_classic/agent_demos/analyze_semantic_words_markdown.py +0 -250
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_comprehensive_evaluation.py +0 -59
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_browser.py +0 -152
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_config.toml +0 -24
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_framework.py +0 -1194
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/crafter_synth_config.toml +0 -56
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_config_modal.toml +0 -32
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/filter_traces_sft_turso.py +0 -738
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/kick_off_ft_modal.py +0 -384
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_action_results.py +0 -53
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_agent_actions.py +0 -178
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_latest_run.py +0 -222
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_lm_traces.py +0 -183
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_no_rewards.py +0 -210
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/analyze_trace_issue.py +0 -206
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/check_db_schema.py +0 -49
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/check_latest_results.py +0 -64
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/debug_agent_responses.py +0 -88
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_modal_ft/old/quick_trace_check.py +0 -77
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/compare_experiments.py +0 -324
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/filter_traces_sft_turso.py +0 -580
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/kick_off_ft_oai.py +0 -362
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/multi_model_config.toml +0 -49
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_enhanced_hooks.py +0 -332
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_hook_events.py +0 -97
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/analyze_hook_results.py +0 -217
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/check_hook_storage.py +0 -87
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/check_seeds.py +0 -88
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/compare_seed_performance.py +0 -195
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/custom_eval_pipelines.py +0 -400
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/plot_hook_frequency.py +0 -195
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/old/seed_analysis_summary.py +0 -56
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_openai_ft/run_rollouts_for_models_and_compare_v3.py +0 -858
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_quick_evaluation.py +0 -52
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_react_agent.py +0 -874
- synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluation.py +0 -1412
- synth_ai/environments/examples/crafter_classic/agent_demos/example_v3_usage.py +0 -216
- synth_ai/environments/examples/crafter_classic/agent_demos/old/compare_traces.py +0 -296
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_comprehensive_evaluation.py +0 -58
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_env_serialization.py +0 -464
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_evaluation_browser.py +0 -152
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_quick_evaluation.py +0 -51
- synth_ai/environments/examples/crafter_classic/agent_demos/old/crafter_trace_evaluation.py +0 -1412
- synth_ai/environments/examples/crafter_classic/agent_demos/old/debug_player_loss.py +0 -112
- synth_ai/environments/examples/crafter_classic/agent_demos/old/diagnose_service.py +0 -203
- synth_ai/environments/examples/crafter_classic/agent_demos/old/diagnose_slowness.py +0 -305
- synth_ai/environments/examples/crafter_classic/agent_demos/old/eval_by_difficulty.py +0 -126
- synth_ai/environments/examples/crafter_classic/agent_demos/old/eval_example.py +0 -94
- synth_ai/environments/examples/crafter_classic/agent_demos/old/explore_saved_states.py +0 -142
- synth_ai/environments/examples/crafter_classic/agent_demos/old/filter_traces_sft.py +0 -26
- synth_ai/environments/examples/crafter_classic/agent_demos/old/filter_traces_sft_OLD.py +0 -984
- synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_data_gemini.py +0 -724
- synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_data_modal.py +0 -386
- synth_ai/environments/examples/crafter_classic/agent_demos/old/generate_ft_metadata.py +0 -205
- synth_ai/environments/examples/crafter_classic/agent_demos/old/kick_off_ft_gemini.py +0 -150
- synth_ai/environments/examples/crafter_classic/agent_demos/old/kick_off_ft_modal.py +0 -283
- synth_ai/environments/examples/crafter_classic/agent_demos/old/prepare_vertex_ft.py +0 -280
- synth_ai/environments/examples/crafter_classic/agent_demos/old/profile_env_slowness.py +0 -456
- synth_ai/environments/examples/crafter_classic/agent_demos/old/replicate_issue.py +0 -166
- synth_ai/environments/examples/crafter_classic/agent_demos/old/run_and_eval.py +0 -102
- synth_ai/environments/examples/crafter_classic/agent_demos/old/run_comparison.py +0 -128
- synth_ai/environments/examples/crafter_classic/agent_demos/old/run_qwen_rollouts.py +0 -655
- synth_ai/environments/examples/crafter_classic/agent_demos/old/trace_eval_OLD.py +0 -202
- synth_ai/environments/examples/crafter_classic/agent_demos/old/validate_openai_format.py +0 -166
- synth_ai/environments/examples/crafter_classic/config_logging.py +0 -111
- synth_ai/environments/examples/crafter_classic/debug_translation.py +0 -0
- synth_ai/environments/examples/crafter_classic/engine.py +0 -579
- synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +0 -64
- synth_ai/environments/examples/crafter_classic/engine_helpers/action_map.py +0 -6
- synth_ai/environments/examples/crafter_classic/engine_helpers/serialization.py +0 -75
- synth_ai/environments/examples/crafter_classic/engine_serialization_patch_v3.py +0 -267
- synth_ai/environments/examples/crafter_classic/environment.py +0 -404
- synth_ai/environments/examples/crafter_classic/taskset.py +0 -233
- synth_ai/environments/examples/crafter_classic/trace_hooks_v3.py +0 -228
- synth_ai/environments/examples/crafter_classic/world_config_patch_simple.py +0 -299
- synth_ai/environments/examples/crafter_custom/__init__.py +0 -4
- synth_ai/environments/examples/crafter_custom/agent_demos/__init__.py +0 -1
- synth_ai/environments/examples/crafter_custom/agent_demos/trace_eval.py +0 -202
- synth_ai/environments/examples/crafter_custom/crafter/__init__.py +0 -7
- synth_ai/environments/examples/crafter_custom/crafter/config.py +0 -182
- synth_ai/environments/examples/crafter_custom/crafter/constants.py +0 -8
- synth_ai/environments/examples/crafter_custom/crafter/engine.py +0 -269
- synth_ai/environments/examples/crafter_custom/crafter/env.py +0 -262
- synth_ai/environments/examples/crafter_custom/crafter/objects.py +0 -417
- synth_ai/environments/examples/crafter_custom/crafter/recorder.py +0 -187
- synth_ai/environments/examples/crafter_custom/crafter/worldgen.py +0 -118
- synth_ai/environments/examples/crafter_custom/dataset_builder.py +0 -373
- synth_ai/environments/examples/crafter_custom/environment.py +0 -312
- synth_ai/environments/examples/crafter_custom/old/analyze_diamond_issue.py +0 -159
- synth_ai/environments/examples/crafter_custom/old/analyze_diamond_spawning.py +0 -158
- synth_ai/environments/examples/crafter_custom/old/compare_worlds.py +0 -71
- synth_ai/environments/examples/crafter_custom/old/dataset_stats.py +0 -105
- synth_ai/environments/examples/crafter_custom/old/diamond_spawning_summary.py +0 -119
- synth_ai/environments/examples/crafter_custom/old/example_dataset_usage.py +0 -52
- synth_ai/environments/examples/crafter_custom/run_dataset.py +0 -305
- synth_ai/environments/examples/enron/art_helpers/email_search_tools.py +0 -156
- synth_ai/environments/examples/enron/art_helpers/local_email_db.py +0 -281
- synth_ai/environments/examples/enron/art_helpers/types_enron.py +0 -25
- synth_ai/environments/examples/enron/engine.py +0 -295
- synth_ai/environments/examples/enron/environment.py +0 -166
- synth_ai/environments/examples/enron/taskset.py +0 -112
- synth_ai/environments/examples/enron/units/keyword_stats.py +0 -112
- synth_ai/environments/examples/minigrid/__init__.py +0 -48
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_evaluation_framework.py +0 -1188
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_quick_evaluation.py +0 -48
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_react_agent.py +0 -562
- synth_ai/environments/examples/minigrid/agent_demos/minigrid_trace_evaluation.py +0 -221
- synth_ai/environments/examples/minigrid/engine.py +0 -589
- synth_ai/environments/examples/minigrid/environment.py +0 -274
- synth_ai/environments/examples/minigrid/environment_mapping.py +0 -242
- synth_ai/environments/examples/minigrid/puzzle_loader.py +0 -417
- synth_ai/environments/examples/minigrid/taskset.py +0 -583
- synth_ai/environments/examples/nethack/__init__.py +0 -7
- synth_ai/environments/examples/nethack/achievements.py +0 -337
- synth_ai/environments/examples/nethack/agent_demos/nethack_evaluation_framework.py +0 -981
- synth_ai/environments/examples/nethack/agent_demos/nethack_quick_evaluation.py +0 -74
- synth_ai/environments/examples/nethack/agent_demos/nethack_react_agent.py +0 -831
- synth_ai/environments/examples/nethack/engine.py +0 -739
- synth_ai/environments/examples/nethack/environment.py +0 -256
- synth_ai/environments/examples/nethack/helpers/__init__.py +0 -41
- synth_ai/environments/examples/nethack/helpers/action_mapping.py +0 -301
- synth_ai/environments/examples/nethack/helpers/nle_wrapper.py +0 -402
- synth_ai/environments/examples/nethack/helpers/observation_utils.py +0 -433
- synth_ai/environments/examples/nethack/helpers/recording_wrapper.py +0 -200
- synth_ai/environments/examples/nethack/helpers/trajectory_recorder.py +0 -269
- synth_ai/environments/examples/nethack/helpers/visualization/replay_viewer.py +0 -308
- synth_ai/environments/examples/nethack/helpers/visualization/visualizer.py +0 -431
- synth_ai/environments/examples/nethack/taskset.py +0 -323
- synth_ai/environments/examples/red/__init__.py +0 -7
- synth_ai/environments/examples/red/agent_demos/__init__.py +0 -1
- synth_ai/environments/examples/red/config_logging.py +0 -110
- synth_ai/environments/examples/red/engine.py +0 -694
- synth_ai/environments/examples/red/engine_helpers/__init__.py +0 -1
- synth_ai/environments/examples/red/engine_helpers/memory_map.py +0 -28
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +0 -276
- synth_ai/environments/examples/red/engine_helpers/reward_library/__init__.py +0 -142
- synth_ai/environments/examples/red/engine_helpers/reward_library/adaptive_rewards.py +0 -57
- synth_ai/environments/examples/red/engine_helpers/reward_library/battle_rewards.py +0 -284
- synth_ai/environments/examples/red/engine_helpers/reward_library/composite_rewards.py +0 -150
- synth_ai/environments/examples/red/engine_helpers/reward_library/economy_rewards.py +0 -138
- synth_ai/environments/examples/red/engine_helpers/reward_library/efficiency_rewards.py +0 -57
- synth_ai/environments/examples/red/engine_helpers/reward_library/exploration_rewards.py +0 -331
- synth_ai/environments/examples/red/engine_helpers/reward_library/novelty_rewards.py +0 -121
- synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_rewards.py +0 -559
- synth_ai/environments/examples/red/engine_helpers/reward_library/pokemon_rewards.py +0 -313
- synth_ai/environments/examples/red/engine_helpers/reward_library/social_rewards.py +0 -148
- synth_ai/environments/examples/red/engine_helpers/reward_library/story_rewards.py +0 -247
- synth_ai/environments/examples/red/engine_helpers/screen_analysis.py +0 -368
- synth_ai/environments/examples/red/engine_helpers/state_extraction.py +0 -140
- synth_ai/environments/examples/red/environment.py +0 -238
- synth_ai/environments/examples/red/taskset.py +0 -79
- synth_ai/environments/examples/red/units/__init__.py +0 -1
- synth_ai/environments/examples/sokoban/__init__.py +0 -1
- synth_ai/environments/examples/sokoban/agent_demos/sokoban_full_eval.py +0 -899
- synth_ai/environments/examples/sokoban/engine.py +0 -678
- synth_ai/environments/examples/sokoban/engine_helpers/__init__.py +0 -1
- synth_ai/environments/examples/sokoban/engine_helpers/room_utils.py +0 -657
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/__init__.py +0 -18
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/__init__.py +0 -3
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/boxoban_env.py +0 -131
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/render_utils.py +0 -370
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/room_utils.py +0 -332
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env.py +0 -306
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_fixed_targets.py +0 -67
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_pull.py +0 -115
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_two_player.py +0 -123
- synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_variations.py +0 -394
- synth_ai/environments/examples/sokoban/environment.py +0 -229
- synth_ai/environments/examples/sokoban/generate_verified_puzzles.py +0 -440
- synth_ai/environments/examples/sokoban/puzzle_loader.py +0 -312
- synth_ai/environments/examples/sokoban/taskset.py +0 -428
- synth_ai/environments/examples/sokoban/units/astar_common.py +0 -95
- synth_ai/environments/examples/tictactoe/__init__.py +0 -1
- synth_ai/environments/examples/tictactoe/engine.py +0 -368
- synth_ai/environments/examples/tictactoe/environment.py +0 -240
- synth_ai/environments/examples/tictactoe/taskset.py +0 -215
- synth_ai/environments/examples/verilog/__init__.py +0 -10
- synth_ai/environments/examples/verilog/engine.py +0 -329
- synth_ai/environments/examples/verilog/environment.py +0 -350
- synth_ai/environments/examples/verilog/taskset.py +0 -420
- synth_ai/environments/examples/wordle/__init__.py +0 -29
- synth_ai/environments/examples/wordle/engine.py +0 -398
- synth_ai/environments/examples/wordle/environment.py +0 -159
- synth_ai/environments/examples/wordle/helpers/generate_instances_wordfreq.py +0 -75
- synth_ai/environments/examples/wordle/taskset.py +0 -230
- synth_ai/environments/reproducibility/core.py +0 -42
- synth_ai/environments/reproducibility/helpers.py +0 -0
- synth_ai/environments/reproducibility/tree.py +0 -364
- synth_ai/environments/service/app.py +0 -98
- synth_ai/environments/service/core_routes.py +0 -1020
- synth_ai/environments/service/external_registry.py +0 -56
- synth_ai/environments/service/registry.py +0 -9
- synth_ai/environments/stateful/__init__.py +0 -1
- synth_ai/environments/stateful/core.py +0 -163
- synth_ai/environments/stateful/engine.py +0 -21
- synth_ai/environments/stateful/state.py +0 -7
- synth_ai/environments/tasks/api.py +0 -19
- synth_ai/environments/tasks/core.py +0 -80
- synth_ai/environments/tasks/filters.py +0 -41
- synth_ai/environments/tasks/utils.py +0 -91
- synth_ai/environments/v0_observability/history.py +0 -3
- synth_ai/environments/v0_observability/log.py +0 -2
- synth_ai/evals/base.py +0 -15
- synth_ai/experimental/synth_oss.py +0 -446
- synth_ai/handshake.py +0 -63
- synth_ai/http.py +0 -26
- synth_ai/http_client.py +0 -104
- synth_ai/inference/client.py +0 -20
- synth_ai/install_sqld.sh +0 -40
- synth_ai/jobs/client.py +0 -246
- synth_ai/learning/__init__.py +0 -24
- synth_ai/learning/config.py +0 -43
- synth_ai/learning/filtering.py +0 -0
- synth_ai/learning/ft_client.py +0 -59
- synth_ai/learning/offline/dpo.py +0 -0
- synth_ai/learning/offline/providers.py +0 -7
- synth_ai/learning/offline/sft.py +0 -0
- synth_ai/learning/offline/shared.py +0 -0
- synth_ai/learning/online/grpo.py +0 -0
- synth_ai/learning/online/irft.py +0 -0
- synth_ai/learning/prompts/banking77_injection_eval.py +0 -168
- synth_ai/learning/prompts/gepa.py +0 -0
- synth_ai/learning/prompts/hello_world_in_context_injection_ex.py +0 -213
- synth_ai/learning/prompts/mipro.py +0 -289
- synth_ai/learning/prompts/random_search.py +0 -246
- synth_ai/learning/prompts/run_mipro_banking77.py +0 -172
- synth_ai/learning/prompts/run_random_search_banking77.py +0 -324
- synth_ai/learning/sse.py +0 -58
- synth_ai/learning/validators.py +0 -48
- synth_ai/lm/__init__.py +0 -51
- synth_ai/lm/caching/constants.py +0 -6
- synth_ai/lm/caching/dbs.py +0 -0
- synth_ai/lm/caching/ephemeral.py +0 -102
- synth_ai/lm/caching/handler.py +0 -137
- synth_ai/lm/caching/initialize.py +0 -11
- synth_ai/lm/caching/persistent.py +0 -114
- synth_ai/lm/config.py +0 -110
- synth_ai/lm/constants.py +0 -32
- synth_ai/lm/core/__init__.py +0 -8
- synth_ai/lm/core/all.py +0 -73
- synth_ai/lm/core/exceptions.py +0 -7
- synth_ai/lm/core/main.py +0 -319
- synth_ai/lm/core/main_v3.py +0 -594
- synth_ai/lm/core/synth_models.py +0 -48
- synth_ai/lm/core/vendor_clients.py +0 -188
- synth_ai/lm/cost/__init__.py +0 -0
- synth_ai/lm/cost/monitor.py +0 -1
- synth_ai/lm/cost/statefulness.py +0 -1
- synth_ai/lm/injection.py +0 -80
- synth_ai/lm/overrides.py +0 -206
- synth_ai/lm/provider_support/__init__.py +0 -8
- synth_ai/lm/provider_support/anthropic.py +0 -972
- synth_ai/lm/provider_support/openai.py +0 -1139
- synth_ai/lm/provider_support/suppress_logging.py +0 -31
- synth_ai/lm/structured_outputs/__init__.py +0 -0
- synth_ai/lm/structured_outputs/handler.py +0 -440
- synth_ai/lm/structured_outputs/inject.py +0 -297
- synth_ai/lm/structured_outputs/rehabilitate.py +0 -185
- synth_ai/lm/tools/__init__.py +0 -3
- synth_ai/lm/tools/base.py +0 -172
- synth_ai/lm/unified_interface.py +0 -202
- synth_ai/lm/vendors/__init__.py +0 -0
- synth_ai/lm/vendors/base.py +0 -81
- synth_ai/lm/vendors/core/__init__.py +0 -0
- synth_ai/lm/vendors/core/anthropic_api.py +0 -387
- synth_ai/lm/vendors/core/gemini_api.py +0 -292
- synth_ai/lm/vendors/core/mistral_api.py +0 -322
- synth_ai/lm/vendors/core/openai_api.py +0 -225
- synth_ai/lm/vendors/core/synth_dev_api.py +0 -0
- synth_ai/lm/vendors/local/__init__.py +0 -0
- synth_ai/lm/vendors/local/ollama.py +0 -0
- synth_ai/lm/vendors/openai_standard.py +0 -780
- synth_ai/lm/vendors/openai_standard_responses.py +0 -256
- synth_ai/lm/vendors/retries.py +0 -22
- synth_ai/lm/vendors/supported/__init__.py +0 -0
- synth_ai/lm/vendors/supported/custom_endpoint.py +0 -417
- synth_ai/lm/vendors/supported/deepseek.py +0 -69
- synth_ai/lm/vendors/supported/grok.py +0 -75
- synth_ai/lm/vendors/supported/groq.py +0 -16
- synth_ai/lm/vendors/supported/ollama.py +0 -15
- synth_ai/lm/vendors/supported/openrouter.py +0 -74
- synth_ai/lm/vendors/supported/together.py +0 -11
- synth_ai/lm/vendors/synth_client.py +0 -808
- synth_ai/lm/warmup.py +0 -186
- synth_ai/rl/secrets.py +0 -19
- synth_ai/scripts/verify_rewards.py +0 -100
- synth_ai/task/__init__.py +0 -10
- synth_ai/task/contracts.py +0 -120
- synth_ai/task/health.py +0 -28
- synth_ai/task/validators.py +0 -12
- synth_ai/tracing/__init__.py +0 -30
- synth_ai/tracing_v1/__init__.py +0 -33
- synth_ai/tracing_v3/config.py +0 -84
- synth_ai/tracing_v3/storage/config.py +0 -62
- synth_ai/tracing_v3/turso/__init__.py +0 -25
- synth_ai/tracing_v3/turso/daemon.py +0 -144
- synth_ai/tracing_v3/turso/manager.py +0 -760
- synth_ai/v0/tracing/__init__.py +0 -0
- synth_ai/v0/tracing/abstractions.py +0 -224
- synth_ai/v0/tracing/base_client.py +0 -91
- synth_ai/v0/tracing/client_manager.py +0 -131
- synth_ai/v0/tracing/config.py +0 -142
- synth_ai/v0/tracing/context.py +0 -146
- synth_ai/v0/tracing/decorators.py +0 -682
- synth_ai/v0/tracing/events/__init__.py +0 -0
- synth_ai/v0/tracing/events/manage.py +0 -147
- synth_ai/v0/tracing/events/scope.py +0 -86
- synth_ai/v0/tracing/events/store.py +0 -228
- synth_ai/v0/tracing/immediate_client.py +0 -151
- synth_ai/v0/tracing/local.py +0 -18
- synth_ai/v0/tracing/log_client_base.py +0 -73
- synth_ai/v0/tracing/retry_queue.py +0 -186
- synth_ai/v0/tracing/trackers.py +0 -515
- synth_ai/v0/tracing/upload.py +0 -512
- synth_ai/v0/tracing/utils.py +0 -9
- synth_ai/v0/tracing_v1/__init__.py +0 -16
- synth_ai/v0/tracing_v1/abstractions.py +0 -224
- synth_ai/v0/tracing_v1/base_client.py +0 -91
- synth_ai/v0/tracing_v1/client_manager.py +0 -131
- synth_ai/v0/tracing_v1/config.py +0 -142
- synth_ai/v0/tracing_v1/context.py +0 -146
- synth_ai/v0/tracing_v1/decorators.py +0 -703
- synth_ai/v0/tracing_v1/events/__init__.py +0 -0
- synth_ai/v0/tracing_v1/events/manage.py +0 -147
- synth_ai/v0/tracing_v1/events/scope.py +0 -86
- synth_ai/v0/tracing_v1/events/store.py +0 -228
- synth_ai/v0/tracing_v1/immediate_client.py +0 -151
- synth_ai/v0/tracing_v1/local.py +0 -18
- synth_ai/v0/tracing_v1/log_client_base.py +0 -73
- synth_ai/v0/tracing_v1/retry_queue.py +0 -186
- synth_ai/v0/tracing_v1/trackers.py +0 -515
- synth_ai/v0/tracing_v1/upload.py +0 -527
- synth_ai/v0/tracing_v1/utils.py +0 -9
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.8.dev2.dist-info/METADATA +0 -129
- synth_ai-0.2.8.dev2.dist-info/RECORD +0 -420
- /synth_ai/{demos → cli/demo_apps}/demo_task_apps/math/__init__.py +0 -0
- /synth_ai/{lm/caching → core/apps}/__init__.py +0 -0
- /synth_ai/{tracing_v3 → core/tracing_v3}/lm_call_record_abstractions.py +0 -0
- /synth_ai/{tracing_v3 → core/tracing_v3}/storage/__init__.py +0 -0
- /synth_ai/{tracing_v3 → core/tracing_v3}/storage/exceptions.py +0 -0
- /synth_ai/{tracing_v3 → core/tracing_v3}/storage/types.py +0 -0
- /synth_ai/{compound/cais.py → py.typed} +0 -0
- /synth_ai/{learning → sdk/learning}/core.py +0 -0
- /synth_ai/{learning → sdk/learning}/gateway.py +0 -0
- {synth_ai-0.2.8.dev2.dist-info → synth_ai-0.4.3.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.8.dev2.dist-info → synth_ai-0.4.3.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.8.dev2.dist-info → synth_ai-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Dict
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from synth_ai.core.env import PROD_BASE_URL_DEFAULT
|
|
9
|
+
from synth_ai.core.process import ensure_local_port_available
|
|
10
|
+
from synth_ai.core.task_app_state import persist_env_api_key
|
|
11
|
+
from synth_ai.core.user_config import load_user_env, update_user_config
|
|
12
|
+
|
|
13
|
+
from .env import mask_str, resolve_env_var
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ensure_env_credentials",
|
|
17
|
+
"ensure_port_free",
|
|
18
|
+
"preflight_env_key",
|
|
19
|
+
"interactive_fill_env",
|
|
20
|
+
"save_to_env_file",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
_ENV_LINE = re.compile(r"^\s*(?:export\s+)?(?P<key>[A-Za-z0-9_]+)\s*=\s*(?P<value>.*)$")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def ensure_env_credentials(*, require_synth: bool = False, prompt: bool = True) -> None:
|
|
27
|
+
"""Ensure required API keys are present in the process environment."""
|
|
28
|
+
|
|
29
|
+
load_user_env(override=False)
|
|
30
|
+
|
|
31
|
+
env_key = (os.environ.get("ENVIRONMENT_API_KEY") or "").strip()
|
|
32
|
+
if prompt and not env_key:
|
|
33
|
+
resolve_env_var("ENVIRONMENT_API_KEY")
|
|
34
|
+
env_key = (os.environ.get("ENVIRONMENT_API_KEY") or "").strip()
|
|
35
|
+
|
|
36
|
+
if env_key:
|
|
37
|
+
update_user_config(
|
|
38
|
+
{
|
|
39
|
+
"ENVIRONMENT_API_KEY": env_key,
|
|
40
|
+
"DEV_ENVIRONMENT_API_KEY": env_key,
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
persist_env_api_key(env_key)
|
|
44
|
+
elif prompt:
|
|
45
|
+
raise click.ClickException("ENVIRONMENT_API_KEY is required.")
|
|
46
|
+
|
|
47
|
+
synth_key = (os.environ.get("SYNTH_API_KEY") or "").strip()
|
|
48
|
+
if prompt and (require_synth or not synth_key):
|
|
49
|
+
resolve_env_var("SYNTH_API_KEY")
|
|
50
|
+
synth_key = (os.environ.get("SYNTH_API_KEY") or "").strip()
|
|
51
|
+
|
|
52
|
+
if synth_key:
|
|
53
|
+
update_user_config({"SYNTH_API_KEY": synth_key})
|
|
54
|
+
elif require_synth and prompt:
|
|
55
|
+
raise click.ClickException("SYNTH_API_KEY is required.")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def ensure_port_free(port: int, host: str, *, force: bool) -> None:
|
|
59
|
+
"""Ensure a TCP port is not in use, optionally killing processes when ``force`` is True."""
|
|
60
|
+
|
|
61
|
+
if ensure_local_port_available(host, port, force=force):
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
message = f"Port {port} is still in use. Stop the running server and try again."
|
|
65
|
+
if force:
|
|
66
|
+
raise click.ClickException(message)
|
|
67
|
+
raise click.ClickException(f"Port {port} appears to be in use. Restart with --force to terminate it.")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def preflight_env_key(*, crash_on_failure: bool = False) -> None:
|
|
71
|
+
"""Ensure ENVIRONMENT_API_KEY exists and attempt a backend registration."""
|
|
72
|
+
|
|
73
|
+
ensure_env_credentials(require_synth=False, prompt=not crash_on_failure)
|
|
74
|
+
load_user_env(override=False)
|
|
75
|
+
|
|
76
|
+
raw_backend = (
|
|
77
|
+
os.environ.get("BACKEND_BASE_URL")
|
|
78
|
+
or os.environ.get("SYNTH_BASE_URL")
|
|
79
|
+
or f"{PROD_BASE_URL_DEFAULT}/api"
|
|
80
|
+
)
|
|
81
|
+
backend_base = raw_backend.rstrip("/")
|
|
82
|
+
if not backend_base.endswith("/api"):
|
|
83
|
+
backend_base += "/api"
|
|
84
|
+
|
|
85
|
+
synth_key = os.environ.get("SYNTH_API_KEY") or ""
|
|
86
|
+
env_api_key = (os.environ.get("ENVIRONMENT_API_KEY") or "").strip()
|
|
87
|
+
|
|
88
|
+
def _mint_key() -> str | None:
|
|
89
|
+
try:
|
|
90
|
+
from synth_ai.sdk.learning.rl.secrets import mint_environment_api_key
|
|
91
|
+
|
|
92
|
+
key = mint_environment_api_key()
|
|
93
|
+
os.environ["ENVIRONMENT_API_KEY"] = key
|
|
94
|
+
os.environ.setdefault("DEV_ENVIRONMENT_API_KEY", key)
|
|
95
|
+
update_user_config(
|
|
96
|
+
{
|
|
97
|
+
"ENVIRONMENT_API_KEY": key,
|
|
98
|
+
"DEV_ENVIRONMENT_API_KEY": key,
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
persist_env_api_key(key)
|
|
102
|
+
click.echo(f"[preflight] minted ENVIRONMENT_API_KEY ({mask_str(key)})")
|
|
103
|
+
return key
|
|
104
|
+
except Exception as exc: # pragma: no cover - defensive fallback
|
|
105
|
+
if crash_on_failure:
|
|
106
|
+
raise click.ClickException(
|
|
107
|
+
f"[CRITICAL] Failed to mint ENVIRONMENT_API_KEY: {exc}"
|
|
108
|
+
) from exc
|
|
109
|
+
click.echo(
|
|
110
|
+
f"[WARN] Failed to mint ENVIRONMENT_API_KEY automatically ({exc}); proceeding without upload"
|
|
111
|
+
)
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
minted = False
|
|
115
|
+
if not env_api_key:
|
|
116
|
+
env_api_key = _mint_key() or ""
|
|
117
|
+
minted = bool(env_api_key)
|
|
118
|
+
|
|
119
|
+
if not env_api_key:
|
|
120
|
+
if crash_on_failure:
|
|
121
|
+
raise click.ClickException(
|
|
122
|
+
"[CRITICAL] ENVIRONMENT_API_KEY missing; run `synth-ai setup` to configure it."
|
|
123
|
+
)
|
|
124
|
+
click.echo("[preflight] ENVIRONMENT_API_KEY missing; continuing without verification.")
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
if minted:
|
|
128
|
+
persist_env_api_key(env_api_key)
|
|
129
|
+
|
|
130
|
+
if not synth_key.strip():
|
|
131
|
+
click.echo("[preflight] SYNTH_API_KEY not set; skipping backend preflight.")
|
|
132
|
+
return
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
import base64
|
|
136
|
+
|
|
137
|
+
import httpx
|
|
138
|
+
from nacl.public import PublicKey, SealedBox
|
|
139
|
+
except Exception: # pragma: no cover - optional deps
|
|
140
|
+
click.echo("[preflight] Optional crypto dependencies missing; skipping upload.")
|
|
141
|
+
return
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
with httpx.Client(timeout=15.0, headers={"Authorization": f"Bearer {synth_key}"}) as client:
|
|
145
|
+
click.echo(f"[preflight] backend={backend_base}")
|
|
146
|
+
click.echo("[preflight] fetching public key…")
|
|
147
|
+
rpk = client.get(f"{backend_base.rstrip('/')}/v1/crypto/public-key")
|
|
148
|
+
if rpk.status_code != 200:
|
|
149
|
+
click.echo(f"[preflight] public key fetch failed with {rpk.status_code}; skipping upload")
|
|
150
|
+
return
|
|
151
|
+
pk = (rpk.json() or {}).get("public_key")
|
|
152
|
+
if not pk:
|
|
153
|
+
click.echo("[preflight] no public key returned; skipping upload")
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
pk_bytes = base64.b64decode(pk, validate=True)
|
|
157
|
+
sealed_box = SealedBox(PublicKey(pk_bytes))
|
|
158
|
+
ciphertext = sealed_box.encrypt(env_api_key.encode("utf-8"))
|
|
159
|
+
ct_b64 = base64.b64encode(ciphertext).decode()
|
|
160
|
+
payload = {"name": "ENVIRONMENT_API_KEY", "ciphertext_b64": ct_b64}
|
|
161
|
+
|
|
162
|
+
click.echo(f"[preflight] posting to {backend_base.rstrip('/')}/v1/env-keys")
|
|
163
|
+
response = client.post(f"{backend_base.rstrip('/')}/v1/env-keys", json=payload)
|
|
164
|
+
if 200 <= response.status_code < 300:
|
|
165
|
+
click.echo(
|
|
166
|
+
f"✅ ENVIRONMENT_API_KEY uploaded successfully ({mask_str(env_api_key)})"
|
|
167
|
+
)
|
|
168
|
+
try:
|
|
169
|
+
ver = client.get(f"{backend_base.rstrip('/')}/v1/env-keys/verify")
|
|
170
|
+
if ver.status_code == 200 and (ver.json() or {}).get("present"):
|
|
171
|
+
click.echo("✅ Key verified in backend")
|
|
172
|
+
else:
|
|
173
|
+
click.echo(
|
|
174
|
+
f"⚠️ Verification returned {ver.status_code}, but upload succeeded - proceeding"
|
|
175
|
+
)
|
|
176
|
+
except Exception as verify_err: # pragma: no cover - verification optional
|
|
177
|
+
click.echo(
|
|
178
|
+
f"⚠️ Verification check failed ({verify_err}), but upload succeeded - proceeding"
|
|
179
|
+
)
|
|
180
|
+
return
|
|
181
|
+
|
|
182
|
+
snippet = response.text[:400] if response.text else ""
|
|
183
|
+
message = (
|
|
184
|
+
f"ENVIRONMENT_API_KEY upload failed with status {response.status_code}"
|
|
185
|
+
+ (f" body={snippet}" if snippet else "")
|
|
186
|
+
)
|
|
187
|
+
if crash_on_failure:
|
|
188
|
+
raise click.ClickException(f"[CRITICAL] {message}")
|
|
189
|
+
click.echo(f"[WARN] {message}; proceeding anyway")
|
|
190
|
+
except Exception as exc: # pragma: no cover - network failures
|
|
191
|
+
message = f"Backend preflight for ENVIRONMENT_API_KEY failed: {exc}"
|
|
192
|
+
if crash_on_failure:
|
|
193
|
+
raise click.ClickException(f"[CRITICAL] {message}") from exc
|
|
194
|
+
click.echo(f"[WARN] {message}; proceeding anyway")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _parse_env_file(path: Path) -> dict[str, str]:
|
|
198
|
+
data: dict[str, str] = {}
|
|
199
|
+
try:
|
|
200
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
201
|
+
if not line or line.lstrip().startswith("#") or "=" not in line:
|
|
202
|
+
continue
|
|
203
|
+
key, value = line.split("=", 1)
|
|
204
|
+
data[key.strip()] = value.strip()
|
|
205
|
+
except FileNotFoundError:
|
|
206
|
+
pass
|
|
207
|
+
return data
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _merge_env_content(original: str, updates: Dict[str, str]) -> str:
|
|
211
|
+
"""Merge env updates into existing content while preserving comments/spacing."""
|
|
212
|
+
lines = original.splitlines(keepends=True)
|
|
213
|
+
seen: set[str] = set()
|
|
214
|
+
newline_default = "\n"
|
|
215
|
+
if lines and lines[-1].endswith("\r\n"):
|
|
216
|
+
newline_default = "\r\n"
|
|
217
|
+
|
|
218
|
+
merged: list[str] = []
|
|
219
|
+
for line in lines:
|
|
220
|
+
stripped = line.rstrip("\r\n")
|
|
221
|
+
m = _ENV_LINE.match(stripped)
|
|
222
|
+
key = m.group("key") if m else None
|
|
223
|
+
if key and key in updates and key not in seen:
|
|
224
|
+
end = "\r\n" if line.endswith("\r\n") else "\n"
|
|
225
|
+
merged.append(f"{key}={updates[key]}{end}")
|
|
226
|
+
seen.add(key)
|
|
227
|
+
else:
|
|
228
|
+
merged.append(line)
|
|
229
|
+
|
|
230
|
+
for key, val in updates.items():
|
|
231
|
+
if key not in seen:
|
|
232
|
+
merged.append(f"{key}={val}{newline_default}")
|
|
233
|
+
|
|
234
|
+
if merged and not merged[-1].endswith(("\n", "\r\n")):
|
|
235
|
+
merged[-1] = merged[-1] + newline_default
|
|
236
|
+
|
|
237
|
+
return "".join(merged)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def save_to_env_file(env_path: Path, key: str, value: str) -> Path:
|
|
241
|
+
"""Update a single key in .env preserving comments/formatting."""
|
|
242
|
+
existing = env_path.read_text(encoding="utf-8", errors="ignore") if env_path.exists() else ""
|
|
243
|
+
merged = _merge_env_content(existing, {key: value})
|
|
244
|
+
env_path.parent.mkdir(parents=True, exist_ok=True)
|
|
245
|
+
env_path.write_text(merged, encoding="utf-8")
|
|
246
|
+
return env_path
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def interactive_fill_env(env_path: Path) -> Path | None:
|
|
250
|
+
"""Fill ENVIRONMENT_API_KEY/SYNTH_API_KEY/OPENAI_API_KEY while preserving file content."""
|
|
251
|
+
existing = _parse_env_file(env_path) if env_path.exists() else {}
|
|
252
|
+
|
|
253
|
+
def _prompt(label: str, *, default: str = "", required: bool) -> str | None:
|
|
254
|
+
while True:
|
|
255
|
+
try:
|
|
256
|
+
value = click.prompt(
|
|
257
|
+
label, default=default, show_default=bool(default) or not required
|
|
258
|
+
).strip()
|
|
259
|
+
except (click.Abort, EOFError, KeyboardInterrupt): # pragma: no cover - interactive paths
|
|
260
|
+
click.echo("Aborted env creation.")
|
|
261
|
+
return None
|
|
262
|
+
if value or not required:
|
|
263
|
+
return value
|
|
264
|
+
click.echo("This field is required.")
|
|
265
|
+
|
|
266
|
+
# Allow non-interactive tests to run; skip TTY enforcement.
|
|
267
|
+
env_api_key = _prompt(
|
|
268
|
+
"ENVIRONMENT_API_KEY",
|
|
269
|
+
default=existing.get("ENVIRONMENT_API_KEY", ""),
|
|
270
|
+
required=True,
|
|
271
|
+
)
|
|
272
|
+
if env_api_key is None:
|
|
273
|
+
return None
|
|
274
|
+
synth_key = _prompt(
|
|
275
|
+
"SYNTH_API_KEY (optional)",
|
|
276
|
+
default=existing.get("SYNTH_API_KEY", ""),
|
|
277
|
+
required=False,
|
|
278
|
+
) or ""
|
|
279
|
+
openai_key = _prompt(
|
|
280
|
+
"OPENAI_API_KEY (optional)",
|
|
281
|
+
default=existing.get("OPENAI_API_KEY", ""),
|
|
282
|
+
required=False,
|
|
283
|
+
) or ""
|
|
284
|
+
|
|
285
|
+
updates = {
|
|
286
|
+
"ENVIRONMENT_API_KEY": env_api_key,
|
|
287
|
+
"SYNTH_API_KEY": synth_key,
|
|
288
|
+
"OPENAI_API_KEY": openai_key,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
content = env_path.read_text(encoding="utf-8", errors="ignore") if env_path.exists() else ""
|
|
292
|
+
merged = _merge_env_content(content, updates)
|
|
293
|
+
env_path.parent.mkdir(parents=True, exist_ok=True)
|
|
294
|
+
env_path.write_text(merged, encoding="utf-8")
|
|
295
|
+
return env_path
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import tomllib
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Dict, List, Literal, Tuple
|
|
5
|
+
|
|
6
|
+
from synth_ai.cli.lib.prompts import ctx_print
|
|
7
|
+
from synth_ai.core.paths import is_hidden_path, validate_file_type
|
|
8
|
+
|
|
9
|
+
# Train config types: prompt optimization, reinforcement learning, supervised fine-tuning, ADAS, context learning
|
|
10
|
+
TrainType = Literal["prompt", "rl", "sft", "adas", "context_learning"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_type(config: Dict[str, Any]) -> TrainType | None:
|
|
14
|
+
if "context_learning" in config:
|
|
15
|
+
return "context_learning"
|
|
16
|
+
|
|
17
|
+
if "prompt_learning" in config:
|
|
18
|
+
return "prompt"
|
|
19
|
+
|
|
20
|
+
# Graph / ADAS jobs use a dedicated [graph] (or [adas]) section.
|
|
21
|
+
if isinstance(config.get("graph"), dict) or isinstance(config.get("adas"), dict):
|
|
22
|
+
return "adas"
|
|
23
|
+
|
|
24
|
+
algorithm = config.get("algorithm")
|
|
25
|
+
algo_type = None
|
|
26
|
+
algo_method = None
|
|
27
|
+
if isinstance(algorithm, dict):
|
|
28
|
+
algo_type = str(algorithm.get("type") or "").lower()
|
|
29
|
+
algo_method = str(algorithm.get("method") or "").lower()
|
|
30
|
+
|
|
31
|
+
job = config.get("job")
|
|
32
|
+
compute = config.get("compute")
|
|
33
|
+
rollout = config.get("rollout")
|
|
34
|
+
policy = config.get("policy")
|
|
35
|
+
model = config.get("model")
|
|
36
|
+
|
|
37
|
+
if algo_type == "online" or algo_method in {"policy_gradient", "ppo", "gspo"}:
|
|
38
|
+
return "rl"
|
|
39
|
+
if rollout and (policy or model):
|
|
40
|
+
return "rl"
|
|
41
|
+
|
|
42
|
+
if algo_type == "offline" or algo_method in {"sft", "supervised_finetune"}:
|
|
43
|
+
return "sft"
|
|
44
|
+
if job and compute:
|
|
45
|
+
return "sft"
|
|
46
|
+
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def validate_context_learning_cfg(cfg: Dict[str, Any]) -> None:
|
|
51
|
+
section = cfg.get("context_learning")
|
|
52
|
+
if not isinstance(section, dict):
|
|
53
|
+
raise ValueError("[context_learning] section must be a dict")
|
|
54
|
+
|
|
55
|
+
task_app_url = section.get("task_app_url") or section.get("task_url")
|
|
56
|
+
if not task_app_url:
|
|
57
|
+
raise ValueError("[context_learning].task_app_url is required")
|
|
58
|
+
|
|
59
|
+
evaluation_seeds = section.get("evaluation_seeds")
|
|
60
|
+
if evaluation_seeds is not None and not isinstance(evaluation_seeds, list):
|
|
61
|
+
raise ValueError("[context_learning].evaluation_seeds must be a list when provided")
|
|
62
|
+
|
|
63
|
+
env_section = section.get("environment")
|
|
64
|
+
if env_section is not None and not isinstance(env_section, dict):
|
|
65
|
+
raise ValueError("[context_learning].environment must be a dict when provided")
|
|
66
|
+
|
|
67
|
+
algorithm_section = section.get("algorithm")
|
|
68
|
+
if algorithm_section is not None and not isinstance(algorithm_section, dict):
|
|
69
|
+
raise ValueError("[context_learning].algorithm must be a dict when provided")
|
|
70
|
+
|
|
71
|
+
metadata = section.get("metadata")
|
|
72
|
+
if metadata is not None and not isinstance(metadata, dict):
|
|
73
|
+
raise ValueError("[context_learning].metadata must be a dict when provided")
|
|
74
|
+
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def validate_po_cfg(cfg: Dict[str, Any]) -> None:
|
|
79
|
+
pl_cfg = cfg.get("prompt_learning")
|
|
80
|
+
if not pl_cfg:
|
|
81
|
+
pl_cfg = cfg
|
|
82
|
+
|
|
83
|
+
if not isinstance(pl_cfg, dict):
|
|
84
|
+
raise ValueError("[prompt_learning] section must be a dict")
|
|
85
|
+
|
|
86
|
+
algorithm = pl_cfg.get("algorithm")
|
|
87
|
+
if not algorithm:
|
|
88
|
+
raise ValueError("[prompt_learning].algorithm is required")
|
|
89
|
+
|
|
90
|
+
if algorithm not in {"mipro", "gepa"}:
|
|
91
|
+
raise ValueError("[prompt_learning].algorithm must be 'mipro' or 'gepa'")
|
|
92
|
+
|
|
93
|
+
if not pl_cfg.get("task_app_url"):
|
|
94
|
+
raise ValueError("[prompt_learning].task_app_url is required")
|
|
95
|
+
|
|
96
|
+
if algorithm == "mipro":
|
|
97
|
+
mipro = pl_cfg.get("mipro")
|
|
98
|
+
if not isinstance(mipro, dict):
|
|
99
|
+
raise ValueError("[prompt_learning].mipro section is required when algorithm is 'mipro'")
|
|
100
|
+
elif algorithm == "gepa":
|
|
101
|
+
gepa = pl_cfg.get("gepa")
|
|
102
|
+
if not isinstance(gepa, dict):
|
|
103
|
+
raise ValueError("[prompt_learning].gepa section is required when algorithm is 'gepa'")
|
|
104
|
+
|
|
105
|
+
policy = pl_cfg.get("policy")
|
|
106
|
+
if policy is not None:
|
|
107
|
+
if not isinstance(policy, dict):
|
|
108
|
+
raise ValueError("[prompt_learning].policy must be a dict")
|
|
109
|
+
if not policy.get("model"):
|
|
110
|
+
raise ValueError("[prompt_learning].policy.model is required")
|
|
111
|
+
if not policy.get("provider"):
|
|
112
|
+
raise ValueError("[prompt_learning].policy.provider is required")
|
|
113
|
+
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def validate_sft_cfg(cfg: Dict[str, Any]) -> None:
|
|
118
|
+
algorithm = cfg.get("algorithm")
|
|
119
|
+
if not isinstance(algorithm, dict):
|
|
120
|
+
raise ValueError("[algorithm] section is required")
|
|
121
|
+
if algorithm.get("type") != "offline":
|
|
122
|
+
raise ValueError("[algorithm].type must be 'offline'")
|
|
123
|
+
method = algorithm.get("method")
|
|
124
|
+
if method and method not in {"sft", "supervised_finetune"}:
|
|
125
|
+
raise ValueError("[algorithm].method must be 'sft' or 'supervised_finetune'")
|
|
126
|
+
if not algorithm.get("variety"):
|
|
127
|
+
raise ValueError("[algorithm].variety is required")
|
|
128
|
+
|
|
129
|
+
job = cfg.get("job")
|
|
130
|
+
if not isinstance(job, dict):
|
|
131
|
+
raise ValueError("[job] section is required")
|
|
132
|
+
if not job.get("model"):
|
|
133
|
+
raise ValueError("[job].model is required")
|
|
134
|
+
if not (job.get("data") or job.get("data_path")):
|
|
135
|
+
raise ValueError("[job].data or [job].data_path is required")
|
|
136
|
+
|
|
137
|
+
compute = cfg.get("compute")
|
|
138
|
+
if not isinstance(compute, dict):
|
|
139
|
+
raise ValueError("[compute] section is required")
|
|
140
|
+
if not compute.get("gpu_type"):
|
|
141
|
+
raise ValueError("[compute].gpu_type is required")
|
|
142
|
+
if not compute.get("gpu_count"):
|
|
143
|
+
raise ValueError("[compute].gpu_count is required")
|
|
144
|
+
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def validate_rl_cfg(cfg: Dict[str, Any]) -> None:
|
|
149
|
+
algorithm = cfg.get("algorithm")
|
|
150
|
+
if not isinstance(algorithm, dict):
|
|
151
|
+
raise ValueError("[algorithm] section is required")
|
|
152
|
+
if algorithm.get("type") != "online":
|
|
153
|
+
raise ValueError("[algorithm].type must be 'online'")
|
|
154
|
+
method = algorithm.get("method")
|
|
155
|
+
if method and method not in {"policy_gradient", "ppo", "gspo"}:
|
|
156
|
+
raise ValueError("[algorithm].method must be policy_gradient/ppo/gspo")
|
|
157
|
+
if not algorithm.get("variety"):
|
|
158
|
+
raise ValueError("[algorithm].variety is required")
|
|
159
|
+
|
|
160
|
+
policy = cfg.get("policy")
|
|
161
|
+
model = cfg.get("model")
|
|
162
|
+
|
|
163
|
+
section: Dict[str, Any]
|
|
164
|
+
if isinstance(policy, dict):
|
|
165
|
+
section = policy
|
|
166
|
+
if not (policy.get("model_name") or policy.get("source")):
|
|
167
|
+
raise ValueError("[policy].model_name or [policy].source is required")
|
|
168
|
+
elif isinstance(model, dict):
|
|
169
|
+
section = model
|
|
170
|
+
if not (model.get("base") or model.get("source")):
|
|
171
|
+
raise ValueError("[model].base or [model].source is required")
|
|
172
|
+
else:
|
|
173
|
+
raise ValueError("[policy] or [model] section is required")
|
|
174
|
+
|
|
175
|
+
if not section.get("trainer_mode"):
|
|
176
|
+
raise ValueError("trainer_mode is required")
|
|
177
|
+
if not section.get("label"):
|
|
178
|
+
raise ValueError("label is required")
|
|
179
|
+
|
|
180
|
+
compute = cfg.get("compute")
|
|
181
|
+
if not isinstance(compute, dict):
|
|
182
|
+
raise ValueError("[compute] section is required")
|
|
183
|
+
if not compute.get("gpu_type"):
|
|
184
|
+
raise ValueError("[compute].gpu_type is required")
|
|
185
|
+
if not compute.get("gpu_count"):
|
|
186
|
+
raise ValueError("[compute].gpu_count is required")
|
|
187
|
+
|
|
188
|
+
rollout = cfg.get("rollout")
|
|
189
|
+
if not isinstance(rollout, dict):
|
|
190
|
+
raise ValueError("[rollout] section is required")
|
|
191
|
+
if not rollout.get("env_name"):
|
|
192
|
+
raise ValueError("[rollout].env_name is required")
|
|
193
|
+
if not rollout.get("policy_name"):
|
|
194
|
+
raise ValueError("[rollout].policy_name is required")
|
|
195
|
+
|
|
196
|
+
topology = cfg.get("topology") or compute.get("topology")
|
|
197
|
+
if not isinstance(topology, dict):
|
|
198
|
+
raise ValueError("[topology] or [compute.topology] is required")
|
|
199
|
+
|
|
200
|
+
training = cfg.get("training")
|
|
201
|
+
if training:
|
|
202
|
+
required_training_fields = (
|
|
203
|
+
"num_epochs",
|
|
204
|
+
"iterations_per_epoch",
|
|
205
|
+
"max_turns",
|
|
206
|
+
"batch_size",
|
|
207
|
+
"group_size",
|
|
208
|
+
"learning_rate",
|
|
209
|
+
)
|
|
210
|
+
for field in required_training_fields:
|
|
211
|
+
if field not in training:
|
|
212
|
+
raise ValueError(f"[training].{field} is required")
|
|
213
|
+
|
|
214
|
+
evaluation = cfg.get("evaluation")
|
|
215
|
+
if evaluation:
|
|
216
|
+
required_eval_fields = ("instances", "every_n_iters", "seeds")
|
|
217
|
+
for field in required_eval_fields:
|
|
218
|
+
if field not in evaluation:
|
|
219
|
+
raise ValueError(f"[evaluation].{field} is required")
|
|
220
|
+
|
|
221
|
+
return None
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def validate_adas_cfg(cfg: Dict[str, Any], *, path: Path) -> None:
|
|
225
|
+
"""Validate a graph/ADAS TOML config.
|
|
226
|
+
|
|
227
|
+
Uses the SDK validator so backend and CLI stay in sync.
|
|
228
|
+
"""
|
|
229
|
+
from synth_ai.sdk.api.train.graph_validators import validate_graph_job_section
|
|
230
|
+
|
|
231
|
+
section = cfg.get("graph") or cfg.get("adas") or {}
|
|
232
|
+
validate_graph_job_section(section, base_dir=path.parent.resolve())
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def validate_train_cfg(path: Path, discovery: bool = False) -> TrainType:
|
|
236
|
+
def print_pass():
|
|
237
|
+
ctx_print("Check passed", not discovery)
|
|
238
|
+
|
|
239
|
+
ctx_print("\nChecking if .toml file", not discovery)
|
|
240
|
+
validate_file_type(path, ".toml")
|
|
241
|
+
print_pass()
|
|
242
|
+
|
|
243
|
+
ctx_print("\nChecking if TOML parses", not discovery)
|
|
244
|
+
cfg = tomllib.loads(path.read_text())
|
|
245
|
+
print_pass()
|
|
246
|
+
|
|
247
|
+
ctx_print("\nChecking if train type is valid", not discovery)
|
|
248
|
+
train_type = get_type(cfg)
|
|
249
|
+
if not train_type:
|
|
250
|
+
raise ValueError(
|
|
251
|
+
"Unable to determine training config type; expected [algorithm] or [prompt_learning] sections."
|
|
252
|
+
)
|
|
253
|
+
print_pass()
|
|
254
|
+
|
|
255
|
+
ctx_print(f"\nChecking if {train_type} config is valid", not discovery)
|
|
256
|
+
match train_type:
|
|
257
|
+
case "context_learning":
|
|
258
|
+
validate_context_learning_cfg(cfg)
|
|
259
|
+
case "prompt":
|
|
260
|
+
validate_po_cfg(cfg)
|
|
261
|
+
case "rl":
|
|
262
|
+
validate_rl_cfg(cfg)
|
|
263
|
+
case "sft":
|
|
264
|
+
validate_sft_cfg(cfg)
|
|
265
|
+
case "adas":
|
|
266
|
+
validate_adas_cfg(cfg, path=path)
|
|
267
|
+
print_pass()
|
|
268
|
+
|
|
269
|
+
return train_type
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def find_train_cfgs_in_cwd() -> List[Tuple[TrainType, str, str]]:
|
|
273
|
+
cwd = Path.cwd().resolve()
|
|
274
|
+
entries: List[Tuple[TrainType, str, str, float]] = []
|
|
275
|
+
for path in cwd.rglob("*.toml"):
|
|
276
|
+
if is_hidden_path(path, cwd):
|
|
277
|
+
continue
|
|
278
|
+
if not path.is_file():
|
|
279
|
+
continue
|
|
280
|
+
try:
|
|
281
|
+
train_type = validate_train_cfg(path, discovery=True)
|
|
282
|
+
except Exception:
|
|
283
|
+
continue
|
|
284
|
+
try:
|
|
285
|
+
rel_path = path.relative_to(cwd)
|
|
286
|
+
except ValueError:
|
|
287
|
+
rel_path = path
|
|
288
|
+
try:
|
|
289
|
+
mtime = path.stat().st_mtime
|
|
290
|
+
mtime_str = datetime.fromtimestamp(mtime).isoformat(
|
|
291
|
+
sep=" ",
|
|
292
|
+
timespec="seconds",
|
|
293
|
+
)
|
|
294
|
+
except OSError:
|
|
295
|
+
mtime = 0.0
|
|
296
|
+
mtime_str = ""
|
|
297
|
+
entries.append((train_type, str(rel_path), mtime_str, mtime))
|
|
298
|
+
|
|
299
|
+
entries.sort(key=lambda entry: entry[3], reverse=True)
|
|
300
|
+
return [(train_type, rel_path, mtime_str) for train_type, rel_path, mtime_str, _ in entries]
|