synth-ai 0.2.6.dev1__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/cli/demo_apps/core/cli.py +1735 -0
- 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 +117 -51
- 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/cli/demo_apps/demo_task_apps/math/_common.py +16 -0
- 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} +21 -3
- 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 -102
- 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.6.dev1.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 -131
- synth_ai/cli/legacy_root_backup.py +0 -470
- synth_ai/cli/man.py +0 -106
- synth_ai/cli/rl_demo.py +0 -137
- synth_ai/cli/status.py +0 -133
- synth_ai/config/base_url.py +0 -98
- 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/core/cli.py +0 -685
- synth_ai/demos/demo_task_apps/__init__.py +0 -1
- synth_ai/demos/demo_task_apps/math/config.toml +0 -44
- synth_ai/demos/demo_task_apps/math/deploy_task_app.sh +0 -22
- 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 -724
- 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 -91
- 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/http.py +0 -102
- 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 -220
- 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 -140
- synth_ai/v0/tracing/context.py +0 -146
- synth_ai/v0/tracing/decorators.py +0 -680
- 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 -510
- 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 -140
- synth_ai/v0/tracing_v1/context.py +0 -146
- synth_ai/v0/tracing_v1/decorators.py +0 -701
- 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 -525
- synth_ai/v0/tracing_v1/utils.py +0 -9
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.6.dev1.dist-info/METADATA +0 -106
- synth_ai-0.2.6.dev1.dist-info/RECORD +0 -416
- /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.6.dev1.dist-info → synth_ai-0.4.3.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.6.dev1.dist-info → synth_ai-0.4.3.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.6.dev1.dist-info → synth_ai-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict, List, Optional, Callable
|
|
4
|
-
import os
|
|
5
3
|
import time
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
from typing import Any
|
|
6
7
|
|
|
7
|
-
from
|
|
8
|
+
from synth_ai.core._utils.http import AsyncHttpClient, HTTPError, sleep
|
|
9
|
+
from synth_ai.sdk.api.models.supported import (
|
|
10
|
+
UnsupportedModelError,
|
|
11
|
+
normalize_model_identifier,
|
|
12
|
+
)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
def _api_base(b: str) -> str:
|
|
@@ -13,12 +18,7 @@ def _api_base(b: str) -> str:
|
|
|
13
18
|
|
|
14
19
|
|
|
15
20
|
class RlClient:
|
|
16
|
-
"""Lightweight RL client for provider-agnostic job control.
|
|
17
|
-
|
|
18
|
-
Notes:
|
|
19
|
-
- Uses learning/* for status/events/metrics and rl/* for creation/start.
|
|
20
|
-
- Trainer endpoints are resolved server-side via trainer_id.
|
|
21
|
-
"""
|
|
21
|
+
"""Lightweight RL client for provider-agnostic job control."""
|
|
22
22
|
|
|
23
23
|
def __init__(self, base_url: str, api_key: str, *, timeout: float = 600.0) -> None:
|
|
24
24
|
self._base_url = base_url.rstrip("/")
|
|
@@ -26,15 +26,24 @@ class RlClient:
|
|
|
26
26
|
self._timeout = timeout
|
|
27
27
|
|
|
28
28
|
async def resolve_trainer_start_url(self, trainer_id: str) -> str:
|
|
29
|
-
"""GET /api/rl/services/{id} → { training_start_url }"""
|
|
30
29
|
path = f"/api/rl/services/{trainer_id}"
|
|
31
30
|
async with AsyncHttpClient(self._base_url, self._api_key, timeout=30.0) as http:
|
|
32
31
|
js = await http.get(path)
|
|
33
32
|
if not isinstance(js, dict):
|
|
34
|
-
raise HTTPError(
|
|
33
|
+
raise HTTPError(
|
|
34
|
+
status=500,
|
|
35
|
+
url=path,
|
|
36
|
+
message="invalid_service_response",
|
|
37
|
+
body_snippet=str(js)[:200],
|
|
38
|
+
)
|
|
35
39
|
start_url = js.get("training_start_url")
|
|
36
40
|
if not isinstance(start_url, str) or not start_url:
|
|
37
|
-
raise HTTPError(
|
|
41
|
+
raise HTTPError(
|
|
42
|
+
status=500,
|
|
43
|
+
url=path,
|
|
44
|
+
message="missing_training_start_url",
|
|
45
|
+
body_snippet=str(js)[:200],
|
|
46
|
+
)
|
|
38
47
|
return start_url
|
|
39
48
|
|
|
40
49
|
async def create_job(
|
|
@@ -42,15 +51,20 @@ class RlClient:
|
|
|
42
51
|
*,
|
|
43
52
|
model: str,
|
|
44
53
|
task_app_url: str,
|
|
45
|
-
trainer:
|
|
46
|
-
trainer_id:
|
|
47
|
-
job_config_id:
|
|
48
|
-
inline_config:
|
|
49
|
-
) ->
|
|
54
|
+
trainer: dict[str, Any],
|
|
55
|
+
trainer_id: str | None = None,
|
|
56
|
+
job_config_id: str | None = None,
|
|
57
|
+
inline_config: dict[str, Any] | None = None,
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
try:
|
|
60
|
+
normalized_model = normalize_model_identifier(model)
|
|
61
|
+
except UnsupportedModelError as exc:
|
|
62
|
+
raise ValueError(str(exc)) from exc
|
|
63
|
+
|
|
50
64
|
body = {
|
|
51
65
|
"job_type": "rl",
|
|
52
66
|
"data": {
|
|
53
|
-
"model":
|
|
67
|
+
"model": normalized_model,
|
|
54
68
|
"endpoint_base_url": task_app_url,
|
|
55
69
|
**({"job_config_id": job_config_id} if job_config_id else {}),
|
|
56
70
|
**({"config": inline_config} if inline_config else {}),
|
|
@@ -63,10 +77,15 @@ class RlClient:
|
|
|
63
77
|
async with AsyncHttpClient(self._base_url, self._api_key, timeout=self._timeout) as http:
|
|
64
78
|
js = await http.post_json(f"{_api_base(self._base_url)}/rl/jobs", json=body)
|
|
65
79
|
if not isinstance(js, dict):
|
|
66
|
-
raise HTTPError(
|
|
80
|
+
raise HTTPError(
|
|
81
|
+
status=500,
|
|
82
|
+
url="/api/rl/jobs",
|
|
83
|
+
message="invalid_create_response",
|
|
84
|
+
body_snippet=str(js)[:200],
|
|
85
|
+
)
|
|
67
86
|
return js
|
|
68
87
|
|
|
69
|
-
async def start_job_if_supported(self, job_id: str) ->
|
|
88
|
+
async def start_job_if_supported(self, job_id: str) -> dict[str, Any] | None:
|
|
70
89
|
path = f"{_api_base(self._base_url)}/rl/jobs/{job_id}/start"
|
|
71
90
|
try:
|
|
72
91
|
async with AsyncHttpClient(self._base_url, self._api_key, timeout=30.0) as http:
|
|
@@ -76,22 +95,26 @@ class RlClient:
|
|
|
76
95
|
return None
|
|
77
96
|
raise
|
|
78
97
|
|
|
79
|
-
async def get_job(self, job_id: str) ->
|
|
98
|
+
async def get_job(self, job_id: str) -> dict[str, Any]:
|
|
80
99
|
async with AsyncHttpClient(self._base_url, self._api_key, timeout=30.0) as http:
|
|
81
100
|
return await http.get(f"{_api_base(self._base_url)}/learning/jobs/{job_id}")
|
|
82
101
|
|
|
83
|
-
async def get_events(
|
|
102
|
+
async def get_events(
|
|
103
|
+
self, job_id: str, *, since_seq: int = 0, limit: int = 200
|
|
104
|
+
) -> list[dict[str, Any]]:
|
|
84
105
|
params = {"since_seq": since_seq, "limit": limit}
|
|
85
106
|
async with AsyncHttpClient(self._base_url, self._api_key, timeout=30.0) as http:
|
|
86
107
|
try:
|
|
87
|
-
js = await http.get(
|
|
108
|
+
js = await http.get(
|
|
109
|
+
f"{_api_base(self._base_url)}/learning/jobs/{job_id}/events",
|
|
110
|
+
params=params,
|
|
111
|
+
headers={"accept": "application/json"},
|
|
112
|
+
)
|
|
88
113
|
except HTTPError as he:
|
|
89
|
-
|
|
114
|
+
with suppress(Exception):
|
|
90
115
|
print(
|
|
91
116
|
f"[poll] events HTTPError status={he.status} url={he.url} since_seq={since_seq} body={(he.body_snippet or '')[:200]}"
|
|
92
117
|
)
|
|
93
|
-
except Exception:
|
|
94
|
-
pass
|
|
95
118
|
raise
|
|
96
119
|
if isinstance(js, dict):
|
|
97
120
|
evs = js.get("events") or js.get("data")
|
|
@@ -99,10 +122,14 @@ class RlClient:
|
|
|
99
122
|
return evs
|
|
100
123
|
return []
|
|
101
124
|
|
|
102
|
-
async def get_metrics(
|
|
125
|
+
async def get_metrics(
|
|
126
|
+
self, job_id: str, *, after_step: int = -1, limit: int = 200
|
|
127
|
+
) -> list[dict[str, Any]]:
|
|
103
128
|
params = {"after_step": after_step, "limit": limit}
|
|
104
129
|
async with AsyncHttpClient(self._base_url, self._api_key, timeout=30.0) as http:
|
|
105
|
-
js = await http.get(
|
|
130
|
+
js = await http.get(
|
|
131
|
+
f"{_api_base(self._base_url)}/learning/jobs/{job_id}/metrics", params=params
|
|
132
|
+
)
|
|
106
133
|
if isinstance(js, dict) and isinstance(js.get("points"), list):
|
|
107
134
|
return js["points"]
|
|
108
135
|
return []
|
|
@@ -115,73 +142,65 @@ class RlClient:
|
|
|
115
142
|
max_seconds: float | None = None,
|
|
116
143
|
empty_polls_threshold: int = 5,
|
|
117
144
|
startup_deadline_s: int = 45,
|
|
118
|
-
on_event:
|
|
119
|
-
on_metric:
|
|
120
|
-
) ->
|
|
121
|
-
last_seq_by_stream:
|
|
122
|
-
events_job_id:
|
|
123
|
-
last_status:
|
|
124
|
-
last_step_by_name:
|
|
145
|
+
on_event: Callable[[dict[str, Any]], None] | None = None,
|
|
146
|
+
on_metric: Callable[[dict[str, Any]], None] | None = None,
|
|
147
|
+
) -> dict[str, Any]:
|
|
148
|
+
last_seq_by_stream: dict[str, int] = {}
|
|
149
|
+
events_job_id: str | None = None
|
|
150
|
+
last_status: str | None = None
|
|
151
|
+
last_step_by_name: dict[str, int] = {}
|
|
125
152
|
empty_polls = 0
|
|
126
153
|
saw_any_event = False
|
|
127
154
|
start_t = time.time()
|
|
128
155
|
terminal = {"succeeded", "failed", "cancelled", "canceled", "error", "completed"}
|
|
129
156
|
|
|
130
157
|
while True:
|
|
131
|
-
status_data:
|
|
158
|
+
status_data: dict[str, Any] | None = None
|
|
132
159
|
try:
|
|
133
160
|
status_data = await self.get_job(job_id)
|
|
134
161
|
except Exception:
|
|
135
162
|
status_data = None
|
|
136
163
|
if status_data is None:
|
|
137
|
-
|
|
164
|
+
with suppress(Exception):
|
|
138
165
|
print(f"[poll] get_job returned None base={self._base_url} job_id={job_id}")
|
|
139
|
-
except Exception:
|
|
140
|
-
pass
|
|
141
166
|
status = str((status_data or {}).get("status") or "").lower()
|
|
142
167
|
if status_data:
|
|
143
168
|
linked = status_data.get("linked_job_id")
|
|
144
169
|
if isinstance(linked, str) and linked and linked != events_job_id:
|
|
145
170
|
events_job_id = linked
|
|
146
|
-
|
|
171
|
+
with suppress(Exception):
|
|
147
172
|
print(f"[poll] discovered linked_job_id stream={events_job_id}")
|
|
148
|
-
except Exception:
|
|
149
|
-
pass
|
|
150
173
|
if status and status != last_status:
|
|
151
174
|
last_status = status
|
|
152
|
-
# Status transitions only to avoid log spam
|
|
153
175
|
if on_event:
|
|
154
|
-
|
|
176
|
+
with suppress(Exception):
|
|
155
177
|
on_event({"type": "rl.status", "message": status})
|
|
156
|
-
except Exception:
|
|
157
|
-
pass
|
|
158
178
|
|
|
159
|
-
# Events
|
|
160
179
|
stream_ids = [job_id]
|
|
161
180
|
if events_job_id and events_job_id not in stream_ids:
|
|
162
181
|
stream_ids.append(events_job_id)
|
|
163
|
-
|
|
164
|
-
print(
|
|
165
|
-
|
|
166
|
-
|
|
182
|
+
with suppress(Exception):
|
|
183
|
+
print(
|
|
184
|
+
f"[poll] streams={stream_ids} intervals={interval_seconds}s since_map={last_seq_by_stream} empty_polls={empty_polls}"
|
|
185
|
+
)
|
|
167
186
|
total_events_this_cycle = 0
|
|
168
187
|
terminal_event_seen = False
|
|
169
|
-
terminal_event_status:
|
|
188
|
+
terminal_event_status: str | None = None
|
|
170
189
|
for ev_id in stream_ids:
|
|
171
190
|
since = last_seq_by_stream.get(ev_id, 0)
|
|
172
191
|
try:
|
|
173
192
|
events = await self.get_events(ev_id, since_seq=since, limit=200)
|
|
174
193
|
except HTTPError as he:
|
|
175
|
-
|
|
176
|
-
print(
|
|
177
|
-
|
|
178
|
-
|
|
194
|
+
with suppress(Exception):
|
|
195
|
+
print(
|
|
196
|
+
f"[poll] get_events error status={he.status} url={he.url} since={since} body={(he.body_snippet or '')[:200]}"
|
|
197
|
+
)
|
|
179
198
|
events = []
|
|
180
199
|
except Exception as e:
|
|
181
|
-
|
|
182
|
-
print(
|
|
183
|
-
|
|
184
|
-
|
|
200
|
+
with suppress(Exception):
|
|
201
|
+
print(
|
|
202
|
+
f"[poll] get_events unexpected error ev_id={ev_id} since={since} err={type(e).__name__}: {e}"
|
|
203
|
+
)
|
|
185
204
|
events = []
|
|
186
205
|
total_events_this_cycle += len(events)
|
|
187
206
|
if events:
|
|
@@ -192,10 +211,8 @@ class RlClient:
|
|
|
192
211
|
continue
|
|
193
212
|
last_seq_by_stream[ev_id] = seq_val
|
|
194
213
|
if on_event:
|
|
195
|
-
|
|
214
|
+
with suppress(Exception):
|
|
196
215
|
on_event(e)
|
|
197
|
-
except Exception:
|
|
198
|
-
pass
|
|
199
216
|
et = str(e.get("type") or e.get("event_type") or "").lower()
|
|
200
217
|
if et in ("rl.job.completed", "workflow.completed", "rl.train.completed"):
|
|
201
218
|
terminal_event_seen = True
|
|
@@ -204,7 +221,6 @@ class RlClient:
|
|
|
204
221
|
terminal_event_seen = True
|
|
205
222
|
terminal_event_status = "failed"
|
|
206
223
|
|
|
207
|
-
# Metrics
|
|
208
224
|
try:
|
|
209
225
|
after = max(last_step_by_name.values()) if last_step_by_name else -1
|
|
210
226
|
points = await self.get_metrics(job_id, after_step=after, limit=200)
|
|
@@ -215,10 +231,8 @@ class RlClient:
|
|
|
215
231
|
continue
|
|
216
232
|
last_step_by_name[name] = step
|
|
217
233
|
if on_metric:
|
|
218
|
-
|
|
234
|
+
with suppress(Exception):
|
|
219
235
|
on_metric(p)
|
|
220
|
-
except Exception:
|
|
221
|
-
pass
|
|
222
236
|
except Exception:
|
|
223
237
|
pass
|
|
224
238
|
|
|
@@ -232,25 +246,23 @@ class RlClient:
|
|
|
232
246
|
else:
|
|
233
247
|
empty_polls = 0
|
|
234
248
|
if empty_polls >= max(1, int(empty_polls_threshold)):
|
|
235
|
-
|
|
249
|
+
with suppress(Exception):
|
|
236
250
|
print(
|
|
237
251
|
f"[poll] threshold hit: empty_polls={empty_polls} >= {empty_polls_threshold} streams={stream_ids} last_seq_map={last_seq_by_stream}"
|
|
238
252
|
)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
253
|
+
raise AssertionError(
|
|
254
|
+
f"No new events detected for {empty_polls_threshold} consecutive polls. Check event ingestion."
|
|
255
|
+
)
|
|
242
256
|
|
|
243
257
|
if not saw_any_event and (time.time() - start_t) > int(startup_deadline_s):
|
|
244
|
-
|
|
258
|
+
with suppress(Exception):
|
|
245
259
|
print(
|
|
246
260
|
f"[poll] startup window exceeded: {startup_deadline_s}s base={self._base_url} job={job_id} streams={stream_ids} last_seq_map={last_seq_by_stream}"
|
|
247
261
|
)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
262
|
+
raise AssertionError(
|
|
263
|
+
f"No events observed within startup window ({startup_deadline_s}s). Investigate event streaming."
|
|
264
|
+
)
|
|
251
265
|
|
|
252
266
|
await sleep(interval_seconds)
|
|
253
267
|
if max_seconds is not None and (time.time() - start_t) >= max_seconds:
|
|
254
268
|
raise TimeoutError(f"Polling timed out after {max_seconds}s for job {job_id}")
|
|
255
|
-
|
|
256
|
-
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _ensure_positive(value: Any, *, name: str) -> int:
|
|
8
|
+
try:
|
|
9
|
+
ivalue = int(value)
|
|
10
|
+
except (TypeError, ValueError) as exc:
|
|
11
|
+
raise ValueError(f"{name} must be an integer") from exc
|
|
12
|
+
if ivalue < 1:
|
|
13
|
+
raise ValueError(f"{name} must be >= 1")
|
|
14
|
+
return ivalue
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(slots=True)
|
|
18
|
+
class RLJobConfig:
|
|
19
|
+
model: str
|
|
20
|
+
task_app_url: str
|
|
21
|
+
trainer_id: str
|
|
22
|
+
batch_size: int = 1
|
|
23
|
+
group_size: int = 2
|
|
24
|
+
job_config_id: str | None = None
|
|
25
|
+
inline_config: dict[str, Any] | None = None
|
|
26
|
+
|
|
27
|
+
def trainer_dict(self) -> dict[str, Any]:
|
|
28
|
+
return {
|
|
29
|
+
"batch_size": _ensure_positive(self.batch_size, name="trainer.batch_size"),
|
|
30
|
+
"group_size": _ensure_positive(self.group_size, name="trainer.group_size"),
|
|
31
|
+
}
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
"""Compatibility re-export for rollout contracts used by RL tooling."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Compatibility layer: re-export Task App rollout contracts from synth_ai.task.contracts
|
|
5
|
-
so existing imports continue to work while consolidating under synth_ai.task.
|
|
6
|
-
"""
|
|
3
|
+
from __future__ import annotations
|
|
7
4
|
|
|
8
|
-
from synth_ai.task.contracts import (
|
|
5
|
+
from synth_ai.sdk.task.contracts import (
|
|
9
6
|
RolloutEnvSpec,
|
|
7
|
+
RolloutMetrics,
|
|
10
8
|
RolloutPolicySpec,
|
|
11
9
|
RolloutRecordConfig,
|
|
12
|
-
RolloutSafetyConfig,
|
|
13
10
|
RolloutRequest,
|
|
14
|
-
RolloutStep,
|
|
15
|
-
RolloutTrajectory,
|
|
16
|
-
RolloutMetrics,
|
|
17
11
|
RolloutResponse,
|
|
12
|
+
RolloutSafetyConfig,
|
|
18
13
|
)
|
|
19
14
|
|
|
20
15
|
__all__ = [
|
|
@@ -23,10 +18,6 @@ __all__ = [
|
|
|
23
18
|
"RolloutRecordConfig",
|
|
24
19
|
"RolloutSafetyConfig",
|
|
25
20
|
"RolloutRequest",
|
|
26
|
-
"RolloutStep",
|
|
27
|
-
"RolloutTrajectory",
|
|
28
21
|
"RolloutMetrics",
|
|
29
22
|
"RolloutResponse",
|
|
30
23
|
]
|
|
31
|
-
|
|
32
|
-
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
"""Helpers for uploading Environment credentials to the backend."""
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import base64
|
|
6
6
|
import binascii
|
|
7
7
|
import json
|
|
8
|
-
from typing import Any, Dict
|
|
9
8
|
import os
|
|
9
|
+
from typing import Any
|
|
10
10
|
|
|
11
11
|
import requests
|
|
12
12
|
from nacl.public import PublicKey, SealedBox
|
|
@@ -18,14 +18,12 @@ _ALGORITHM = "libsodium.sealedbox.v1"
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def encrypt_for_backend(pubkey_b64: str, secret: str | bytes) -> str:
|
|
21
|
-
"""Encrypt ``secret`` for storage by the backend using libsodium sealed boxes."""
|
|
22
|
-
|
|
23
21
|
if not isinstance(pubkey_b64, str) or not pubkey_b64.strip():
|
|
24
22
|
raise ValueError("public key must be a non-empty base64 string")
|
|
25
23
|
|
|
26
24
|
try:
|
|
27
25
|
key_bytes = base64.b64decode(pubkey_b64, validate=True)
|
|
28
|
-
except binascii.Error as exc:
|
|
26
|
+
except binascii.Error as exc:
|
|
29
27
|
raise ValueError("public key must be base64-encoded") from exc
|
|
30
28
|
|
|
31
29
|
if len(key_bytes) != 32:
|
|
@@ -35,7 +33,7 @@ def encrypt_for_backend(pubkey_b64: str, secret: str | bytes) -> str:
|
|
|
35
33
|
secret_bytes = secret.encode("utf-8")
|
|
36
34
|
elif isinstance(secret, bytes):
|
|
37
35
|
secret_bytes = secret
|
|
38
|
-
else:
|
|
36
|
+
else:
|
|
39
37
|
raise TypeError("secret must be str or bytes")
|
|
40
38
|
|
|
41
39
|
if not secret_bytes:
|
|
@@ -52,20 +50,17 @@ def setup_environment_api_key(
|
|
|
52
50
|
token: str | None = None,
|
|
53
51
|
*,
|
|
54
52
|
timeout: float = 15.0,
|
|
55
|
-
) ->
|
|
56
|
-
"""Upload an ENVIRONMENT_API_KEY to the backend."""
|
|
57
|
-
|
|
53
|
+
) -> dict[str, Any]:
|
|
58
54
|
backend = backend_base.rstrip("/")
|
|
59
55
|
if not backend:
|
|
60
56
|
raise ValueError("backend_base must be provided")
|
|
61
57
|
if not synth_api_key:
|
|
62
58
|
raise ValueError("synth_api_key must be provided")
|
|
63
59
|
|
|
64
|
-
# Require caller-provided plaintext. If not provided, read from ENVIRONMENT_API_KEY.
|
|
65
60
|
plaintext = token if token is not None else os.getenv("ENVIRONMENT_API_KEY", "").strip()
|
|
66
61
|
if not plaintext:
|
|
67
62
|
raise ValueError("ENVIRONMENT_API_KEY must be set (or pass token=...) to upload")
|
|
68
|
-
if not isinstance(plaintext, str):
|
|
63
|
+
if not isinstance(plaintext, str):
|
|
69
64
|
raise TypeError("token must be a string")
|
|
70
65
|
|
|
71
66
|
token_bytes = plaintext.encode("utf-8")
|
|
@@ -81,7 +76,7 @@ def setup_environment_api_key(
|
|
|
81
76
|
|
|
82
77
|
try:
|
|
83
78
|
doc = response.json()
|
|
84
|
-
except ValueError as exc:
|
|
79
|
+
except ValueError as exc:
|
|
85
80
|
raise RuntimeError("backend returned invalid JSON for public key") from exc
|
|
86
81
|
|
|
87
82
|
if not isinstance(doc, dict):
|
|
@@ -91,17 +86,51 @@ def setup_environment_api_key(
|
|
|
91
86
|
if not isinstance(pubkey, str) or not pubkey:
|
|
92
87
|
raise RuntimeError("backend response missing public_key")
|
|
93
88
|
|
|
94
|
-
# The backend currently returns a single algorithm identifier; keep a guard in
|
|
95
|
-
# case future versions change the value and we need to surface that to callers.
|
|
96
89
|
alg = doc.get("alg")
|
|
97
90
|
if alg is not None and alg != _ALGORITHM:
|
|
98
91
|
raise RuntimeError(f"unsupported sealed box algorithm: {alg}")
|
|
99
92
|
|
|
93
|
+
# Diagnostics: safe previews and hashes to correlate with backend logs
|
|
94
|
+
try:
|
|
95
|
+
import hashlib as _hash
|
|
96
|
+
|
|
97
|
+
pk_bytes = base64.b64decode(pubkey, validate=True)
|
|
98
|
+
pk_sha256 = _hash.sha256(pk_bytes).hexdigest()
|
|
99
|
+
print(
|
|
100
|
+
f"[env-keys] public_key: b64_len={len(pubkey)} sha256={pk_sha256} head={pubkey[:16]} tail={pubkey[-16:]}"
|
|
101
|
+
)
|
|
102
|
+
_plen = len(plaintext)
|
|
103
|
+
_ppref = (plaintext[:6] + "…") if _plen > 10 else plaintext
|
|
104
|
+
_psuf = ("…" + plaintext[-4:]) if _plen > 10 else ""
|
|
105
|
+
_has_ws = any(ch.isspace() for ch in plaintext)
|
|
106
|
+
print(
|
|
107
|
+
f"[env-keys] plaintext: len={_plen} preview={_ppref}{_psuf} has_ws={bool(_has_ws)}"
|
|
108
|
+
)
|
|
109
|
+
except Exception:
|
|
110
|
+
pass
|
|
111
|
+
|
|
100
112
|
ciphertext_b64 = encrypt_for_backend(pubkey, token_bytes)
|
|
101
113
|
|
|
102
114
|
body = {"name": "ENVIRONMENT_API_KEY", "ciphertext_b64": ciphertext_b64}
|
|
103
115
|
post_url = f"{backend}/api/v1/env-keys"
|
|
104
|
-
|
|
116
|
+
# Ciphertext diagnostics
|
|
117
|
+
try:
|
|
118
|
+
import hashlib as _hash
|
|
119
|
+
|
|
120
|
+
_ct_bytes = base64.b64decode(ciphertext_b64, validate=True)
|
|
121
|
+
_ct_sha = _hash.sha256(_ct_bytes).hexdigest()
|
|
122
|
+
print(
|
|
123
|
+
f"[env-keys] ciphertext: b64_len={len(ciphertext_b64)} sha256={_ct_sha} head={ciphertext_b64[:16]} tail={ciphertext_b64[-16:]}"
|
|
124
|
+
)
|
|
125
|
+
except Exception:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
response2 = requests.post(
|
|
129
|
+
post_url,
|
|
130
|
+
headers={**headers, "Content-Type": "application/json"},
|
|
131
|
+
json=body,
|
|
132
|
+
timeout=timeout,
|
|
133
|
+
)
|
|
105
134
|
_raise_with_detail(response2)
|
|
106
135
|
|
|
107
136
|
try:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Helpers for generating Environment credentials."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import secrets
|
|
6
|
+
|
|
7
|
+
__all__ = ["mint_environment_api_key"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def mint_environment_api_key() -> str:
|
|
11
|
+
"""Mint a random ENVIRONMENT_API_KEY value."""
|
|
12
|
+
|
|
13
|
+
return secrets.token_hex(32)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from .client import FtClient
|
|
2
|
+
from .data import (
|
|
3
|
+
SFTDataError,
|
|
4
|
+
SFTExample,
|
|
5
|
+
SFTMessage,
|
|
6
|
+
SFTToolCall,
|
|
7
|
+
SFTToolDefinition,
|
|
8
|
+
coerce_example,
|
|
9
|
+
collect_sft_jsonl_errors,
|
|
10
|
+
iter_sft_examples,
|
|
11
|
+
load_jsonl,
|
|
12
|
+
parse_jsonl_line,
|
|
13
|
+
validate_jsonl_or_raise,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"FtClient",
|
|
18
|
+
"SFTDataError",
|
|
19
|
+
"SFTExample",
|
|
20
|
+
"SFTMessage",
|
|
21
|
+
"SFTToolCall",
|
|
22
|
+
"SFTToolDefinition",
|
|
23
|
+
"collect_sft_jsonl_errors",
|
|
24
|
+
"coerce_example",
|
|
25
|
+
"iter_sft_examples",
|
|
26
|
+
"load_jsonl",
|
|
27
|
+
"parse_jsonl_line",
|
|
28
|
+
"validate_jsonl_or_raise",
|
|
29
|
+
]
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from synth_ai.core._utils.http import AsyncHttpClient, HTTPError
|
|
7
|
+
|
|
8
|
+
from .config import prepare_sft_job_payload
|
|
9
|
+
from .data import validate_jsonl_or_raise
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FtClient:
|
|
13
|
+
def __init__(self, base_url: str, api_key: str, *, timeout: float = 30.0) -> None:
|
|
14
|
+
self._base_url = base_url.rstrip("/")
|
|
15
|
+
self._api_key = api_key
|
|
16
|
+
self._timeout = timeout
|
|
17
|
+
|
|
18
|
+
async def upload_training_file(self, path: str | Path, *, purpose: str = "fine-tune") -> str:
|
|
19
|
+
p = Path(path)
|
|
20
|
+
if p.suffix.lower() == ".jsonl" and purpose == "fine-tune":
|
|
21
|
+
validate_jsonl_or_raise(p, min_messages=2)
|
|
22
|
+
content = p.read_bytes()
|
|
23
|
+
async with AsyncHttpClient(self._base_url, self._api_key, timeout=self._timeout) as http:
|
|
24
|
+
data = {"purpose": purpose}
|
|
25
|
+
files = {"file": (p.name, content, _infer_content_type(p.name))}
|
|
26
|
+
js = await http.post_multipart("/api/learning/files", data=data, files=files)
|
|
27
|
+
if not isinstance(js, dict) or "id" not in js:
|
|
28
|
+
raise HTTPError(
|
|
29
|
+
status=500,
|
|
30
|
+
url="/api/learning/files",
|
|
31
|
+
message="invalid_upload_response",
|
|
32
|
+
body_snippet=str(js)[:200],
|
|
33
|
+
)
|
|
34
|
+
return str(js["id"])
|
|
35
|
+
|
|
36
|
+
async def create_sft_job(
|
|
37
|
+
self,
|
|
38
|
+
*,
|
|
39
|
+
model: str,
|
|
40
|
+
training_file_id: str,
|
|
41
|
+
hyperparameters: dict[str, Any],
|
|
42
|
+
metadata: dict[str, Any] | None = None,
|
|
43
|
+
) -> dict[str, Any]:
|
|
44
|
+
body = prepare_sft_job_payload(
|
|
45
|
+
model=model,
|
|
46
|
+
training_file=training_file_id,
|
|
47
|
+
hyperparameters=hyperparameters,
|
|
48
|
+
metadata=metadata,
|
|
49
|
+
training_type="sft_offline",
|
|
50
|
+
training_file_field="training_file_id",
|
|
51
|
+
require_training_file=True,
|
|
52
|
+
)
|
|
53
|
+
async with AsyncHttpClient(self._base_url, self._api_key, timeout=self._timeout) as http:
|
|
54
|
+
return await http.post_json("/api/learning/jobs", json=body)
|
|
55
|
+
|
|
56
|
+
async def start_job(self, job_id: str) -> dict[str, Any]:
|
|
57
|
+
async with AsyncHttpClient(self._base_url, self._api_key, timeout=self._timeout) as http:
|
|
58
|
+
return await http.post_json(f"/api/learning/jobs/{job_id}/start", json={})
|
|
59
|
+
|
|
60
|
+
async def get_job_status(self, job_id: str) -> dict[str, Any]:
|
|
61
|
+
"""Get the status and details of an SFT job.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
job_id: The job ID to check
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Job details including status, progress, etc.
|
|
68
|
+
"""
|
|
69
|
+
async with AsyncHttpClient(self._base_url, self._api_key, timeout=self._timeout) as http:
|
|
70
|
+
return await http.get(f"/api/learning/jobs/{job_id}")
|
|
71
|
+
|
|
72
|
+
async def list_jobs(self, *, limit: int = 50, offset: int = 0) -> list[dict[str, Any]]:
|
|
73
|
+
"""List SFT jobs.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
limit: Max number of jobs to return
|
|
77
|
+
offset: Pagination offset
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
List of job objects
|
|
81
|
+
"""
|
|
82
|
+
async with AsyncHttpClient(self._base_url, self._api_key, timeout=self._timeout) as http:
|
|
83
|
+
result = await http.get(f"/api/learning/jobs?limit={limit}&offset={offset}")
|
|
84
|
+
return result if isinstance(result, list) else result.get("jobs", [])
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _infer_content_type(filename: str) -> str:
|
|
88
|
+
name = filename.lower()
|
|
89
|
+
if name.endswith(".jsonl"):
|
|
90
|
+
return "application/jsonl"
|
|
91
|
+
if name.endswith(".json"):
|
|
92
|
+
return "application/json"
|
|
93
|
+
if name.endswith(".txt"):
|
|
94
|
+
return "text/plain"
|
|
95
|
+
return "application/octet-stream"
|