synth-ai 0.2.14__py3-none-any.whl → 0.2.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of synth-ai might be problematic. Click here for more details.
- examples/README.md +1 -0
- examples/analyze_semantic_words.sh +2 -2
- examples/blog_posts/pokemon_vl/README.md +98 -0
- examples/blog_posts/pokemon_vl/configs/eval_qwen3_vl.toml +25 -0
- examples/blog_posts/pokemon_vl/configs/eval_rl_final.toml +24 -0
- examples/blog_posts/pokemon_vl/configs/filter_high_reward.toml +10 -0
- examples/blog_posts/pokemon_vl/configs/train_rl_from_sft.toml +42 -0
- examples/blog_posts/pokemon_vl/configs/train_sft_qwen4b_vl.toml +40 -0
- examples/blog_posts/warming_up_to_rl/README.md +158 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_groq_qwen32b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_openai_gpt_oss_120b.toml +29 -0
- examples/blog_posts/warming_up_to_rl/configs/filter_high_reward_dataset.toml +10 -0
- examples/blog_posts/warming_up_to_rl/configs/train_rl_from_sft.toml +41 -0
- examples/blog_posts/warming_up_to_rl/configs/train_sft_qwen4b.toml +40 -0
- examples/dev/qwen3_32b_qlora_4xh100.toml +5 -0
- examples/multi_step/SFT_README.md +147 -0
- examples/multi_step/configs/crafter_rl_outcome.toml +1 -1
- examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +73 -115
- examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +1 -1
- examples/multi_step/configs/crafter_rl_stepwise_simple.toml +1 -1
- examples/multi_step/configs/crafter_rl_stepwise_simple_NEW_FORMAT.toml +105 -0
- examples/multi_step/configs/crafter_sft_qwen30b_lora.toml +62 -0
- examples/multi_step/configs/verilog_rl_lora.toml +80 -123
- examples/multi_step/convert_traces_to_sft.py +84 -0
- examples/multi_step/run_sft_qwen30b.sh +45 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +1 -2
- examples/qwen_coder/configs/coder_lora_4b.toml +5 -1
- examples/qwen_coder/configs/coder_lora_small.toml +1 -2
- examples/qwen_vl/BUGS_AND_FIXES.md +232 -0
- examples/qwen_vl/IMAGE_VALIDATION_COMPLETE.md +271 -0
- examples/qwen_vl/IMAGE_VALIDATION_SUMMARY.md +260 -0
- examples/qwen_vl/INFERENCE_SFT_TESTS.md +412 -0
- examples/qwen_vl/NEXT_STEPS_2B.md +325 -0
- examples/qwen_vl/QUICKSTART.md +327 -0
- examples/qwen_vl/QUICKSTART_RL_VISION.md +110 -0
- examples/qwen_vl/README.md +152 -0
- examples/qwen_vl/RL_VISION_COMPLETE.md +475 -0
- examples/qwen_vl/RL_VISION_TESTING.md +333 -0
- examples/qwen_vl/SDK_VISION_INTEGRATION.md +328 -0
- examples/qwen_vl/SETUP_COMPLETE.md +274 -0
- examples/qwen_vl/VISION_TESTS_COMPLETE.md +489 -0
- examples/qwen_vl/VLM_PIPELINE_COMPLETE.md +242 -0
- examples/qwen_vl/__init__.py +2 -0
- examples/qwen_vl/collect_data_via_cli.md +415 -0
- examples/qwen_vl/collect_vision_traces.py +368 -0
- examples/qwen_vl/configs/crafter_rl_vision_qwen3vl4b.toml +110 -0
- examples/qwen_vl/configs/crafter_vlm_sft_example.toml +59 -0
- examples/qwen_vl/configs/eval_gpt4o_mini_vision.toml +26 -0
- examples/qwen_vl/configs/eval_gpt4o_vision_proper.toml +29 -0
- examples/qwen_vl/configs/eval_gpt5nano_vision.toml +26 -0
- examples/qwen_vl/configs/eval_qwen3vl_vision.toml +26 -0
- examples/qwen_vl/configs/filter_qwen3vl_sft.toml +49 -0
- examples/qwen_vl/configs/filter_vision_sft.toml +52 -0
- examples/qwen_vl/configs/filter_vision_test.toml +8 -0
- examples/qwen_vl/configs/sft_qwen3_vl_2b_test.toml +54 -0
- examples/qwen_vl/crafter_gpt5nano_agent.py +308 -0
- examples/qwen_vl/crafter_qwen_vl_agent.py +300 -0
- examples/qwen_vl/run_vision_comparison.sh +61 -0
- examples/qwen_vl/run_vision_sft_pipeline.sh +175 -0
- examples/qwen_vl/test_image_validation.py +201 -0
- examples/qwen_vl/test_sft_vision_data.py +110 -0
- examples/rl/README.md +6 -6
- examples/rl/configs/eval_base_qwen.toml +17 -0
- examples/rl/configs/eval_rl_qwen.toml +13 -0
- examples/rl/configs/rl_from_base_qwen.toml +62 -0
- examples/rl/configs/rl_from_base_qwen17.toml +79 -0
- examples/rl/configs/rl_from_ft_qwen.toml +37 -0
- examples/rl/run_eval.py +436 -0
- examples/rl/run_rl_and_save.py +111 -0
- examples/rl/task_app/README.md +21 -0
- examples/rl/task_app/math_single_step.py +990 -0
- examples/rl/task_app/math_task_app.py +111 -0
- examples/run_crafter_demo.sh +2 -2
- examples/sft/README.md +6 -6
- examples/sft/configs/crafter_fft_qwen0p6b.toml +7 -2
- examples/sft/configs/crafter_lora_qwen0p6b.toml +7 -3
- examples/sft/evaluate.py +2 -4
- examples/sft/export_dataset.py +7 -4
- examples/swe/task_app/README.md +33 -3
- examples/swe/task_app/grpo_swe_mini.py +4 -1
- examples/swe/task_app/grpo_swe_mini_task_app.py +0 -12
- examples/swe/task_app/hosted/envs/crafter/react_agent.py +1 -1
- examples/swe/task_app/hosted/envs/mini_swe/environment.py +50 -23
- examples/swe/task_app/hosted/inference/openai_client.py +4 -4
- examples/swe/task_app/hosted/policy_routes.py +0 -2
- examples/swe/task_app/hosted/rollout.py +0 -8
- examples/swe/task_app/morph_backend.py +178 -0
- examples/task_apps/crafter/task_app/README.md +1 -1
- examples/task_apps/crafter/task_app/grpo_crafter.py +70 -10
- examples/task_apps/crafter/task_app/grpo_crafter_task_app.py +1 -1
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/policy.py +63 -27
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/react_agent.py +1 -2
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/openai_client.py +48 -50
- examples/task_apps/crafter/task_app/synth_envs_hosted/policy_routes.py +75 -36
- examples/task_apps/crafter/task_app/synth_envs_hosted/rollout.py +31 -15
- examples/task_apps/enron/__init__.py +1 -0
- examples/task_apps/enron/task_app/grpo_enron_task_app.py +1 -1
- examples/task_apps/math/README.md +1 -2
- examples/task_apps/pokemon_red/README.md +3 -4
- examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +6 -5
- examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +1 -2
- examples/task_apps/pokemon_red/task_app.py +36 -5
- examples/task_apps/sokoban/README.md +2 -3
- examples/task_apps/verilog/eval_groq_qwen32b.toml +12 -14
- examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +1 -1
- examples/vlm/README.md +3 -3
- examples/vlm/configs/crafter_vlm_gpt4o.toml +5 -0
- examples/vlm/crafter_openai_vlm_agent.py +3 -5
- examples/vlm/filter_image_rows.py +1 -1
- examples/vlm/run_crafter_vlm_benchmark.py +2 -2
- examples/warming_up_to_rl/_utils.py +92 -0
- examples/warming_up_to_rl/analyze_trace_db.py +1 -1
- examples/warming_up_to_rl/configs/crafter_fft.toml +5 -0
- examples/warming_up_to_rl/configs/eval_fft_qwen4b.toml +2 -0
- examples/warming_up_to_rl/configs/eval_groq_qwen32b.toml +2 -0
- examples/warming_up_to_rl/configs/eval_modal_qwen4b.toml +2 -1
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +2 -1
- examples/warming_up_to_rl/configs/rl_from_ft.toml +2 -0
- examples/warming_up_to_rl/export_trace_sft.py +174 -60
- examples/warming_up_to_rl/readme.md +63 -132
- examples/warming_up_to_rl/run_fft_and_save.py +1 -1
- examples/warming_up_to_rl/run_local_rollout_traced.py +1 -1
- examples/warming_up_to_rl/run_rl_and_save.py +1 -1
- examples/warming_up_to_rl/task_app/README.md +42 -0
- examples/warming_up_to_rl/task_app/grpo_crafter.py +827 -0
- examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +135 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/README.md +173 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/__init__.py +5 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/branching.py +143 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/environment_routes.py +1226 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/__init__.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/__init__.py +6 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/app.py +1 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/environment.py +522 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +454 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +108 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/shared.py +305 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/tools.py +47 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +204 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/__init__.py +5 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +618 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/main.py +100 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +1084 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/registry.py +195 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/rollout.py +1861 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/__init__.py +5 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/volume.py +211 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_agents.py +161 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/test_service.py +137 -0
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +62 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen.toml +27 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen17.toml +5 -0
- synth_ai/__init__.py +44 -30
- synth_ai/_utils/__init__.py +47 -0
- synth_ai/_utils/base_url.py +10 -0
- synth_ai/_utils/http.py +10 -0
- synth_ai/_utils/prompts.py +10 -0
- synth_ai/_utils/task_app_state.py +12 -0
- synth_ai/_utils/user_config.py +10 -0
- synth_ai/api/models/supported.py +144 -7
- synth_ai/api/train/__init__.py +13 -1
- synth_ai/api/train/builders.py +9 -3
- synth_ai/api/train/cli.py +155 -17
- synth_ai/api/train/config_finder.py +18 -11
- synth_ai/api/train/configs/__init__.py +8 -1
- synth_ai/api/train/configs/rl.py +32 -7
- synth_ai/api/train/configs/sft.py +6 -2
- synth_ai/api/train/configs/shared.py +59 -2
- synth_ai/api/train/env_resolver.py +13 -10
- synth_ai/auth/credentials.py +119 -0
- synth_ai/cli/__init__.py +61 -69
- synth_ai/cli/_modal_wrapper.py +7 -5
- synth_ai/cli/_typer_patch.py +0 -2
- synth_ai/cli/_validate_task_app.py +22 -4
- synth_ai/cli/commands/__init__.py +17 -0
- synth_ai/cli/commands/demo/__init__.py +6 -0
- synth_ai/cli/commands/demo/core.py +163 -0
- synth_ai/cli/commands/deploy/__init__.py +23 -0
- synth_ai/cli/commands/deploy/core.py +614 -0
- synth_ai/cli/commands/deploy/errors.py +72 -0
- synth_ai/cli/commands/deploy/validation.py +11 -0
- synth_ai/cli/commands/eval/__init__.py +19 -0
- synth_ai/cli/commands/eval/core.py +1109 -0
- synth_ai/cli/commands/eval/errors.py +81 -0
- synth_ai/cli/commands/eval/validation.py +133 -0
- synth_ai/cli/commands/filter/__init__.py +12 -0
- synth_ai/cli/commands/filter/core.py +388 -0
- synth_ai/cli/commands/filter/errors.py +55 -0
- synth_ai/cli/commands/filter/validation.py +77 -0
- synth_ai/cli/commands/help/__init__.py +177 -0
- synth_ai/cli/commands/help/core.py +73 -0
- synth_ai/cli/commands/status/__init__.py +64 -0
- synth_ai/cli/commands/status/client.py +192 -0
- synth_ai/cli/commands/status/config.py +92 -0
- synth_ai/cli/commands/status/errors.py +20 -0
- synth_ai/cli/commands/status/formatters.py +164 -0
- synth_ai/cli/commands/status/subcommands/__init__.py +9 -0
- synth_ai/cli/commands/status/subcommands/files.py +79 -0
- synth_ai/cli/commands/status/subcommands/jobs.py +334 -0
- synth_ai/cli/commands/status/subcommands/models.py +79 -0
- synth_ai/cli/commands/status/subcommands/runs.py +81 -0
- synth_ai/cli/commands/status/subcommands/summary.py +47 -0
- synth_ai/cli/commands/status/utils.py +114 -0
- synth_ai/cli/commands/train/__init__.py +53 -0
- synth_ai/cli/commands/train/core.py +21 -0
- synth_ai/cli/commands/train/errors.py +117 -0
- synth_ai/cli/commands/train/judge_schemas.py +199 -0
- synth_ai/cli/commands/train/judge_validation.py +304 -0
- synth_ai/cli/commands/train/validation.py +443 -0
- synth_ai/cli/demo.py +2 -162
- synth_ai/cli/deploy/__init__.py +28 -0
- synth_ai/cli/deploy/core.py +5 -0
- synth_ai/cli/deploy/errors.py +23 -0
- synth_ai/cli/deploy/validation.py +5 -0
- synth_ai/cli/eval/__init__.py +36 -0
- synth_ai/cli/eval/core.py +5 -0
- synth_ai/cli/eval/errors.py +31 -0
- synth_ai/cli/eval/validation.py +5 -0
- synth_ai/cli/filter/__init__.py +28 -0
- synth_ai/cli/filter/core.py +5 -0
- synth_ai/cli/filter/errors.py +23 -0
- synth_ai/cli/filter/validation.py +5 -0
- synth_ai/cli/legacy_root_backup.py +3 -1
- synth_ai/cli/lib/__init__.py +10 -0
- synth_ai/cli/lib/task_app_discovery.py +7 -0
- synth_ai/cli/lib/task_app_env.py +518 -0
- synth_ai/cli/modal_serve/__init__.py +12 -0
- synth_ai/cli/modal_serve/core.py +14 -0
- synth_ai/cli/modal_serve/errors.py +8 -0
- synth_ai/cli/modal_serve/validation.py +11 -0
- synth_ai/cli/recent.py +2 -1
- synth_ai/cli/serve/__init__.py +12 -0
- synth_ai/cli/serve/core.py +14 -0
- synth_ai/cli/serve/errors.py +8 -0
- synth_ai/cli/serve/validation.py +11 -0
- synth_ai/cli/setup.py +21 -0
- synth_ai/cli/status.py +7 -126
- synth_ai/cli/task_app_deploy.py +7 -0
- synth_ai/cli/task_app_list.py +25 -0
- synth_ai/cli/task_app_modal_serve.py +11 -0
- synth_ai/cli/task_app_serve.py +11 -0
- synth_ai/cli/task_apps.py +110 -1499
- synth_ai/cli/traces.py +1 -1
- synth_ai/cli/train/__init__.py +12 -0
- synth_ai/cli/train/core.py +21 -0
- synth_ai/cli/train/errors.py +8 -0
- synth_ai/cli/train/validation.py +24 -0
- synth_ai/cli/train.py +5 -0
- synth_ai/cli/turso.py +1 -1
- synth_ai/cli/watch.py +1 -1
- synth_ai/demos/__init__.py +10 -0
- synth_ai/demos/core/__init__.py +28 -1
- synth_ai/demos/crafter/__init__.py +1 -0
- synth_ai/demos/crafter/crafter_fft_4b.toml +55 -0
- synth_ai/demos/crafter/grpo_crafter_task_app.py +185 -0
- synth_ai/demos/crafter/rl_from_base_qwen4b.toml +74 -0
- synth_ai/demos/demo_registry.py +176 -0
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +1 -1
- synth_ai/demos/math/__init__.py +1 -0
- synth_ai/demos/math/_common.py +16 -0
- synth_ai/demos/math/app.py +38 -0
- synth_ai/demos/math/config.toml +76 -0
- synth_ai/demos/math/deploy_modal.py +54 -0
- synth_ai/demos/math/modal_task_app.py +702 -0
- synth_ai/demos/math/task_app_entry.py +51 -0
- synth_ai/environments/environment/core.py +7 -1
- synth_ai/environments/examples/bandit/engine.py +0 -1
- synth_ai/environments/examples/bandit/environment.py +0 -1
- synth_ai/environments/examples/red/engine.py +33 -12
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +151 -179
- synth_ai/environments/examples/red/environment.py +26 -0
- synth_ai/environments/examples/red/trace_hooks_v3.py +168 -0
- synth_ai/environments/examples/wordle/environment.py +0 -1
- synth_ai/evals/base.py +16 -5
- synth_ai/evals/client.py +1 -1
- synth_ai/http.py +8 -22
- synth_ai/inference/client.py +1 -1
- synth_ai/judge_schemas.py +4 -5
- synth_ai/learning/client.py +1 -1
- synth_ai/learning/health.py +1 -1
- synth_ai/learning/jobs.py +1 -1
- synth_ai/learning/rl/client.py +4 -2
- synth_ai/learning/rl/env_keys.py +1 -1
- synth_ai/learning/rl/secrets.py +1 -1
- synth_ai/learning/sft/client.py +1 -1
- synth_ai/learning/sft/data.py +407 -4
- synth_ai/learning/validators.py +4 -1
- synth_ai/streaming/__init__.py +29 -0
- synth_ai/streaming/config.py +94 -0
- synth_ai/streaming/handlers.py +469 -0
- synth_ai/streaming/streamer.py +301 -0
- synth_ai/streaming/types.py +95 -0
- synth_ai/task/apps/__init__.py +4 -2
- synth_ai/task/config.py +6 -4
- synth_ai/task/rubrics/__init__.py +1 -2
- synth_ai/task/rubrics/loaders.py +14 -10
- synth_ai/task/rubrics.py +219 -0
- synth_ai/task/trace_correlation_helpers.py +24 -11
- synth_ai/task/tracing_utils.py +14 -3
- synth_ai/task/validators.py +0 -1
- synth_ai/tracing_v3/abstractions.py +3 -3
- synth_ai/tracing_v3/config.py +15 -13
- synth_ai/tracing_v3/constants.py +21 -0
- synth_ai/tracing_v3/db_config.py +3 -1
- synth_ai/tracing_v3/decorators.py +10 -7
- synth_ai/tracing_v3/llm_call_record_helpers.py +5 -5
- synth_ai/tracing_v3/migration_helper.py +1 -2
- synth_ai/tracing_v3/session_tracer.py +7 -7
- synth_ai/tracing_v3/storage/base.py +29 -29
- synth_ai/tracing_v3/storage/config.py +3 -3
- synth_ai/tracing_v3/turso/daemon.py +8 -9
- synth_ai/tracing_v3/turso/native_manager.py +80 -72
- synth_ai/tracing_v3/utils.py +2 -2
- synth_ai/utils/__init__.py +101 -0
- synth_ai/utils/base_url.py +94 -0
- synth_ai/utils/cli.py +131 -0
- synth_ai/utils/env.py +294 -0
- synth_ai/utils/http.py +172 -0
- synth_ai/utils/modal.py +308 -0
- synth_ai/utils/process.py +212 -0
- synth_ai/utils/prompts.py +39 -0
- synth_ai/utils/sqld.py +122 -0
- synth_ai/utils/task_app_discovery.py +882 -0
- synth_ai/utils/task_app_env.py +186 -0
- synth_ai/utils/task_app_state.py +318 -0
- synth_ai/utils/user_config.py +137 -0
- synth_ai/v0/config/__init__.py +1 -5
- synth_ai/v0/config/base_url.py +1 -7
- synth_ai/v0/tracing/config.py +1 -1
- synth_ai/v0/tracing/decorators.py +1 -1
- synth_ai/v0/tracing/upload.py +1 -1
- synth_ai/v0/tracing_v1/config.py +1 -1
- synth_ai/v0/tracing_v1/decorators.py +1 -1
- synth_ai/v0/tracing_v1/upload.py +1 -1
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/METADATA +91 -32
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/RECORD +341 -154
- synth_ai/cli/man.py +0 -106
- synth_ai/cli/tui.py +0 -57
- synth_ai/compound/cais.py +0 -0
- synth_ai/core/experiment.py +0 -13
- synth_ai/core/system.py +0 -15
- synth_ai/demo_registry.py +0 -295
- synth_ai/handshake.py +0 -109
- synth_ai/tui/__init__.py +0 -5
- synth_ai/tui/__main__.py +0 -13
- synth_ai/tui/cli/__init__.py +0 -1
- synth_ai/tui/cli/query_experiments.py +0 -164
- synth_ai/tui/cli/query_experiments_v3.py +0 -164
- synth_ai/tui/dashboard.py +0 -906
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.14.dist-info → synth_ai-0.2.17.dist-info}/top_level.txt +0 -0
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Query experiments and sessions from Turso/sqld using v3 tracing.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import argparse
|
|
7
|
-
import asyncio
|
|
8
|
-
|
|
9
|
-
from synth_ai.tracing_v3.turso.manager import AsyncSQLTraceManager
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
async def list_experiments(db_url: str):
|
|
13
|
-
"""List all experiments in the database."""
|
|
14
|
-
db = AsyncSQLTraceManager(db_url)
|
|
15
|
-
await db.initialize()
|
|
16
|
-
|
|
17
|
-
try:
|
|
18
|
-
df = await db.query_traces("""
|
|
19
|
-
SELECT
|
|
20
|
-
e.experiment_id,
|
|
21
|
-
e.name,
|
|
22
|
-
e.description,
|
|
23
|
-
e.created_at,
|
|
24
|
-
COUNT(DISTINCT st.session_id) as num_sessions,
|
|
25
|
-
COUNT(DISTINCT ev.id) as num_events,
|
|
26
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.cost_usd ELSE 0 END) / 100.0 as total_cost,
|
|
27
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.total_tokens ELSE 0 END) as total_tokens
|
|
28
|
-
FROM experiments e
|
|
29
|
-
LEFT JOIN session_traces st ON e.experiment_id = st.experiment_id
|
|
30
|
-
LEFT JOIN events ev ON st.session_id = ev.session_id
|
|
31
|
-
GROUP BY e.experiment_id, e.name, e.description, e.created_at
|
|
32
|
-
ORDER BY e.created_at DESC
|
|
33
|
-
""")
|
|
34
|
-
|
|
35
|
-
if df.empty:
|
|
36
|
-
print("No experiments found in database.")
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
print(f"\n{'=' * 100}")
|
|
40
|
-
print(f"{'Experiments in ' + db_url:^100}")
|
|
41
|
-
print(f"{'=' * 100}\n")
|
|
42
|
-
|
|
43
|
-
for _, row in df.iterrows():
|
|
44
|
-
print(f"🧪 {row['name']} (id: {row['experiment_id'][:8]}...)")
|
|
45
|
-
print(f" Created: {row['created_at']}")
|
|
46
|
-
print(f" Description: {row['description']}")
|
|
47
|
-
print(f" Sessions: {row['num_sessions']}")
|
|
48
|
-
print(f" Events: {row['num_events']:,}")
|
|
49
|
-
if row["total_cost"] and row["total_cost"] > 0:
|
|
50
|
-
print(f" Cost: ${row['total_cost']:.4f}")
|
|
51
|
-
if row["total_tokens"] and row["total_tokens"] > 0:
|
|
52
|
-
print(f" Tokens: {int(row['total_tokens']):,}")
|
|
53
|
-
print()
|
|
54
|
-
finally:
|
|
55
|
-
await db.close()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
async def show_experiment_details(db_url: str, experiment_id: str):
|
|
59
|
-
"""Show detailed information about a specific experiment."""
|
|
60
|
-
db = AsyncSQLTraceManager(db_url)
|
|
61
|
-
await db.initialize()
|
|
62
|
-
|
|
63
|
-
try:
|
|
64
|
-
# Get experiment info
|
|
65
|
-
exp_df = await db.query_traces(
|
|
66
|
-
"""
|
|
67
|
-
SELECT * FROM experiments WHERE experiment_id LIKE :exp_id
|
|
68
|
-
""",
|
|
69
|
-
{"exp_id": f"{experiment_id}%"},
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
if exp_df.empty:
|
|
73
|
-
print(f"No experiment found matching ID: {experiment_id}")
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
exp = exp_df.iloc[0]
|
|
77
|
-
print(f"\n{'=' * 100}")
|
|
78
|
-
print(f"Experiment: {exp['name']} ({exp['experiment_id']})")
|
|
79
|
-
print(f"{'=' * 100}\n")
|
|
80
|
-
|
|
81
|
-
# Get session statistics
|
|
82
|
-
sessions_df = await db.get_sessions_by_experiment(exp["experiment_id"])
|
|
83
|
-
|
|
84
|
-
if sessions_df:
|
|
85
|
-
print(f"Sessions: {len(sessions_df)}")
|
|
86
|
-
|
|
87
|
-
# Get aggregated stats
|
|
88
|
-
stats_df = await db.query_traces(
|
|
89
|
-
"""
|
|
90
|
-
SELECT
|
|
91
|
-
COUNT(DISTINCT ev.id) as total_events,
|
|
92
|
-
COUNT(DISTINCT m.id) as total_messages,
|
|
93
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.cost_usd ELSE 0 END) / 100.0 as total_cost,
|
|
94
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.total_tokens ELSE 0 END) as total_tokens
|
|
95
|
-
FROM session_traces st
|
|
96
|
-
LEFT JOIN events ev ON st.session_id = ev.session_id
|
|
97
|
-
LEFT JOIN messages m ON st.session_id = m.session_id
|
|
98
|
-
WHERE st.experiment_id = :exp_id
|
|
99
|
-
""",
|
|
100
|
-
{"exp_id": exp["experiment_id"]},
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
if not stats_df.empty:
|
|
104
|
-
stats = stats_df.iloc[0]
|
|
105
|
-
print(f"Total events: {int(stats['total_events']):,}")
|
|
106
|
-
print(f"Total messages: {int(stats['total_messages']):,}")
|
|
107
|
-
print(f"Total cost: ${stats['total_cost']:.4f}")
|
|
108
|
-
print(f"Total tokens: {int(stats['total_tokens']):,}")
|
|
109
|
-
|
|
110
|
-
# Show session list
|
|
111
|
-
print("\nSession list:")
|
|
112
|
-
for sess in sessions_df:
|
|
113
|
-
print(f" - {sess['session_id']} ({sess['created_at']})")
|
|
114
|
-
print(
|
|
115
|
-
f" Timesteps: {sess['num_timesteps']}, Events: {sess['num_events']}, Messages: {sess['num_messages']}"
|
|
116
|
-
)
|
|
117
|
-
finally:
|
|
118
|
-
await db.close()
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
async def show_model_usage(db_url: str, model_name: str | None = None):
|
|
122
|
-
"""Show model usage statistics."""
|
|
123
|
-
db = AsyncSQLTraceManager(db_url)
|
|
124
|
-
await db.initialize()
|
|
125
|
-
|
|
126
|
-
try:
|
|
127
|
-
df = await db.get_model_usage(model_name=model_name)
|
|
128
|
-
|
|
129
|
-
if df.empty:
|
|
130
|
-
print("No model usage data found.")
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
print(f"\n{'=' * 100}")
|
|
134
|
-
print(f"{'Model Usage Statistics':^100}")
|
|
135
|
-
print(f"{'=' * 100}\n")
|
|
136
|
-
|
|
137
|
-
print(df.to_string(index=False))
|
|
138
|
-
finally:
|
|
139
|
-
await db.close()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
async def main():
|
|
143
|
-
parser = argparse.ArgumentParser(description="Query experiments from Turso/sqld (v3)")
|
|
144
|
-
parser.add_argument(
|
|
145
|
-
"-u", "--url", default="sqlite+libsql://http://127.0.0.1:8080", help="Turso database URL"
|
|
146
|
-
)
|
|
147
|
-
parser.add_argument(
|
|
148
|
-
"-e", "--experiment", help="Show details for specific experiment ID (can be partial)"
|
|
149
|
-
)
|
|
150
|
-
parser.add_argument("-m", "--model", help="Show usage for specific model")
|
|
151
|
-
parser.add_argument("--usage", action="store_true", help="Show model usage statistics")
|
|
152
|
-
|
|
153
|
-
args = parser.parse_args()
|
|
154
|
-
|
|
155
|
-
if args.usage or args.model:
|
|
156
|
-
await show_model_usage(args.url, args.model)
|
|
157
|
-
elif args.experiment:
|
|
158
|
-
await show_experiment_details(args.url, args.experiment)
|
|
159
|
-
else:
|
|
160
|
-
await list_experiments(args.url)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if __name__ == "__main__":
|
|
164
|
-
asyncio.run(main())
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Query experiments and sessions from Turso/sqld using v3 tracing.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import argparse
|
|
7
|
-
import asyncio
|
|
8
|
-
|
|
9
|
-
from synth_ai.tracing_v3.turso.manager import AsyncSQLTraceManager
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
async def list_experiments(db_url: str):
|
|
13
|
-
"""List all experiments in the database."""
|
|
14
|
-
db = AsyncSQLTraceManager(db_url)
|
|
15
|
-
await db.initialize()
|
|
16
|
-
|
|
17
|
-
try:
|
|
18
|
-
df = await db.query_traces("""
|
|
19
|
-
SELECT
|
|
20
|
-
e.experiment_id,
|
|
21
|
-
e.name,
|
|
22
|
-
e.description,
|
|
23
|
-
e.created_at,
|
|
24
|
-
COUNT(DISTINCT st.session_id) as num_sessions,
|
|
25
|
-
COUNT(DISTINCT ev.id) as num_events,
|
|
26
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.cost_usd ELSE 0 END) / 100.0 as total_cost,
|
|
27
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.total_tokens ELSE 0 END) as total_tokens
|
|
28
|
-
FROM experiments e
|
|
29
|
-
LEFT JOIN session_traces st ON e.experiment_id = st.experiment_id
|
|
30
|
-
LEFT JOIN events ev ON st.session_id = ev.session_id
|
|
31
|
-
GROUP BY e.experiment_id, e.name, e.description, e.created_at
|
|
32
|
-
ORDER BY e.created_at DESC
|
|
33
|
-
""")
|
|
34
|
-
|
|
35
|
-
if df.empty:
|
|
36
|
-
print("No experiments found in database.")
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
print(f"\n{'=' * 100}")
|
|
40
|
-
print(f"{'Experiments in ' + db_url:^100}")
|
|
41
|
-
print(f"{'=' * 100}\n")
|
|
42
|
-
|
|
43
|
-
for _, row in df.iterrows():
|
|
44
|
-
print(f"🧪 {row['name']} (id: {row['experiment_id'][:8]}...)")
|
|
45
|
-
print(f" Created: {row['created_at']}")
|
|
46
|
-
print(f" Description: {row['description']}")
|
|
47
|
-
print(f" Sessions: {row['num_sessions']}")
|
|
48
|
-
print(f" Events: {row['num_events']:,}")
|
|
49
|
-
if row["total_cost"] and row["total_cost"] > 0:
|
|
50
|
-
print(f" Cost: ${row['total_cost']:.4f}")
|
|
51
|
-
if row["total_tokens"] and row["total_tokens"] > 0:
|
|
52
|
-
print(f" Tokens: {int(row['total_tokens']):,}")
|
|
53
|
-
print()
|
|
54
|
-
finally:
|
|
55
|
-
await db.close()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
async def show_experiment_details(db_url: str, experiment_id: str):
|
|
59
|
-
"""Show detailed information about a specific experiment."""
|
|
60
|
-
db = AsyncSQLTraceManager(db_url)
|
|
61
|
-
await db.initialize()
|
|
62
|
-
|
|
63
|
-
try:
|
|
64
|
-
# Get experiment info
|
|
65
|
-
exp_df = await db.query_traces(
|
|
66
|
-
"""
|
|
67
|
-
SELECT * FROM experiments WHERE experiment_id LIKE :exp_id
|
|
68
|
-
""",
|
|
69
|
-
{"exp_id": f"{experiment_id}%"},
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
if exp_df.empty:
|
|
73
|
-
print(f"No experiment found matching ID: {experiment_id}")
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
exp = exp_df.iloc[0]
|
|
77
|
-
print(f"\n{'=' * 100}")
|
|
78
|
-
print(f"Experiment: {exp['name']} ({exp['experiment_id']})")
|
|
79
|
-
print(f"{'=' * 100}\n")
|
|
80
|
-
|
|
81
|
-
# Get session statistics
|
|
82
|
-
sessions_df = await db.get_sessions_by_experiment(exp["experiment_id"])
|
|
83
|
-
|
|
84
|
-
if sessions_df:
|
|
85
|
-
print(f"Sessions: {len(sessions_df)}")
|
|
86
|
-
|
|
87
|
-
# Get aggregated stats
|
|
88
|
-
stats_df = await db.query_traces(
|
|
89
|
-
"""
|
|
90
|
-
SELECT
|
|
91
|
-
COUNT(DISTINCT ev.id) as total_events,
|
|
92
|
-
COUNT(DISTINCT m.id) as total_messages,
|
|
93
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.cost_usd ELSE 0 END) / 100.0 as total_cost,
|
|
94
|
-
SUM(CASE WHEN ev.event_type = 'cais' THEN ev.total_tokens ELSE 0 END) as total_tokens
|
|
95
|
-
FROM session_traces st
|
|
96
|
-
LEFT JOIN events ev ON st.session_id = ev.session_id
|
|
97
|
-
LEFT JOIN messages m ON st.session_id = m.session_id
|
|
98
|
-
WHERE st.experiment_id = :exp_id
|
|
99
|
-
""",
|
|
100
|
-
{"exp_id": exp["experiment_id"]},
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
if not stats_df.empty:
|
|
104
|
-
stats = stats_df.iloc[0]
|
|
105
|
-
print(f"Total events: {int(stats['total_events']):,}")
|
|
106
|
-
print(f"Total messages: {int(stats['total_messages']):,}")
|
|
107
|
-
print(f"Total cost: ${stats['total_cost']:.4f}")
|
|
108
|
-
print(f"Total tokens: {int(stats['total_tokens']):,}")
|
|
109
|
-
|
|
110
|
-
# Show session list
|
|
111
|
-
print("\nSession list:")
|
|
112
|
-
for sess in sessions_df:
|
|
113
|
-
print(f" - {sess['session_id']} ({sess['created_at']})")
|
|
114
|
-
print(
|
|
115
|
-
f" Timesteps: {sess['num_timesteps']}, Events: {sess['num_events']}, Messages: {sess['num_messages']}"
|
|
116
|
-
)
|
|
117
|
-
finally:
|
|
118
|
-
await db.close()
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
async def show_model_usage(db_url: str, model_name: str | None = None):
|
|
122
|
-
"""Show model usage statistics."""
|
|
123
|
-
db = AsyncSQLTraceManager(db_url)
|
|
124
|
-
await db.initialize()
|
|
125
|
-
|
|
126
|
-
try:
|
|
127
|
-
df = await db.get_model_usage(model_name=model_name)
|
|
128
|
-
|
|
129
|
-
if df.empty:
|
|
130
|
-
print("No model usage data found.")
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
print(f"\n{'=' * 100}")
|
|
134
|
-
print(f"{'Model Usage Statistics':^100}")
|
|
135
|
-
print(f"{'=' * 100}\n")
|
|
136
|
-
|
|
137
|
-
print(df.to_string(index=False))
|
|
138
|
-
finally:
|
|
139
|
-
await db.close()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
async def main():
|
|
143
|
-
parser = argparse.ArgumentParser(description="Query experiments from Turso/sqld (v3)")
|
|
144
|
-
parser.add_argument(
|
|
145
|
-
"-u", "--url", default="sqlite+libsql://http://127.0.0.1:8080", help="Turso database URL"
|
|
146
|
-
)
|
|
147
|
-
parser.add_argument(
|
|
148
|
-
"-e", "--experiment", help="Show details for specific experiment ID (can be partial)"
|
|
149
|
-
)
|
|
150
|
-
parser.add_argument("-m", "--model", help="Show usage for specific model")
|
|
151
|
-
parser.add_argument("--usage", action="store_true", help="Show model usage statistics")
|
|
152
|
-
|
|
153
|
-
args = parser.parse_args()
|
|
154
|
-
|
|
155
|
-
if args.usage or args.model:
|
|
156
|
-
await show_model_usage(args.url, args.model)
|
|
157
|
-
elif args.experiment:
|
|
158
|
-
await show_experiment_details(args.url, args.experiment)
|
|
159
|
-
else:
|
|
160
|
-
await list_experiments(args.url)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if __name__ == "__main__":
|
|
164
|
-
asyncio.run(main())
|