synth-ai 0.2.8.dev4__py3-none-any.whl → 0.2.23.dev3__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.
- examples/README.md +1 -0
- examples/__init__.py +16 -0
- examples/analyze_semantic_words.sh +17 -0
- examples/baseline/banking77_baseline.py +243 -0
- examples/baseline/banking77_pipeline_baseline.py +294 -0
- examples/baseline/crafter_baseline.py +407 -0
- examples/baseline/pokemon_red_baseline.py +326 -0
- examples/baseline/simple_baseline.py +56 -0
- examples/baseline/warming_up_to_rl_baseline.py +239 -0
- examples/blog_posts/gepa/README.md +355 -0
- examples/blog_posts/gepa/configs/banking77_gepa_local.toml +95 -0
- examples/blog_posts/gepa/configs/banking77_gepa_test.toml +80 -0
- examples/blog_posts/gepa/configs/banking77_mipro_local.toml +50 -0
- examples/blog_posts/gepa/configs/banking77_pipeline_gepa_local.toml +101 -0
- examples/blog_posts/gepa/configs/banking77_pipeline_gepa_test.toml +96 -0
- examples/blog_posts/gepa/configs/hotpotqa_gepa_local.toml +57 -0
- examples/blog_posts/gepa/configs/hotpotqa_gepa_qwen.toml +35 -0
- examples/blog_posts/gepa/configs/hotpotqa_mipro_local.toml +51 -0
- examples/blog_posts/gepa/configs/hover_gepa_local.toml +57 -0
- examples/blog_posts/gepa/configs/hover_gepa_qwen.toml +35 -0
- examples/blog_posts/gepa/configs/hover_mipro_local.toml +51 -0
- examples/blog_posts/gepa/configs/ifbench_gepa_local.toml +57 -0
- examples/blog_posts/gepa/configs/ifbench_gepa_qwen.toml +35 -0
- examples/blog_posts/gepa/configs/ifbench_mipro_local.toml +51 -0
- examples/blog_posts/gepa/configs/pupa_gepa_local.toml +58 -0
- examples/blog_posts/gepa/configs/pupa_mipro_local.toml +52 -0
- examples/blog_posts/gepa/deploy_banking77_task_app.sh +54 -0
- examples/blog_posts/gepa/gepa_baseline.py +204 -0
- examples/blog_posts/gepa/query_prompts_example.py +97 -0
- examples/blog_posts/gepa/run_gepa_banking77.sh +112 -0
- examples/blog_posts/gepa/run_gepa_banking77_pipeline.sh +163 -0
- examples/blog_posts/gepa/task_apps.py +105 -0
- examples/blog_posts/gepa/test_gepa_local.sh +67 -0
- examples/blog_posts/gepa/verify_banking77_setup.sh +123 -0
- examples/blog_posts/mipro/README.md +415 -0
- examples/blog_posts/mipro/configs/banking77_mipro_local.toml +91 -0
- examples/blog_posts/mipro/configs/banking77_mipro_test.toml +87 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_gemini_flash_lite_local.toml +98 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_gpt41mini_local.toml +96 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_local.toml +94 -0
- examples/blog_posts/mipro/configs/banking77_pipeline_mipro_test.toml +170 -0
- examples/blog_posts/mipro/deploy_banking77_pipeline_task_app.sh +59 -0
- examples/blog_posts/mipro/deploy_banking77_task_app.sh +41 -0
- examples/blog_posts/mipro/multi_step.md +79 -0
- examples/blog_posts/mipro/run_mipro_banking77.sh +191 -0
- examples/blog_posts/mipro/run_mipro_banking77_pipeline.sh +171 -0
- examples/blog_posts/mipro/run_mipro_banking77_pipeline_gemini_flash_lite.sh +177 -0
- examples/blog_posts/mipro/run_mipro_banking77_pipeline_gpt41mini.sh +173 -0
- examples/blog_posts/mipro/verify_banking77_setup.sh +117 -0
- examples/blog_posts/pokemon_vl/README.md +98 -0
- examples/blog_posts/pokemon_vl/configs/eval_gpt5nano.toml +26 -0
- examples/blog_posts/pokemon_vl/configs/eval_qwen3_vl.toml +27 -0
- examples/blog_posts/pokemon_vl/configs/eval_rl_final.toml +24 -0
- examples/blog_posts/pokemon_vl/configs/filter_high_reward.toml +10 -0
- examples/blog_posts/pokemon_vl/configs/train_rl_from_sft.toml +43 -0
- examples/blog_posts/pokemon_vl/configs/train_sft_qwen4b_vl.toml +40 -0
- examples/blog_posts/pokemon_vl/extract_images.py +239 -0
- examples/blog_posts/pokemon_vl/pokemon_vl_baseline.py +326 -0
- examples/blog_posts/pokemon_vl/run_eval_extract_images.py +209 -0
- examples/blog_posts/pokemon_vl/run_qwen_eval_extract_images.py +212 -0
- examples/blog_posts/pokemon_vl/text_box_analysis.md +106 -0
- examples/blog_posts/warming_up_to_rl/ARCHITECTURE.md +195 -0
- examples/blog_posts/warming_up_to_rl/FINAL_TEST_RESULTS.md +127 -0
- examples/blog_posts/warming_up_to_rl/INFERENCE_SUCCESS.md +132 -0
- examples/blog_posts/warming_up_to_rl/README.md +158 -0
- examples/blog_posts/warming_up_to_rl/SMOKE_TESTING.md +164 -0
- examples/blog_posts/warming_up_to_rl/SMOKE_TEST_COMPLETE.md +253 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_baseline_qwen32b_10x20.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_ft_qwen4b_10x20.toml +26 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_groq_qwen32b.toml +25 -0
- examples/blog_posts/warming_up_to_rl/configs/eval_openai_gpt_oss_120b.toml +29 -0
- examples/blog_posts/warming_up_to_rl/configs/filter_high_reward_dataset.toml +10 -0
- examples/blog_posts/warming_up_to_rl/configs/smoke_test.toml +75 -0
- examples/blog_posts/warming_up_to_rl/configs/train_rl_from_sft.toml +91 -0
- examples/blog_posts/warming_up_to_rl/configs/train_sft_qwen4b.toml +40 -0
- examples/blog_posts/warming_up_to_rl/warming_up_to_rl_baseline.py +187 -0
- examples/crafter_debug_render.py +186 -0
- examples/dev/qwen3_32b_qlora_4xh100.toml +45 -0
- examples/gepa/banking77_pipeline_gepa.toml +96 -0
- examples/gepa/multi_stage_gepa_example.toml +84 -0
- examples/gepa/run_gepa_banking77_pipeline.sh +157 -0
- examples/multi_step/SFT_README.md +147 -0
- examples/multi_step/configs/README_verilog_rl.md +77 -0
- examples/multi_step/configs/VERILOG_REWARDS.md +103 -0
- examples/multi_step/configs/VERILOG_RL_CHECKLIST.md +196 -0
- examples/multi_step/configs/crafter_eval_synth_qwen4b.toml +35 -0
- examples/multi_step/configs/crafter_eval_text_only_groq_qwen32b.toml +36 -0
- examples/multi_step/configs/crafter_rl_outcome.toml +75 -0
- examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +145 -0
- examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +84 -0
- examples/multi_step/configs/crafter_rl_stepwise_simple.toml +79 -0
- 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/crafter_synth_backend.md +40 -0
- examples/multi_step/configs/verilog_eval_groq_qwen32b.toml +31 -0
- examples/multi_step/configs/verilog_eval_synth_qwen8b.toml +33 -0
- examples/multi_step/configs/verilog_rl_lora.toml +147 -0
- examples/multi_step/convert_traces_to_sft.py +84 -0
- examples/multi_step/crafter_rl_lora.md +70 -0
- examples/multi_step/judges/crafter_backend_judge.py +220 -0
- examples/multi_step/judges/verilog_backend_judge.py +234 -0
- examples/multi_step/readme.md +48 -0
- examples/multi_step/run_sft_qwen30b.sh +45 -0
- examples/multi_step/sse_metrics_streaming_notes.md +357 -0
- examples/multi_step/task_app_config_notes.md +494 -0
- examples/multi_step/verilog_rl_lora.md +218 -0
- examples/qwen_coder/README.md +102 -0
- examples/qwen_coder/_shared.py +113 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +60 -0
- examples/qwen_coder/configs/coder_lora_4b.toml +61 -0
- examples/qwen_coder/configs/coder_lora_small.toml +57 -0
- examples/qwen_coder/generate_dataset.py +98 -0
- examples/qwen_coder/infer_ft_smoke.py +65 -0
- examples/qwen_coder/infer_prod_proxy.py +73 -0
- examples/qwen_coder/infer_via_synth.py +87 -0
- examples/qwen_coder/scripts/infer_coder.sh +19 -0
- examples/qwen_coder/scripts/train_coder_30b.sh +22 -0
- examples/qwen_coder/sft_full_17b.py +103 -0
- examples/qwen_coder/sft_lora_30b.py +110 -0
- examples/qwen_coder/subset_jsonl.py +39 -0
- examples/qwen_coder/todos.md +38 -0
- examples/qwen_coder/validate_jsonl.py +60 -0
- 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 +169 -0
- 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 +80 -0
- examples/rl/configs/rl_from_ft_qwen.toml +37 -0
- examples/rl/download_dataset.py +80 -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 +10 -0
- examples/sdk_prompt_learning_example.py +55 -0
- examples/sft/README.md +139 -0
- examples/sft/configs/crafter_fft_qwen0p6b.toml +49 -0
- examples/sft/configs/crafter_lora_qwen0p6b.toml +49 -0
- examples/sft/evaluate.py +117 -0
- examples/sft/export_dataset.py +120 -0
- examples/sft/generate_traces.py +164 -0
- examples/swe/__init__.py +12 -0
- examples/swe/task_app/README.md +135 -0
- examples/swe/task_app/__init__.py +2 -0
- examples/swe/task_app/grpo_swe_mini.py +604 -0
- examples/swe/task_app/grpo_swe_mini_task_app.py +124 -0
- examples/swe/task_app/hosted/README.md +173 -0
- examples/swe/task_app/hosted/__init__.py +5 -0
- examples/swe/task_app/hosted/branching.py +143 -0
- examples/swe/task_app/hosted/environment_routes.py +1289 -0
- examples/swe/task_app/hosted/envs/__init__.py +1 -0
- examples/swe/task_app/hosted/envs/crafter/__init__.py +6 -0
- examples/swe/task_app/hosted/envs/crafter/app.py +1 -0
- examples/swe/task_app/hosted/envs/crafter/environment.py +522 -0
- examples/swe/task_app/hosted/envs/crafter/policy.py +478 -0
- examples/swe/task_app/hosted/envs/crafter/react_agent.py +108 -0
- examples/swe/task_app/hosted/envs/crafter/shared.py +305 -0
- examples/swe/task_app/hosted/envs/crafter/tools.py +47 -0
- examples/swe/task_app/hosted/envs/mini_swe/__init__.py +8 -0
- examples/swe/task_app/hosted/envs/mini_swe/environment.py +1191 -0
- examples/swe/task_app/hosted/envs/mini_swe/policy.py +355 -0
- examples/swe/task_app/hosted/envs/mini_swe/shared.py +83 -0
- examples/swe/task_app/hosted/envs/mini_swe/tools.py +96 -0
- examples/swe/task_app/hosted/hosted_app.py +204 -0
- examples/swe/task_app/hosted/inference/__init__.py +5 -0
- examples/swe/task_app/hosted/inference/openai_client.py +584 -0
- examples/swe/task_app/hosted/main.py +100 -0
- examples/swe/task_app/hosted/policy_routes.py +1094 -0
- examples/swe/task_app/hosted/registry.py +195 -0
- examples/swe/task_app/hosted/rollout.py +1905 -0
- examples/swe/task_app/hosted/storage/__init__.py +5 -0
- examples/swe/task_app/hosted/storage/volume.py +211 -0
- examples/swe/task_app/hosted/test_agents.py +161 -0
- examples/swe/task_app/hosted/test_service.py +136 -0
- examples/swe/task_app/hosted/utils.py +62 -0
- examples/swe/task_app/morph_backend.py +178 -0
- examples/task_apps/IMAGE_ONLY_EVAL_QUICKSTART.md +258 -0
- examples/task_apps/TESTING.md +275 -0
- examples/task_apps/banking77/__init__.py +6 -0
- examples/task_apps/banking77/banking77_task_app.py +912 -0
- examples/task_apps/banking77/deploy_wrapper.py +46 -0
- examples/task_apps/banking77_pipeline/__init__.py +6 -0
- examples/task_apps/banking77_pipeline/banking77_pipeline_task_app.py +489 -0
- examples/task_apps/banking77_pipeline/deploy_wrapper.py +50 -0
- examples/task_apps/crafter/CREATE_SFT_DATASET.md +286 -0
- examples/task_apps/crafter/EVAL_IMAGE_ONLY_RESULTS.md +152 -0
- examples/task_apps/crafter/FILTER_COMMAND_STATUS.md +187 -0
- examples/task_apps/crafter/FILTER_COMMAND_SUCCESS.md +281 -0
- examples/task_apps/crafter/QUERY_EXAMPLES.md +203 -0
- examples/task_apps/crafter/README_IMAGE_ONLY_EVAL.md +316 -0
- examples/task_apps/crafter/eval_image_only_gpt4o.toml +28 -0
- examples/task_apps/crafter/eval_text_only_groq_llama.toml +36 -0
- examples/task_apps/crafter/filter_sft_dataset.toml +16 -0
- examples/task_apps/crafter/task_app/README.md +42 -0
- examples/task_apps/crafter/task_app/__init__.py +5 -0
- examples/task_apps/crafter/task_app/grpo_crafter.py +1055 -0
- examples/task_apps/crafter/task_app/grpo_crafter_task_app.py +146 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/README.md +173 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/__init__.py +5 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/branching.py +143 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/environment_routes.py +1226 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/__init__.py +1 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/__init__.py +6 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/app.py +1 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/environment.py +532 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/policy.py +583 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/react_agent.py +122 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/shared.py +305 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/envs/crafter/tools.py +47 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/hosted_app.py +253 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/__init__.py +5 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/inference/openai_client.py +999 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/main.py +100 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/policy_routes.py +1252 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/registry.py +195 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/rollout.py +2233 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/storage/__init__.py +5 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/storage/volume.py +211 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/test_agents.py +161 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/test_service.py +136 -0
- examples/task_apps/crafter/task_app/synth_envs_hosted/utils.py +411 -0
- examples/task_apps/dev/pokemon_emerald/__init__.py +2 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/README.md +811 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/__init__.py +120 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/action.py +160 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/memory.py +155 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/perception.py +69 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/planning.py +96 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/simple.py +1502 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/system_prompt.py +4 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/grab_map.py +68 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/manual.py +216 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/__init__.py +35 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emerald_utils.py +631 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emulator.py +1544 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/enums.py +1428 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/memory_reader.py +4848 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/types.py +41 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/utils.py +298 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pyproject.toml +95 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/run.py +204 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/app.py +2152 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/client.py +429 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/frame_server.py +155 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/README.md +78 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/run_tests.py +122 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_direct.py +76 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_prompts.py +413 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_battle_state_formatting.py +204 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection.py +133 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection_comprehensive.py +229 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_direct_agent_emulator.py +300 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_fps_adjustment_pytest.py +205 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_direct.py +200 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_transition.py +284 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_map_ground_truth_comparison.py +468 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_memory_map.py +575 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_server_map_validation.py +311 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_torchic_state.py +259 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/anticheat.py +372 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/checkpoint.py +296 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/error_handler.py +275 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/get_local_ip.py +22 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/helpers.py +44 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/llm_logger.py +514 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_formatter.py +415 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher.py +1763 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher_singleton.py +33 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_trimmer.py +106 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_visualizer.py +334 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/ocr_dialogue.py +1020 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/recording.py +188 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/state_formatter.py +1481 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/vlm.py +862 -0
- examples/task_apps/dev/pokemon_emerald/modal_app.py +114 -0
- examples/task_apps/dev/pokemon_emerald/task_app/README.md +81 -0
- examples/task_apps/dev/pokemon_emerald/task_app/__init__.py +6 -0
- examples/task_apps/dev/pokemon_emerald/task_app/pokemon_emerald.py +685 -0
- examples/task_apps/enron/__init__.py +2 -0
- examples/task_apps/enron/eval_groq_qwen32.toml +16 -0
- examples/task_apps/enron/filter_sft.toml +5 -0
- examples/task_apps/enron/task_app/README.md +14 -0
- examples/task_apps/enron/task_app/__init__.py +1 -0
- examples/task_apps/enron/task_app/grpo_enron.py +906 -0
- examples/task_apps/enron/task_app/grpo_enron_task_app.py +146 -0
- examples/task_apps/enron/tests/__init__.py +4 -0
- examples/task_apps/enron/tests/conftest.py +115 -0
- examples/task_apps/enron/tests/integration/__init__.py +4 -0
- examples/task_apps/enron/tests/integration/test_enron_eval.py +179 -0
- examples/task_apps/enron/tests/integration/test_enron_rollout.py +135 -0
- examples/task_apps/enron/tests/unit/__init__.py +4 -0
- examples/task_apps/enron/tests/unit/test_enron_environment.py +126 -0
- examples/task_apps/gepa_benchmarks/__init__.py +7 -0
- examples/task_apps/gepa_benchmarks/common.py +260 -0
- examples/task_apps/gepa_benchmarks/hotpotqa_task_app.py +507 -0
- examples/task_apps/gepa_benchmarks/hover_task_app.py +436 -0
- examples/task_apps/gepa_benchmarks/ifbench_task_app.py +563 -0
- examples/task_apps/gepa_benchmarks/pupa_task_app.py +460 -0
- examples/task_apps/math/README.md +21 -0
- examples/task_apps/math/math_single_step.py +1000 -0
- examples/task_apps/math/math_task_app.py +115 -0
- examples/task_apps/pokemon_battle/__init__.py +2 -0
- examples/task_apps/pokemon_battle/modal_app.py +104 -0
- examples/task_apps/pokemon_battle/task_app/README.md +68 -0
- examples/task_apps/pokemon_battle/task_app/__init__.py +6 -0
- examples/task_apps/pokemon_battle/task_app/pokemon_showdown.py +932 -0
- examples/task_apps/pokemon_red/EVAL_IMAGE_ONLY_COMPLETE.md +283 -0
- examples/task_apps/pokemon_red/EVAL_IMAGE_ONLY_STATUS.md +155 -0
- examples/task_apps/pokemon_red/README.md +356 -0
- examples/task_apps/pokemon_red/README_IMAGE_ONLY_EVAL.md +428 -0
- examples/task_apps/pokemon_red/__init__.py +3 -0
- examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +30 -0
- examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +224 -0
- examples/task_apps/pokemon_red/pallet_town_rl_config.toml +75 -0
- examples/task_apps/pokemon_red/task_app.py +1048 -0
- examples/task_apps/pokemon_red/test_pallet_town_rewards.py +193 -0
- examples/task_apps/sokoban/README.md +306 -0
- examples/task_apps/sokoban/__init__.py +3 -0
- examples/task_apps/sokoban/eval_groq_qwen32.toml +16 -0
- examples/task_apps/sokoban/eval_openai_gpt5.toml +16 -0
- examples/task_apps/sokoban/filter_sft.toml +5 -0
- examples/task_apps/sokoban/task_app.py +1058 -0
- examples/task_apps/sokoban/tests/__init__.py +4 -0
- examples/task_apps/sokoban/tests/conftest.py +113 -0
- examples/task_apps/sokoban/tests/integration/__init__.py +4 -0
- examples/task_apps/sokoban/tests/integration/test_sokoban_eval.py +57 -0
- examples/task_apps/sokoban/tests/integration/test_sokoban_rollout.py +198 -0
- examples/task_apps/sokoban/tests/unit/__init__.py +4 -0
- examples/task_apps/sokoban/tests/unit/test_sokoban_environment.py +114 -0
- examples/task_apps/verilog/__init__.py +1 -0
- examples/task_apps/verilog/eval_groq_qwen32b.toml +22 -0
- examples/task_apps/verilog/filter_sft.toml +5 -0
- examples/task_apps/verilog/task_app/README.md +12 -0
- examples/task_apps/verilog/task_app/__init__.py +1 -0
- examples/task_apps/verilog/task_app/grpo_verilog.py +1166 -0
- examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +145 -0
- examples/task_apps/verilog/tests/__init__.py +4 -0
- examples/task_apps/verilog/tests/conftest.py +115 -0
- examples/task_apps/verilog/tests/integration/__init__.py +4 -0
- examples/task_apps/verilog/tests/integration/test_verilog_eval.py +181 -0
- examples/task_apps/verilog/tests/integration/test_verilog_rollout.py +55 -0
- examples/task_apps/verilog/tests/unit/__init__.py +4 -0
- examples/task_apps/verilog/tests/unit/test_verilog_scoring.py +118 -0
- examples/tunnel_gepa_banking77/README.md +106 -0
- examples/tunnel_gepa_banking77/banking77_gepa_tunnel.toml +95 -0
- examples/tunnel_gepa_banking77/keep_tunnel_running.py +60 -0
- examples/tunnel_gepa_banking77/run_gepa_with_tunnel.sh +226 -0
- examples/vlm/PROPOSAL.md +53 -0
- examples/vlm/README.md +68 -0
- examples/vlm/configs/crafter_vlm_gpt4o.toml +49 -0
- examples/vlm/crafter_image_only_agent.py +207 -0
- examples/vlm/crafter_openai_vlm_agent.py +275 -0
- examples/vlm/filter_image_rows.py +63 -0
- examples/vlm/run_crafter_vlm_benchmark.py +316 -0
- examples/warming_up_to_rl/_utils.py +92 -0
- examples/warming_up_to_rl/analyze_trace_db.py +422 -0
- examples/warming_up_to_rl/configs/crafter_fft.toml +53 -0
- examples/warming_up_to_rl/configs/crafter_fft_4b.toml +54 -0
- examples/warming_up_to_rl/configs/eval_fft_qwen4b.toml +22 -0
- examples/warming_up_to_rl/configs/eval_groq_qwen32b.toml +15 -0
- examples/warming_up_to_rl/configs/eval_modal_qwen4b.toml +24 -0
- examples/warming_up_to_rl/configs/eval_stepwise_complex.toml +35 -0
- examples/warming_up_to_rl/configs/eval_stepwise_consistent.toml +26 -0
- examples/warming_up_to_rl/configs/eval_stepwise_per_achievement.toml +36 -0
- examples/warming_up_to_rl/configs/eval_stepwise_simple.toml +32 -0
- examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +85 -0
- examples/warming_up_to_rl/configs/rl_from_ft.toml +58 -0
- examples/warming_up_to_rl/export_trace_sft.py +837 -0
- examples/warming_up_to_rl/groq_test.py +97 -0
- examples/warming_up_to_rl/manage_secrets.py +131 -0
- examples/warming_up_to_rl/old/event_rewards.md +234 -0
- examples/warming_up_to_rl/old/notes.md +73 -0
- examples/warming_up_to_rl/readme.md +110 -0
- examples/warming_up_to_rl/run_eval.py +736 -0
- examples/warming_up_to_rl/run_fft_and_save.py +380 -0
- examples/warming_up_to_rl/run_local_rollout.py +239 -0
- examples/warming_up_to_rl/run_local_rollout_modal.py +248 -0
- examples/warming_up_to_rl/run_local_rollout_parallel.py +405 -0
- examples/warming_up_to_rl/run_local_rollout_traced.py +477 -0
- examples/warming_up_to_rl/run_rl_and_save.py +124 -0
- examples/warming_up_to_rl/run_rollout_remote.py +156 -0
- examples/warming_up_to_rl/task_app/README.md +42 -0
- examples/warming_up_to_rl/task_app/grpo_crafter.py +876 -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 +253 -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 +729 -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 +1114 -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 +1891 -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 +129 -0
- examples/workflows/math_rl/configs/eval_base_qwen.toml +15 -0
- examples/workflows/math_rl/configs/eval_rl_qwen.toml +11 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen.toml +62 -0
- examples/workflows/math_rl/configs/rl_from_base_qwen17.toml +80 -0
- examples/workflows/math_rl/configs/rl_from_ft_qwen.toml +35 -0
- examples/workflows/math_rl/download_dataset.py +80 -0
- examples/workflows/math_rl/run_eval.py +436 -0
- examples/workflows/math_rl/run_rl_and_save.py +111 -0
- synth_ai/__init__.py +47 -23
- 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 +514 -0
- synth_ai/api/train/__init__.py +63 -0
- synth_ai/api/train/builders.py +473 -0
- synth_ai/api/train/cli.py +1185 -0
- synth_ai/api/train/config_finder.py +246 -0
- synth_ai/api/train/configs/__init__.py +65 -0
- synth_ai/api/train/configs/prompt_learning.py +496 -0
- synth_ai/api/train/configs/rl.py +188 -0
- synth_ai/api/train/configs/sft.py +99 -0
- synth_ai/api/train/configs/shared.py +81 -0
- synth_ai/api/train/env_resolver.py +352 -0
- synth_ai/api/train/pollers.py +91 -0
- synth_ai/api/train/prompt_learning.py +425 -0
- synth_ai/api/train/sft.py +390 -0
- synth_ai/api/train/supported_algos.py +147 -0
- synth_ai/api/train/task_app.py +195 -0
- synth_ai/api/train/utils.py +244 -0
- synth_ai/api/train/validators.py +1117 -0
- synth_ai/api/tunnel.py +49 -0
- synth_ai/auth/credentials.py +94 -0
- synth_ai/baseline/__init__.py +25 -0
- synth_ai/baseline/config.py +209 -0
- synth_ai/baseline/discovery.py +214 -0
- synth_ai/baseline/execution.py +146 -0
- synth_ai/cfgs.py +227 -0
- synth_ai/cli/__init__.py +90 -45
- synth_ai/cli/_modal_wrapper.py +31 -0
- synth_ai/cli/_storage.py +20 -0
- synth_ai/cli/_typer_patch.py +47 -0
- synth_ai/cli/_validate_task_app.py +29 -0
- synth_ai/cli/balance.py +16 -4
- synth_ai/cli/calc.py +36 -21
- synth_ai/cli/claude.py +70 -0
- synth_ai/cli/codex.py +267 -0
- synth_ai/cli/commands/__init__.py +18 -0
- synth_ai/cli/commands/baseline/__init__.py +12 -0
- synth_ai/cli/commands/baseline/core.py +637 -0
- synth_ai/cli/commands/baseline/list.py +93 -0
- synth_ai/cli/commands/demo/__init__.py +6 -0
- synth_ai/cli/commands/demo/core.py +163 -0
- synth_ai/cli/commands/eval/__init__.py +19 -0
- synth_ai/cli/commands/eval/core.py +1112 -0
- synth_ai/cli/commands/eval/errors.py +81 -0
- synth_ai/cli/commands/eval/validation.py +133 -0
- synth_ai/cli/commands/filter/__init__.py +12 -0
- synth_ai/cli/commands/filter/core.py +424 -0
- synth_ai/cli/commands/filter/errors.py +55 -0
- synth_ai/cli/commands/filter/validation.py +77 -0
- synth_ai/cli/commands/help/__init__.py +185 -0
- synth_ai/cli/commands/help/core.py +72 -0
- synth_ai/cli/commands/smoke/__init__.py +7 -0
- synth_ai/cli/commands/smoke/core.py +1437 -0
- synth_ai/cli/commands/status/__init__.py +66 -0
- synth_ai/cli/commands/status/client.py +192 -0
- synth_ai/cli/commands/status/config.py +92 -0
- synth_ai/cli/commands/status/errors.py +20 -0
- synth_ai/cli/commands/status/formatters.py +164 -0
- synth_ai/cli/commands/status/subcommands/__init__.py +9 -0
- synth_ai/cli/commands/status/subcommands/files.py +79 -0
- synth_ai/cli/commands/status/subcommands/jobs.py +334 -0
- synth_ai/cli/commands/status/subcommands/models.py +79 -0
- synth_ai/cli/commands/status/subcommands/pricing.py +22 -0
- synth_ai/cli/commands/status/subcommands/runs.py +81 -0
- synth_ai/cli/commands/status/subcommands/session.py +183 -0
- synth_ai/cli/commands/status/subcommands/summary.py +47 -0
- synth_ai/cli/commands/status/subcommands/usage.py +203 -0
- synth_ai/cli/commands/status/utils.py +114 -0
- synth_ai/cli/commands/train/__init__.py +53 -0
- synth_ai/cli/commands/train/core.py +21 -0
- synth_ai/cli/commands/train/errors.py +117 -0
- synth_ai/cli/commands/train/judge_schemas.py +200 -0
- synth_ai/cli/commands/train/judge_validation.py +305 -0
- synth_ai/cli/commands/train/validation.py +386 -0
- synth_ai/cli/demo.py +32 -140
- synth_ai/cli/deploy.py +233 -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 +28 -22
- 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/mcp.py +34 -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/opencode.py +256 -0
- synth_ai/cli/recent.py +13 -7
- synth_ai/cli/rl_demo.py +166 -114
- synth_ai/cli/root.py +143 -112
- 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 +49 -0
- synth_ai/cli/status.py +7 -125
- 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 +3134 -0
- synth_ai/cli/traces.py +9 -5
- 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 +73 -0
- synth_ai/cli/watch.py +13 -18
- synth_ai/demos/__init__.py +10 -0
- synth_ai/demos/core/__init__.py +28 -1
- synth_ai/demos/core/cli.py +745 -416
- 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/__init__.py +7 -1
- synth_ai/demos/demo_task_apps/core.py +75 -37
- synth_ai/demos/demo_task_apps/crafter/__init__.py +1 -0
- synth_ai/demos/demo_task_apps/crafter/configs/crafter_fft_4b.toml +53 -0
- synth_ai/demos/demo_task_apps/crafter/configs/rl_from_base_qwen4b.toml +73 -0
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +184 -0
- synth_ai/demos/demo_task_apps/math/_common.py +1 -2
- synth_ai/demos/demo_task_apps/math/app.py +2 -1
- synth_ai/demos/demo_task_apps/math/config.toml +55 -110
- synth_ai/demos/demo_task_apps/math/deploy_modal.py +3 -6
- synth_ai/demos/demo_task_apps/math/modal_task_app.py +491 -166
- synth_ai/demos/demo_task_apps/math/task_app_entry.py +37 -0
- 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 +703 -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 +12 -5
- synth_ai/environments/examples/bandit/environment.py +0 -1
- synth_ai/environments/examples/bandit/taskset.py +4 -4
- synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +7 -4
- synth_ai/environments/examples/crafter_classic/engine_serialization_patch_v3.py +9 -5
- synth_ai/environments/examples/crafter_classic/environment.py +93 -2
- synth_ai/environments/examples/crafter_classic/world_config_patch_simple.py +4 -3
- synth_ai/environments/examples/enron/engine.py +7 -2
- synth_ai/environments/examples/enron/environment.py +68 -0
- synth_ai/environments/examples/red/engine.py +60 -12
- synth_ai/environments/examples/red/engine_helpers/memory_map.py +7 -0
- synth_ai/environments/examples/red/engine_helpers/reward_components.py +151 -179
- synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_progression.py +477 -0
- synth_ai/environments/examples/red/engine_helpers/state_extraction.py +32 -0
- synth_ai/environments/examples/red/environment.py +86 -0
- synth_ai/environments/examples/red/trace_hooks_v3.py +168 -0
- synth_ai/environments/examples/sokoban/taskset.py +116 -0
- synth_ai/environments/examples/verilog/engine.py +104 -12
- synth_ai/environments/examples/wordle/environment.py +0 -1
- synth_ai/environments/reproducibility/tree.py +5 -6
- synth_ai/environments/service/app.py +11 -12
- synth_ai/environments/service/core_routes.py +10 -9
- synth_ai/environments/stateful/engine.py +1 -1
- synth_ai/environments/tasks/core.py +1 -0
- synth_ai/environments/tasks/filters.py +5 -6
- synth_ai/environments/tasks/utils.py +4 -5
- synth_ai/evals/__init__.py +15 -0
- synth_ai/evals/base.py +14 -5
- synth_ai/evals/client.py +82 -0
- synth_ai/evals/types.py +42 -0
- synth_ai/http.py +8 -22
- synth_ai/http_client.py +45 -12
- synth_ai/inference/__init__.py +0 -2
- synth_ai/inference/client.py +21 -7
- synth_ai/jobs/client.py +129 -80
- synth_ai/judge_schemas.py +127 -0
- synth_ai/learning/__init__.py +51 -6
- synth_ai/learning/algorithms.py +14 -0
- synth_ai/learning/client.py +122 -30
- synth_ai/learning/config.py +2 -40
- synth_ai/learning/constants.py +0 -2
- synth_ai/learning/ft_client.py +4 -56
- synth_ai/learning/health.py +14 -8
- synth_ai/learning/jobs.py +43 -47
- synth_ai/learning/prompt_learning_client.py +276 -0
- synth_ai/learning/prompt_learning_types.py +185 -0
- synth_ai/{rl → learning/rl}/__init__.py +14 -5
- synth_ai/learning/rl/client.py +269 -0
- synth_ai/learning/rl/config.py +31 -0
- synth_ai/{rl → learning/rl}/contracts.py +5 -10
- synth_ai/{rl → learning/rl}/env_keys.py +45 -16
- synth_ai/learning/rl/secrets.py +13 -0
- synth_ai/learning/rl_client.py +2 -253
- synth_ai/learning/sft/__init__.py +29 -0
- synth_ai/learning/sft/client.py +68 -0
- synth_ai/learning/sft/config.py +270 -0
- synth_ai/learning/sft/data.py +698 -0
- synth_ai/learning/sse.py +25 -26
- synth_ai/learning/validators.py +29 -25
- synth_ai/mcp/__init__.py +5 -0
- synth_ai/mcp/__main__.py +8 -0
- synth_ai/mcp/main.py +254 -0
- synth_ai/mcp/setup.py +100 -0
- synth_ai/modal.py +257 -0
- synth_ai/pricing/__init__.py +3 -0
- synth_ai/pricing/model_pricing.py +64 -0
- synth_ai/session/__init__.py +75 -0
- synth_ai/session/client.py +383 -0
- synth_ai/session/constants.py +63 -0
- synth_ai/session/exceptions.py +105 -0
- synth_ai/session/manager.py +139 -0
- synth_ai/session/models.py +89 -0
- synth_ai/session/query.py +110 -0
- synth_ai/spec/__init__.py +46 -0
- synth_ai/spec/dataclasses.py +149 -0
- synth_ai/spec/loader.py +144 -0
- synth_ai/spec/serializer.py +199 -0
- synth_ai/spec/validation.py +250 -0
- synth_ai/streaming/__init__.py +29 -0
- synth_ai/streaming/config.py +94 -0
- synth_ai/streaming/handlers.py +589 -0
- synth_ai/streaming/streamer.py +320 -0
- synth_ai/streaming/types.py +95 -0
- synth_ai/task/__init__.py +116 -3
- synth_ai/task/apps/__init__.py +132 -0
- synth_ai/task/auth.py +165 -0
- synth_ai/task/client.py +167 -0
- synth_ai/task/config.py +261 -0
- synth_ai/task/contracts.py +173 -57
- synth_ai/task/datasets.py +108 -0
- synth_ai/task/errors.py +50 -0
- synth_ai/task/health.py +17 -11
- synth_ai/task/inference_api.py +101 -0
- synth_ai/task/json.py +111 -0
- synth_ai/task/proxy.py +251 -0
- synth_ai/task/rubrics/__init__.py +55 -0
- synth_ai/task/rubrics/loaders.py +156 -0
- synth_ai/task/rubrics/models.py +57 -0
- synth_ai/task/rubrics/scoring.py +116 -0
- synth_ai/task/rubrics/strict.py +149 -0
- synth_ai/task/rubrics.py +219 -0
- synth_ai/task/server.py +432 -0
- synth_ai/task/trace_correlation_helpers.py +328 -0
- synth_ai/task/tracing_utils.py +95 -0
- synth_ai/task/validators.py +449 -6
- synth_ai/task/vendors.py +59 -0
- synth_ai/tracing_v3/__init__.py +4 -0
- synth_ai/tracing_v3/abstractions.py +21 -4
- synth_ai/tracing_v3/config.py +167 -22
- synth_ai/tracing_v3/constants.py +21 -0
- synth_ai/tracing_v3/db_config.py +42 -29
- synth_ai/tracing_v3/decorators.py +80 -45
- synth_ai/tracing_v3/examples/basic_usage.py +15 -9
- synth_ai/tracing_v3/hooks.py +6 -4
- synth_ai/tracing_v3/llm_call_record_helpers.py +161 -61
- synth_ai/tracing_v3/migration_helper.py +1 -2
- synth_ai/tracing_v3/replica_sync.py +12 -7
- synth_ai/tracing_v3/serialization.py +130 -0
- synth_ai/tracing_v3/session_tracer.py +86 -21
- synth_ai/tracing_v3/storage/base.py +98 -12
- synth_ai/tracing_v3/storage/config.py +63 -16
- synth_ai/tracing_v3/storage/factory.py +11 -9
- synth_ai/tracing_v3/storage/utils.py +15 -11
- synth_ai/tracing_v3/trace_utils.py +317 -0
- synth_ai/tracing_v3/turso/__init__.py +8 -21
- synth_ai/tracing_v3/turso/daemon.py +123 -15
- synth_ai/tracing_v3/turso/models.py +5 -2
- synth_ai/tracing_v3/turso/native_manager.py +1293 -0
- synth_ai/tracing_v3/utils.py +5 -4
- synth_ai/tunnel.py +143 -0
- synth_ai/tunnel_deploy.py +278 -0
- synth_ai/types.py +8 -0
- synth_ai/urls.py +11 -0
- synth_ai/utils/__init__.py +166 -0
- synth_ai/utils/agents.py +74 -0
- synth_ai/utils/apps.py +152 -0
- synth_ai/utils/base_url.py +94 -0
- synth_ai/utils/bin.py +39 -0
- synth_ai/utils/claude.py +36 -0
- synth_ai/utils/cli.py +284 -0
- synth_ai/utils/config.py +81 -0
- synth_ai/utils/env.py +346 -0
- synth_ai/utils/errors.py +85 -0
- synth_ai/utils/http.py +172 -0
- synth_ai/utils/json.py +72 -0
- synth_ai/utils/log_filter.py +99 -0
- synth_ai/utils/logging.py +198 -0
- synth_ai/utils/modal.py +299 -0
- synth_ai/utils/paths.py +95 -0
- synth_ai/utils/process.py +233 -0
- synth_ai/utils/prompts.py +39 -0
- synth_ai/utils/sqld.py +122 -0
- synth_ai/utils/ssl.py +25 -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/tunnel/__init__.py +12 -0
- synth_ai/utils/tunnel/config.py +55 -0
- synth_ai/utils/user_config.py +137 -0
- synth_ai/uvicorn.py +77 -0
- synth_ai-0.2.23.dev3.dist-info/METADATA +357 -0
- synth_ai-0.2.23.dev3.dist-info/RECORD +983 -0
- {synth_ai-0.2.8.dev4.dist-info → synth_ai-0.2.23.dev3.dist-info}/entry_points.txt +0 -1
- {synth_ai-0.2.8.dev4.dist-info → synth_ai-0.2.23.dev3.dist-info}/top_level.txt +1 -0
- synth_ai/cli/man.py +0 -106
- synth_ai/core/experiment.py +0 -15
- synth_ai/core/system.py +0 -15
- synth_ai/environments/examples/sokoban/units/astar_common.py +0 -95
- synth_ai/experimental/synth_oss.py +0 -446
- synth_ai/handshake.py +0 -63
- synth_ai/install_sqld.sh +0 -40
- 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/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/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/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/base.py +0 -81
- synth_ai/lm/vendors/core/anthropic_api.py +0 -387
- synth_ai/lm/vendors/core/gemini_api.py +0 -292
- synth_ai/lm/vendors/core/mistral_api.py +0 -322
- synth_ai/lm/vendors/core/openai_api.py +0 -225
- synth_ai/lm/vendors/core/synth_dev_api.py +0 -0
- synth_ai/lm/vendors/local/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/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/tracing/__init__.py +0 -30
- synth_ai/tracing_v1/__init__.py +0 -33
- synth_ai/tracing_v3/turso/manager.py +0 -760
- synth_ai/v0/tracing/abstractions.py +0 -224
- synth_ai/v0/tracing/base_client.py +0 -91
- synth_ai/v0/tracing/client_manager.py +0 -131
- synth_ai/v0/tracing/config.py +0 -142
- synth_ai/v0/tracing/context.py +0 -146
- synth_ai/v0/tracing/decorators.py +0 -682
- synth_ai/v0/tracing/events/__init__.py +0 -0
- synth_ai/v0/tracing/events/manage.py +0 -147
- synth_ai/v0/tracing/events/scope.py +0 -86
- synth_ai/v0/tracing/events/store.py +0 -228
- synth_ai/v0/tracing/immediate_client.py +0 -151
- synth_ai/v0/tracing/local.py +0 -18
- synth_ai/v0/tracing/log_client_base.py +0 -73
- synth_ai/v0/tracing/retry_queue.py +0 -186
- synth_ai/v0/tracing/trackers.py +0 -515
- synth_ai/v0/tracing/upload.py +0 -512
- synth_ai/v0/tracing/utils.py +0 -9
- synth_ai/v0/tracing_v1/__init__.py +0 -16
- synth_ai/v0/tracing_v1/abstractions.py +0 -224
- synth_ai/v0/tracing_v1/base_client.py +0 -91
- synth_ai/v0/tracing_v1/client_manager.py +0 -131
- synth_ai/v0/tracing_v1/config.py +0 -142
- synth_ai/v0/tracing_v1/context.py +0 -146
- synth_ai/v0/tracing_v1/decorators.py +0 -703
- synth_ai/v0/tracing_v1/events/__init__.py +0 -0
- synth_ai/v0/tracing_v1/events/manage.py +0 -147
- synth_ai/v0/tracing_v1/events/scope.py +0 -86
- synth_ai/v0/tracing_v1/events/store.py +0 -228
- synth_ai/v0/tracing_v1/immediate_client.py +0 -151
- synth_ai/v0/tracing_v1/local.py +0 -18
- synth_ai/v0/tracing_v1/log_client_base.py +0 -73
- synth_ai/v0/tracing_v1/retry_queue.py +0 -186
- synth_ai/v0/tracing_v1/trackers.py +0 -515
- synth_ai/v0/tracing_v1/upload.py +0 -527
- synth_ai/v0/tracing_v1/utils.py +0 -9
- synth_ai/zyk/__init__.py +0 -30
- synth_ai-0.2.8.dev4.dist-info/METADATA +0 -129
- synth_ai-0.2.8.dev4.dist-info/RECORD +0 -420
- {synth_ai/lm/caching → examples/task_apps}/__init__.py +0 -0
- {synth_ai/lm/cost → examples/task_apps/crafter}/__init__.py +0 -0
- {synth_ai/lm/structured_outputs → examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server}/__init__.py +0 -0
- {synth_ai/lm/vendors → examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests}/__init__.py +0 -0
- {synth_ai/lm/vendors/core → examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils}/__init__.py +0 -0
- {synth_ai/lm/vendors/local → examples/task_apps/math}/__init__.py +0 -0
- {synth_ai/lm/vendors/supported → examples/workflows}/__init__.py +0 -0
- {synth_ai/v0/tracing → examples/workflows/math_rl}/__init__.py +0 -0
- /synth_ai/{compound/cais.py → cli/__main__.py} +0 -0
- /synth_ai/{learning/filtering.py → py.typed} +0 -0
- {synth_ai-0.2.8.dev4.dist-info → synth_ai-0.2.23.dev3.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.8.dev4.dist-info → synth_ai-0.2.23.dev3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,808 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
OpenAI-compatible client for Synth backend.
|
|
3
|
-
Provides async and sync interfaces matching OpenAI's API.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import asyncio
|
|
7
|
-
import json
|
|
8
|
-
import logging
|
|
9
|
-
import os
|
|
10
|
-
from typing import Any, Optional
|
|
11
|
-
|
|
12
|
-
import httpx
|
|
13
|
-
|
|
14
|
-
from ..config import SynthConfig
|
|
15
|
-
|
|
16
|
-
logger = logging.getLogger(__name__)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class ChatInterface:
|
|
20
|
-
"""Nested interface to match OpenAI client structure."""
|
|
21
|
-
|
|
22
|
-
def __init__(self, client):
|
|
23
|
-
self._client = client
|
|
24
|
-
self.completions = self
|
|
25
|
-
|
|
26
|
-
async def create(self, **kwargs):
|
|
27
|
-
"""Create chat completion - matches OpenAI interface."""
|
|
28
|
-
result = await self._client.chat_completions_create(**kwargs)
|
|
29
|
-
# If streaming was requested and the result is an async-iterable, return it directly
|
|
30
|
-
if kwargs.get("stream") and hasattr(result, "__aiter__"):
|
|
31
|
-
return result
|
|
32
|
-
# Convert dict response to object-like structure for OpenAI compatibility
|
|
33
|
-
return OpenAIResponse(result)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class OpenAIResponse:
|
|
37
|
-
"""Wrapper to make dict response behave like OpenAI response object."""
|
|
38
|
-
|
|
39
|
-
def __init__(self, data: dict):
|
|
40
|
-
self._data = data
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def choices(self):
|
|
44
|
-
return [OpenAIChoice(choice) for choice in self._data.get("choices", [])]
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def usage(self):
|
|
48
|
-
return self._data.get("usage")
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def id(self):
|
|
52
|
-
return self._data.get("id")
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def model(self):
|
|
56
|
-
return self._data.get("model")
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def object(self):
|
|
60
|
-
return self._data.get("object")
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class OpenAIChoice:
|
|
64
|
-
"""Wrapper for choice objects."""
|
|
65
|
-
|
|
66
|
-
def __init__(self, data: dict):
|
|
67
|
-
self._data = data
|
|
68
|
-
|
|
69
|
-
@property
|
|
70
|
-
def message(self):
|
|
71
|
-
return OpenAIMessage(self._data.get("message", {}))
|
|
72
|
-
|
|
73
|
-
@property
|
|
74
|
-
def finish_reason(self):
|
|
75
|
-
return self._data.get("finish_reason")
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class OpenAIMessage:
|
|
79
|
-
"""Wrapper for message objects."""
|
|
80
|
-
|
|
81
|
-
def __init__(self, data: dict):
|
|
82
|
-
self._data = data
|
|
83
|
-
|
|
84
|
-
@property
|
|
85
|
-
def role(self):
|
|
86
|
-
return self._data.get("role")
|
|
87
|
-
|
|
88
|
-
@property
|
|
89
|
-
def content(self):
|
|
90
|
-
return self._data.get("content")
|
|
91
|
-
|
|
92
|
-
@property
|
|
93
|
-
def tool_calls(self):
|
|
94
|
-
return self._data.get("tool_calls")
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class StreamDelta:
|
|
98
|
-
"""Wrapper for stream delta objects."""
|
|
99
|
-
|
|
100
|
-
def __init__(self, data: dict):
|
|
101
|
-
self._data = data or {}
|
|
102
|
-
|
|
103
|
-
@property
|
|
104
|
-
def content(self) -> Optional[str]:
|
|
105
|
-
return self._data.get("content")
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class StreamChoice:
|
|
109
|
-
"""Wrapper for stream choice objects."""
|
|
110
|
-
|
|
111
|
-
def __init__(self, data: dict):
|
|
112
|
-
self._data = data or {}
|
|
113
|
-
|
|
114
|
-
@property
|
|
115
|
-
def delta(self) -> StreamDelta:
|
|
116
|
-
return StreamDelta(self._data.get("delta", {}))
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
class StreamChunk:
|
|
120
|
-
"""Wrapper for stream chunk to expose .choices[0].delta.content."""
|
|
121
|
-
|
|
122
|
-
def __init__(self, data: dict):
|
|
123
|
-
self._data = data or {}
|
|
124
|
-
|
|
125
|
-
@property
|
|
126
|
-
def choices(self):
|
|
127
|
-
return [StreamChoice(c) for c in self._data.get("choices", [])]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def _wrap_stream_chunk(data: dict) -> StreamChunk:
|
|
131
|
-
return StreamChunk(data)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
class AsyncSynthClient:
|
|
135
|
-
"""Async client with OpenAI-compatible interface."""
|
|
136
|
-
|
|
137
|
-
def __init__(
|
|
138
|
-
self,
|
|
139
|
-
config: SynthConfig | None = None,
|
|
140
|
-
api_key: Optional[str] = None,
|
|
141
|
-
base_url: Optional[str] = None,
|
|
142
|
-
**_: Any,
|
|
143
|
-
):
|
|
144
|
-
"""Initialize with config or OpenAI-style parameters/env.
|
|
145
|
-
|
|
146
|
-
Precedence: explicit args -> OPENAI_* env -> SYNTH_* env -> SynthConfig.from_env().
|
|
147
|
-
"""
|
|
148
|
-
if config is None and (api_key or base_url):
|
|
149
|
-
config = SynthConfig(
|
|
150
|
-
base_url=base_url or os.getenv("OPENAI_API_BASE") or os.getenv("SYNTH_BASE_URL"),
|
|
151
|
-
api_key=api_key or os.getenv("OPENAI_API_KEY") or os.getenv("SYNTH_API_KEY"),
|
|
152
|
-
)
|
|
153
|
-
elif config is None and (os.getenv("OPENAI_API_BASE") and os.getenv("OPENAI_API_KEY")):
|
|
154
|
-
config = SynthConfig(
|
|
155
|
-
base_url=os.getenv("OPENAI_API_BASE"),
|
|
156
|
-
api_key=os.getenv("OPENAI_API_KEY"),
|
|
157
|
-
)
|
|
158
|
-
self.config = config or SynthConfig.from_env()
|
|
159
|
-
self._client = None
|
|
160
|
-
|
|
161
|
-
# Create nested OpenAI-style interface
|
|
162
|
-
self.chat = ChatInterface(self)
|
|
163
|
-
self.completions = self.chat # Alias for backward compatibility
|
|
164
|
-
|
|
165
|
-
async def __aenter__(self):
|
|
166
|
-
self._client = httpx.AsyncClient(
|
|
167
|
-
timeout=self.config.timeout,
|
|
168
|
-
headers={
|
|
169
|
-
"Authorization": f"Bearer {self.config.api_key}",
|
|
170
|
-
"Content-Type": "application/json",
|
|
171
|
-
},
|
|
172
|
-
)
|
|
173
|
-
return self
|
|
174
|
-
|
|
175
|
-
async def __aexit__(self, *args):
|
|
176
|
-
if self._client:
|
|
177
|
-
await self._client.aclose()
|
|
178
|
-
|
|
179
|
-
async def _ensure_client(self):
|
|
180
|
-
"""Ensure client is initialized."""
|
|
181
|
-
if self._client is None:
|
|
182
|
-
self._client = httpx.AsyncClient(
|
|
183
|
-
timeout=self.config.timeout,
|
|
184
|
-
headers={
|
|
185
|
-
"Authorization": f"Bearer {self.config.api_key}",
|
|
186
|
-
"Content-Type": "application/json",
|
|
187
|
-
},
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
async def responses_create(
|
|
191
|
-
self,
|
|
192
|
-
model: str,
|
|
193
|
-
messages: list[dict[str, Any]],
|
|
194
|
-
previous_response_id: str | None = None,
|
|
195
|
-
tools: list[dict[str, Any]] | None = None,
|
|
196
|
-
tool_choice: str | dict[str, Any] | None = "auto",
|
|
197
|
-
**kwargs,
|
|
198
|
-
) -> dict[str, Any]:
|
|
199
|
-
"""
|
|
200
|
-
Create response using Synth Responses API.
|
|
201
|
-
|
|
202
|
-
Args:
|
|
203
|
-
model: Model identifier
|
|
204
|
-
messages: List of message dicts with 'role' and 'content'
|
|
205
|
-
previous_response_id: Optional ID of previous response for thread management
|
|
206
|
-
tools: List of available tools
|
|
207
|
-
tool_choice: How to choose tools
|
|
208
|
-
**kwargs: Additional parameters
|
|
209
|
-
|
|
210
|
-
Returns:
|
|
211
|
-
Responses API-compatible response dict
|
|
212
|
-
"""
|
|
213
|
-
await self._ensure_client()
|
|
214
|
-
|
|
215
|
-
# Build payload for Responses API
|
|
216
|
-
payload = {
|
|
217
|
-
"model": model,
|
|
218
|
-
"messages": messages,
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
# Add optional parameters
|
|
222
|
-
if previous_response_id is not None:
|
|
223
|
-
payload["previous_response_id"] = previous_response_id
|
|
224
|
-
if tools is not None:
|
|
225
|
-
payload["tools"] = tools
|
|
226
|
-
payload["tool_choice"] = tool_choice
|
|
227
|
-
|
|
228
|
-
# Add any additional kwargs
|
|
229
|
-
payload.update(kwargs)
|
|
230
|
-
|
|
231
|
-
# Retry logic
|
|
232
|
-
for attempt in range(self.config.max_retries):
|
|
233
|
-
try:
|
|
234
|
-
url = f"{self.config.get_base_url_without_v1()}/v1/responses"
|
|
235
|
-
response = await self._client.post(url, json=payload)
|
|
236
|
-
|
|
237
|
-
if response.status_code == 200:
|
|
238
|
-
return response.json()
|
|
239
|
-
|
|
240
|
-
# Handle rate limits with exponential backoff
|
|
241
|
-
if response.status_code == 429:
|
|
242
|
-
wait_time = 2**attempt
|
|
243
|
-
await asyncio.sleep(wait_time)
|
|
244
|
-
continue
|
|
245
|
-
|
|
246
|
-
# Other errors
|
|
247
|
-
response.raise_for_status()
|
|
248
|
-
|
|
249
|
-
except Exception as e:
|
|
250
|
-
if attempt == self.config.max_retries - 1:
|
|
251
|
-
logger.error(f"Failed after {self.config.max_retries} attempts: {e}")
|
|
252
|
-
raise
|
|
253
|
-
await asyncio.sleep(2**attempt)
|
|
254
|
-
|
|
255
|
-
raise Exception(f"Failed to create response after {self.config.max_retries} attempts")
|
|
256
|
-
|
|
257
|
-
async def chat_completions_create(
|
|
258
|
-
self,
|
|
259
|
-
model: str,
|
|
260
|
-
messages: list[dict[str, Any]],
|
|
261
|
-
temperature: float = 0.7,
|
|
262
|
-
max_tokens: int | None = None,
|
|
263
|
-
top_p: float = 1.0,
|
|
264
|
-
frequency_penalty: float = 0.0,
|
|
265
|
-
presence_penalty: float = 0.0,
|
|
266
|
-
stop: str | list[str] | None = None,
|
|
267
|
-
stream: bool = False,
|
|
268
|
-
tools: list[dict[str, Any]] | None = None,
|
|
269
|
-
tool_choice: str | dict[str, Any] | None = "auto",
|
|
270
|
-
response_format: dict[str, Any] | None = None,
|
|
271
|
-
seed: int | None = None,
|
|
272
|
-
**kwargs,
|
|
273
|
-
) -> dict[str, Any]:
|
|
274
|
-
"""
|
|
275
|
-
Create chat completion with OpenAI-compatible API.
|
|
276
|
-
This method provides the OpenAI client interface structure.
|
|
277
|
-
"""
|
|
278
|
-
return await self._chat_completions_create(
|
|
279
|
-
model, messages, temperature, max_tokens, top_p, frequency_penalty,
|
|
280
|
-
presence_penalty, stop, stream, tools, tool_choice, response_format, seed, **kwargs
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
async def _chat_completions_create(
|
|
284
|
-
self,
|
|
285
|
-
model: str,
|
|
286
|
-
messages: list[dict[str, Any]],
|
|
287
|
-
temperature: float = 0.7,
|
|
288
|
-
max_tokens: int | None = None,
|
|
289
|
-
top_p: float = 1.0,
|
|
290
|
-
frequency_penalty: float = 0.0,
|
|
291
|
-
presence_penalty: float = 0.0,
|
|
292
|
-
stop: str | list[str] | None = None,
|
|
293
|
-
stream: bool = False,
|
|
294
|
-
tools: list[dict[str, Any]] | None = None,
|
|
295
|
-
tool_choice: str | dict[str, Any] | None = "auto",
|
|
296
|
-
response_format: dict[str, Any] | None = None,
|
|
297
|
-
seed: int | None = None,
|
|
298
|
-
**kwargs,
|
|
299
|
-
) -> dict[str, Any]:
|
|
300
|
-
"""
|
|
301
|
-
Create chat completion with OpenAI-compatible API.
|
|
302
|
-
|
|
303
|
-
Args:
|
|
304
|
-
model: Model identifier
|
|
305
|
-
messages: List of message dicts with 'role' and 'content'
|
|
306
|
-
temperature: Sampling temperature (0-2)
|
|
307
|
-
max_tokens: Maximum tokens to generate
|
|
308
|
-
top_p: Nucleus sampling parameter
|
|
309
|
-
frequency_penalty: Frequency penalty (-2 to 2)
|
|
310
|
-
presence_penalty: Presence penalty (-2 to 2)
|
|
311
|
-
stop: Stop sequences
|
|
312
|
-
stream: Whether to stream responses
|
|
313
|
-
tools: List of available tools
|
|
314
|
-
tool_choice: How to choose tools
|
|
315
|
-
response_format: Response format constraints
|
|
316
|
-
seed: Random seed for deterministic output
|
|
317
|
-
**kwargs: Additional parameters
|
|
318
|
-
|
|
319
|
-
Returns:
|
|
320
|
-
OpenAI-compatible response dict
|
|
321
|
-
"""
|
|
322
|
-
await self._ensure_client()
|
|
323
|
-
|
|
324
|
-
# Build payload
|
|
325
|
-
payload = {
|
|
326
|
-
"model": model,
|
|
327
|
-
"messages": messages,
|
|
328
|
-
"temperature": temperature,
|
|
329
|
-
"top_p": top_p,
|
|
330
|
-
"frequency_penalty": frequency_penalty,
|
|
331
|
-
"presence_penalty": presence_penalty,
|
|
332
|
-
"stream": stream,
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
# Add optional parameters
|
|
336
|
-
if max_tokens is not None:
|
|
337
|
-
payload["max_tokens"] = max_tokens
|
|
338
|
-
if stop is not None:
|
|
339
|
-
payload["stop"] = stop
|
|
340
|
-
if tools is not None:
|
|
341
|
-
payload["tools"] = tools
|
|
342
|
-
payload["tool_choice"] = tool_choice
|
|
343
|
-
if response_format is not None:
|
|
344
|
-
payload["response_format"] = response_format
|
|
345
|
-
if seed is not None:
|
|
346
|
-
payload["seed"] = seed
|
|
347
|
-
|
|
348
|
-
# Add any additional kwargs (including thinking_mode and thinking_budget)
|
|
349
|
-
payload.update(kwargs)
|
|
350
|
-
|
|
351
|
-
# Apply env defaults for thinking if not set explicitly
|
|
352
|
-
try:
|
|
353
|
-
if "thinking_mode" not in payload:
|
|
354
|
-
env_mode = os.getenv("SYNTH_THINKING_MODE")
|
|
355
|
-
if env_mode in ("think", "no_think"):
|
|
356
|
-
payload["thinking_mode"] = env_mode
|
|
357
|
-
if "thinking_budget" not in payload:
|
|
358
|
-
env_budget = os.getenv("SYNTH_THINKING_BUDGET")
|
|
359
|
-
if env_budget and str(env_budget).strip().isdigit():
|
|
360
|
-
payload["thinking_budget"] = int(env_budget)
|
|
361
|
-
except Exception:
|
|
362
|
-
pass
|
|
363
|
-
|
|
364
|
-
# Local warn if budget exceeds max_tokens (do not mutate payload)
|
|
365
|
-
try:
|
|
366
|
-
bt = payload.get("thinking_budget")
|
|
367
|
-
mt = payload.get("max_tokens")
|
|
368
|
-
if isinstance(bt, int) and isinstance(mt, int) and bt > mt:
|
|
369
|
-
logger.warning(
|
|
370
|
-
"thinking_budget (%s) exceeds max_tokens (%s) – forwarding as-is",
|
|
371
|
-
str(bt), str(mt)
|
|
372
|
-
)
|
|
373
|
-
except Exception:
|
|
374
|
-
pass
|
|
375
|
-
|
|
376
|
-
# Retry logic
|
|
377
|
-
for attempt in range(self.config.max_retries):
|
|
378
|
-
try:
|
|
379
|
-
url = f"{self.config.get_base_url_without_v1()}/v1/chat/completions"
|
|
380
|
-
_debug_client = os.getenv("SYNTH_CLIENT_DEBUG") == "1"
|
|
381
|
-
if _debug_client:
|
|
382
|
-
print(f"🔍 SYNTH DEBUG: Making request to URL: {url}")
|
|
383
|
-
print(f"🔍 SYNTH DEBUG: Payload keys: {list(payload.keys())}")
|
|
384
|
-
if "tools" in payload:
|
|
385
|
-
# Only print counts, avoid dumping tool schemas unless explicitly enabled
|
|
386
|
-
print(f"🔍 SYNTH DEBUG: Tools in payload: {len(payload['tools'])} tools")
|
|
387
|
-
|
|
388
|
-
# If streaming requested, return an async stream adapter
|
|
389
|
-
if stream:
|
|
390
|
-
async def _astream():
|
|
391
|
-
await self._ensure_client()
|
|
392
|
-
async with self._client.stream("POST", url, json=payload) as r: # type: ignore
|
|
393
|
-
r.raise_for_status()
|
|
394
|
-
async for line in r.aiter_lines():
|
|
395
|
-
if not line:
|
|
396
|
-
continue
|
|
397
|
-
if line.startswith("data:"):
|
|
398
|
-
data_line = line[len("data:") :].strip()
|
|
399
|
-
if data_line == "[DONE]":
|
|
400
|
-
return
|
|
401
|
-
try:
|
|
402
|
-
chunk = json.loads(data_line)
|
|
403
|
-
yield _wrap_stream_chunk(chunk)
|
|
404
|
-
except json.JSONDecodeError:
|
|
405
|
-
logger.debug("Non-JSON stream line: %s", data_line)
|
|
406
|
-
|
|
407
|
-
class _AsyncStream:
|
|
408
|
-
def __aiter__(self):
|
|
409
|
-
return _astream()
|
|
410
|
-
|
|
411
|
-
async def __aenter__(self):
|
|
412
|
-
return self
|
|
413
|
-
|
|
414
|
-
async def __aexit__(self, *exc):
|
|
415
|
-
return False
|
|
416
|
-
|
|
417
|
-
return _AsyncStream()
|
|
418
|
-
|
|
419
|
-
response = await self._client.post(url, json=payload)
|
|
420
|
-
|
|
421
|
-
if _debug_client:
|
|
422
|
-
print(f"🔍 SYNTH DEBUG: Response status: {response.status_code}")
|
|
423
|
-
|
|
424
|
-
if response.status_code == 200:
|
|
425
|
-
result = response.json()
|
|
426
|
-
if _debug_client:
|
|
427
|
-
print(f"🔍 SYNTH DEBUG: Response keys: {list(result.keys())}")
|
|
428
|
-
if "choices" in result and result["choices"]:
|
|
429
|
-
choice = result["choices"][0]
|
|
430
|
-
print(f"🔍 SYNTH DEBUG: Choice keys: {list(choice.keys())}")
|
|
431
|
-
if "message" in choice:
|
|
432
|
-
message = choice["message"]
|
|
433
|
-
print(f"🔍 SYNTH DEBUG: Message keys: {list(message.keys())}")
|
|
434
|
-
return result
|
|
435
|
-
|
|
436
|
-
# Handle rate limits with exponential backoff
|
|
437
|
-
if response.status_code == 429:
|
|
438
|
-
wait_time = 2**attempt
|
|
439
|
-
logger.warning(f"Rate limited, waiting {wait_time}s...")
|
|
440
|
-
await asyncio.sleep(wait_time)
|
|
441
|
-
continue
|
|
442
|
-
|
|
443
|
-
# Other errors
|
|
444
|
-
error_msg = f"API error {response.status_code}: {response.text}"
|
|
445
|
-
logger.error(error_msg)
|
|
446
|
-
raise Exception(error_msg)
|
|
447
|
-
|
|
448
|
-
except httpx.TimeoutException:
|
|
449
|
-
if attempt < self.config.max_retries - 1:
|
|
450
|
-
logger.warning(f"Timeout on attempt {attempt + 1}, retrying...")
|
|
451
|
-
continue
|
|
452
|
-
raise
|
|
453
|
-
except Exception as e:
|
|
454
|
-
if attempt < self.config.max_retries - 1 and "rate" in str(e).lower():
|
|
455
|
-
wait_time = 2**attempt
|
|
456
|
-
logger.warning(f"Error on attempt {attempt + 1}, waiting {wait_time}s...")
|
|
457
|
-
await asyncio.sleep(wait_time)
|
|
458
|
-
continue
|
|
459
|
-
raise
|
|
460
|
-
|
|
461
|
-
raise Exception(f"Failed after {self.config.max_retries} attempts")
|
|
462
|
-
|
|
463
|
-
async def close(self):
|
|
464
|
-
"""Close the client."""
|
|
465
|
-
if self._client:
|
|
466
|
-
await self._client.aclose()
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
class SyncChatInterface:
|
|
470
|
-
"""Nested interface to match OpenAI client structure (sync version)."""
|
|
471
|
-
|
|
472
|
-
def __init__(self, client):
|
|
473
|
-
self._client = client
|
|
474
|
-
self.completions = self
|
|
475
|
-
|
|
476
|
-
def create(self, **kwargs):
|
|
477
|
-
"""Create chat completion - matches OpenAI interface."""
|
|
478
|
-
result = self._client.chat_completions_create(**kwargs)
|
|
479
|
-
# Convert dict response to object-like structure for OpenAI compatibility
|
|
480
|
-
return OpenAIResponse(result)
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
class SyncSynthClient:
|
|
484
|
-
"""Sync client with OpenAI-compatible interface."""
|
|
485
|
-
|
|
486
|
-
def __init__(
|
|
487
|
-
self,
|
|
488
|
-
config: SynthConfig | None = None,
|
|
489
|
-
api_key: Optional[str] = None,
|
|
490
|
-
base_url: Optional[str] = None,
|
|
491
|
-
**_: Any,
|
|
492
|
-
):
|
|
493
|
-
"""Initialize with config or OpenAI-style parameters/env."""
|
|
494
|
-
if config is None and (api_key or base_url):
|
|
495
|
-
config = SynthConfig(
|
|
496
|
-
base_url=base_url or os.getenv("OPENAI_API_BASE") or os.getenv("SYNTH_BASE_URL"),
|
|
497
|
-
api_key=api_key or os.getenv("OPENAI_API_KEY") or os.getenv("SYNTH_API_KEY"),
|
|
498
|
-
)
|
|
499
|
-
elif config is None and (os.getenv("OPENAI_API_BASE") and os.getenv("OPENAI_API_KEY")):
|
|
500
|
-
config = SynthConfig(
|
|
501
|
-
base_url=os.getenv("OPENAI_API_BASE"),
|
|
502
|
-
api_key=os.getenv("OPENAI_API_KEY"),
|
|
503
|
-
)
|
|
504
|
-
self.config = config or SynthConfig.from_env()
|
|
505
|
-
self._client = None
|
|
506
|
-
|
|
507
|
-
# Create nested OpenAI-style interface
|
|
508
|
-
self.chat = SyncChatInterface(self)
|
|
509
|
-
self.completions = self.chat # Alias for backward compatibility
|
|
510
|
-
|
|
511
|
-
def __enter__(self):
|
|
512
|
-
self._client = httpx.Client(
|
|
513
|
-
timeout=self.config.timeout,
|
|
514
|
-
headers={
|
|
515
|
-
"Authorization": f"Bearer {self.config.api_key}",
|
|
516
|
-
"Content-Type": "application/json",
|
|
517
|
-
},
|
|
518
|
-
)
|
|
519
|
-
return self
|
|
520
|
-
|
|
521
|
-
def __exit__(self, *args):
|
|
522
|
-
if self._client:
|
|
523
|
-
self._client.close()
|
|
524
|
-
|
|
525
|
-
def _ensure_client(self):
|
|
526
|
-
"""Ensure client is initialized."""
|
|
527
|
-
if self._client is None:
|
|
528
|
-
self._client = httpx.Client(
|
|
529
|
-
timeout=self.config.timeout,
|
|
530
|
-
headers={
|
|
531
|
-
"Authorization": f"Bearer {self.config.api_key}",
|
|
532
|
-
"Content-Type": "application/json",
|
|
533
|
-
},
|
|
534
|
-
)
|
|
535
|
-
|
|
536
|
-
def responses_create(
|
|
537
|
-
self,
|
|
538
|
-
model: str,
|
|
539
|
-
messages: list[dict[str, Any]],
|
|
540
|
-
previous_response_id: str | None = None,
|
|
541
|
-
tools: list[dict[str, Any]] | None = None,
|
|
542
|
-
tool_choice: str | dict[str, Any] | None = "auto",
|
|
543
|
-
**kwargs,
|
|
544
|
-
) -> dict[str, Any]:
|
|
545
|
-
"""
|
|
546
|
-
Create response using Synth Responses API (sync version).
|
|
547
|
-
|
|
548
|
-
See AsyncSynthClient.responses_create for full parameter documentation.
|
|
549
|
-
"""
|
|
550
|
-
self._ensure_client()
|
|
551
|
-
|
|
552
|
-
# Build payload for Responses API
|
|
553
|
-
payload = {
|
|
554
|
-
"model": model,
|
|
555
|
-
"messages": messages,
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
# Add optional parameters
|
|
559
|
-
if previous_response_id is not None:
|
|
560
|
-
payload["previous_response_id"] = previous_response_id
|
|
561
|
-
if tools is not None:
|
|
562
|
-
payload["tools"] = tools
|
|
563
|
-
payload["tool_choice"] = tool_choice
|
|
564
|
-
|
|
565
|
-
# Add any additional kwargs
|
|
566
|
-
payload.update(kwargs)
|
|
567
|
-
|
|
568
|
-
# Retry logic
|
|
569
|
-
for attempt in range(self.config.max_retries):
|
|
570
|
-
try:
|
|
571
|
-
response = self._client.post(
|
|
572
|
-
f"{self.config.get_base_url_without_v1()}/v1/responses", json=payload
|
|
573
|
-
)
|
|
574
|
-
|
|
575
|
-
if response.status_code == 200:
|
|
576
|
-
return response.json()
|
|
577
|
-
|
|
578
|
-
# Handle rate limits
|
|
579
|
-
if response.status_code == 429:
|
|
580
|
-
wait_time = 2**attempt
|
|
581
|
-
logger.warning(f"Rate limited, waiting {wait_time}s...")
|
|
582
|
-
import time
|
|
583
|
-
|
|
584
|
-
time.sleep(wait_time)
|
|
585
|
-
continue
|
|
586
|
-
|
|
587
|
-
# Other errors
|
|
588
|
-
error_msg = f"API error {response.status_code}: {response.text}"
|
|
589
|
-
logger.error(error_msg)
|
|
590
|
-
raise Exception(error_msg)
|
|
591
|
-
|
|
592
|
-
except httpx.TimeoutException:
|
|
593
|
-
if attempt < self.config.max_retries - 1:
|
|
594
|
-
logger.warning(f"Timeout on attempt {attempt + 1}, retrying...")
|
|
595
|
-
continue
|
|
596
|
-
raise
|
|
597
|
-
|
|
598
|
-
raise Exception(f"Failed after {self.config.max_retries} attempts")
|
|
599
|
-
|
|
600
|
-
def chat_completions_create(
|
|
601
|
-
self, model: str, messages: list[dict[str, Any]], **kwargs
|
|
602
|
-
) -> dict[str, Any]:
|
|
603
|
-
"""
|
|
604
|
-
Create chat completion with OpenAI-compatible API (sync version).
|
|
605
|
-
|
|
606
|
-
See AsyncSynthClient.chat_completions_create for full parameter documentation.
|
|
607
|
-
"""
|
|
608
|
-
self._ensure_client()
|
|
609
|
-
|
|
610
|
-
# Build payload (same as async version)
|
|
611
|
-
payload = {"model": model, "messages": messages, **kwargs}
|
|
612
|
-
|
|
613
|
-
# Retry logic
|
|
614
|
-
for attempt in range(self.config.max_retries):
|
|
615
|
-
try:
|
|
616
|
-
response = self._client.post(
|
|
617
|
-
f"{self.config.get_base_url_without_v1()}/v1/chat/completions", json=payload
|
|
618
|
-
)
|
|
619
|
-
|
|
620
|
-
if response.status_code == 200:
|
|
621
|
-
return response.json()
|
|
622
|
-
|
|
623
|
-
# Handle rate limits
|
|
624
|
-
if response.status_code == 429:
|
|
625
|
-
wait_time = 2**attempt
|
|
626
|
-
logger.warning(f"Rate limited, waiting {wait_time}s...")
|
|
627
|
-
import time
|
|
628
|
-
|
|
629
|
-
time.sleep(wait_time)
|
|
630
|
-
continue
|
|
631
|
-
|
|
632
|
-
# Other errors
|
|
633
|
-
error_msg = f"API error {response.status_code}: {response.text}"
|
|
634
|
-
logger.error(error_msg)
|
|
635
|
-
raise Exception(error_msg)
|
|
636
|
-
|
|
637
|
-
except httpx.TimeoutException:
|
|
638
|
-
if attempt < self.config.max_retries - 1:
|
|
639
|
-
logger.warning(f"Timeout on attempt {attempt + 1}, retrying...")
|
|
640
|
-
continue
|
|
641
|
-
raise
|
|
642
|
-
|
|
643
|
-
raise Exception(f"Failed after {self.config.max_retries} attempts")
|
|
644
|
-
|
|
645
|
-
def close(self):
|
|
646
|
-
"""Close the client."""
|
|
647
|
-
if self._client:
|
|
648
|
-
self._client.close()
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
# Factory functions for easy instantiation
|
|
652
|
-
def create_async_client(config: SynthConfig | None = None) -> AsyncSynthClient:
|
|
653
|
-
"""
|
|
654
|
-
Create async Synth client.
|
|
655
|
-
|
|
656
|
-
Args:
|
|
657
|
-
config: Optional SynthConfig. If not provided, loads from environment.
|
|
658
|
-
|
|
659
|
-
Returns:
|
|
660
|
-
AsyncSynthClient instance
|
|
661
|
-
"""
|
|
662
|
-
return AsyncSynthClient(config)
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
def create_sync_client(config: SynthConfig | None = None) -> SyncSynthClient:
|
|
666
|
-
"""
|
|
667
|
-
Create sync Synth client.
|
|
668
|
-
|
|
669
|
-
Args:
|
|
670
|
-
config: Optional SynthConfig. If not provided, loads from environment.
|
|
671
|
-
|
|
672
|
-
Returns:
|
|
673
|
-
SyncSynthClient instance
|
|
674
|
-
"""
|
|
675
|
-
return SyncSynthClient(config)
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
# Drop-in replacements for OpenAI clients
|
|
679
|
-
# These allow Synth to be used as a complete replacement for OpenAI
|
|
680
|
-
|
|
681
|
-
class AsyncOpenAI(AsyncSynthClient):
|
|
682
|
-
"""
|
|
683
|
-
Drop-in replacement for openai.AsyncOpenAI.
|
|
684
|
-
|
|
685
|
-
Use Synth backend instead of OpenAI while maintaining the same API.
|
|
686
|
-
|
|
687
|
-
Example:
|
|
688
|
-
from synth_ai.lm.vendors.synth_client import AsyncOpenAI
|
|
689
|
-
|
|
690
|
-
client = AsyncOpenAI(
|
|
691
|
-
api_key="sk_live_...",
|
|
692
|
-
base_url="https://synth-backend-dev-docker.onrender.com/api"
|
|
693
|
-
)
|
|
694
|
-
|
|
695
|
-
# Works exactly like openai.AsyncOpenAI!
|
|
696
|
-
response = await client.chat.completions.create(
|
|
697
|
-
model="Qwen/Qwen3-0.6B",
|
|
698
|
-
messages=[{"role": "user", "content": "Hello"}]
|
|
699
|
-
)
|
|
700
|
-
"""
|
|
701
|
-
|
|
702
|
-
def __init__(self, api_key: str | None = None, base_url: str | None = None, **kwargs):
|
|
703
|
-
"""
|
|
704
|
-
Initialize AsyncOpenAI-compatible Synth client.
|
|
705
|
-
|
|
706
|
-
Args:
|
|
707
|
-
api_key: Synth API key (if not provided, uses SYNTH_API_KEY env var)
|
|
708
|
-
base_url: Synth base URL (if not provided, uses OPENAI_API_BASE env var)
|
|
709
|
-
**kwargs: Additional arguments passed to AsyncSynthClient
|
|
710
|
-
"""
|
|
711
|
-
# Handle OpenAI-style initialization
|
|
712
|
-
from ..config import SynthConfig
|
|
713
|
-
if api_key or base_url:
|
|
714
|
-
config = SynthConfig(
|
|
715
|
-
base_url=base_url or os.getenv("OPENAI_API_BASE", "https://synth-backend-dev-docker.onrender.com/api"),
|
|
716
|
-
api_key=api_key or os.getenv("OPENAI_API_KEY", "")
|
|
717
|
-
)
|
|
718
|
-
else:
|
|
719
|
-
# Fallback to environment variables (OPENAI_* first, then SYNTH_*)
|
|
720
|
-
env_base = os.getenv("OPENAI_API_BASE") or os.getenv("SYNTH_BASE_URL")
|
|
721
|
-
env_key = os.getenv("OPENAI_API_KEY") or os.getenv("SYNTH_API_KEY")
|
|
722
|
-
config = SynthConfig(base_url=env_base, api_key=env_key) if env_base and env_key else None
|
|
723
|
-
|
|
724
|
-
super().__init__(config, **kwargs)
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
class OpenAI(SyncSynthClient):
|
|
728
|
-
"""
|
|
729
|
-
Drop-in replacement for openai.OpenAI.
|
|
730
|
-
|
|
731
|
-
Synchronous version of AsyncOpenAI for Synth backend.
|
|
732
|
-
"""
|
|
733
|
-
|
|
734
|
-
def __init__(self, api_key: str | None = None, base_url: str | None = None, **kwargs):
|
|
735
|
-
"""
|
|
736
|
-
Initialize OpenAI-compatible Synth client.
|
|
737
|
-
|
|
738
|
-
Args:
|
|
739
|
-
api_key: Synth API key (if not provided, uses SYNTH_API_KEY env var)
|
|
740
|
-
base_url: Synth base URL (if not provided, uses OPENAI_API_BASE env var)
|
|
741
|
-
**kwargs: Additional arguments passed to SyncSynthClient
|
|
742
|
-
"""
|
|
743
|
-
# Handle OpenAI-style initialization
|
|
744
|
-
from ..config import SynthConfig
|
|
745
|
-
if api_key or base_url:
|
|
746
|
-
config = SynthConfig(
|
|
747
|
-
base_url=base_url or os.getenv("OPENAI_API_BASE", "https://synth-backend-dev-docker.onrender.com/api"),
|
|
748
|
-
api_key=api_key or os.getenv("OPENAI_API_KEY", "")
|
|
749
|
-
)
|
|
750
|
-
else:
|
|
751
|
-
env_base = os.getenv("OPENAI_API_BASE") or os.getenv("SYNTH_BASE_URL")
|
|
752
|
-
env_key = os.getenv("OPENAI_API_KEY") or os.getenv("SYNTH_API_KEY")
|
|
753
|
-
config = SynthConfig(base_url=env_base, api_key=env_key) if env_base and env_key else None
|
|
754
|
-
|
|
755
|
-
super().__init__(config, **kwargs)
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
# Convenience imports for easy usage
|
|
759
|
-
__all__ = [
|
|
760
|
-
"AsyncSynthClient",
|
|
761
|
-
"SyncSynthClient",
|
|
762
|
-
"AsyncOpenAI", # Drop-in replacement for openai.AsyncOpenAI
|
|
763
|
-
"OpenAI", # Drop-in replacement for openai.OpenAI
|
|
764
|
-
"create_async_client",
|
|
765
|
-
"create_sync_client",
|
|
766
|
-
"create_chat_completion_async",
|
|
767
|
-
"create_chat_completion_sync",
|
|
768
|
-
"SynthConfig",
|
|
769
|
-
]
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
# Convenience functions for one-off requests
|
|
773
|
-
async def create_chat_completion_async(
|
|
774
|
-
model: str, messages: list[dict[str, Any]], config: SynthConfig | None = None, **kwargs
|
|
775
|
-
) -> dict[str, Any]:
|
|
776
|
-
"""
|
|
777
|
-
Create a chat completion with automatic client management.
|
|
778
|
-
|
|
779
|
-
Args:
|
|
780
|
-
model: Model identifier
|
|
781
|
-
messages: List of message dicts
|
|
782
|
-
config: Optional SynthConfig
|
|
783
|
-
**kwargs: Additional parameters for chat completion
|
|
784
|
-
|
|
785
|
-
Returns:
|
|
786
|
-
OpenAI-compatible response dict
|
|
787
|
-
"""
|
|
788
|
-
async with create_async_client(config) as client:
|
|
789
|
-
return await client.chat_completions_create(model, messages, **kwargs)
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
def create_chat_completion_sync(
|
|
793
|
-
model: str, messages: list[dict[str, Any]], config: SynthConfig | None = None, **kwargs
|
|
794
|
-
) -> dict[str, Any]:
|
|
795
|
-
"""
|
|
796
|
-
Create a chat completion with automatic client management (sync version).
|
|
797
|
-
|
|
798
|
-
Args:
|
|
799
|
-
model: Model identifier
|
|
800
|
-
messages: List of message dicts
|
|
801
|
-
config: Optional SynthConfig
|
|
802
|
-
**kwargs: Additional parameters for chat completion
|
|
803
|
-
|
|
804
|
-
Returns:
|
|
805
|
-
OpenAI-compatible response dict
|
|
806
|
-
"""
|
|
807
|
-
with create_sync_client(config) as client:
|
|
808
|
-
return client.chat_completions_create(model, messages, **kwargs)
|