synth-ai 0.2.9.dev5__py3-none-any.whl → 0.2.10__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.

Files changed (349) hide show
  1. examples/__init__.py +16 -0
  2. examples/crafter_debug_render.py +23 -17
  3. examples/dev/qwen3_32b_qlora_4xh100.toml +40 -0
  4. examples/multi_step/crafter_rl_lora.md +29 -0
  5. examples/qwen_coder/README.md +102 -0
  6. examples/qwen_coder/_shared.py +113 -0
  7. examples/qwen_coder/configs/coder_lora_30b.toml +61 -0
  8. examples/qwen_coder/configs/coder_lora_4b.toml +57 -0
  9. examples/qwen_coder/configs/coder_lora_small.toml +58 -0
  10. examples/qwen_coder/generate_dataset.py +98 -0
  11. examples/qwen_coder/infer_ft_smoke.py +65 -0
  12. examples/qwen_coder/infer_prod_proxy.py +73 -0
  13. examples/qwen_coder/infer_via_synth.py +87 -0
  14. examples/qwen_coder/scripts/infer_coder.sh +19 -0
  15. examples/qwen_coder/scripts/train_coder_30b.sh +22 -0
  16. examples/qwen_coder/sft_full_17b.py +103 -0
  17. examples/qwen_coder/sft_lora_30b.py +110 -0
  18. examples/qwen_coder/subset_jsonl.py +39 -0
  19. examples/qwen_coder/todos.md +38 -0
  20. examples/qwen_coder/validate_jsonl.py +60 -0
  21. examples/rl/configs/eval_base_qwen.toml +1 -1
  22. examples/rl/configs/rl_from_base_qwen17.toml +1 -1
  23. examples/rl/download_dataset.py +26 -10
  24. examples/rl/run_eval.py +53 -52
  25. examples/rl/run_rl_and_save.py +29 -12
  26. examples/rl/task_app/math_single_step.py +180 -41
  27. examples/rl/task_app/math_task_app.py +14 -6
  28. examples/sft/README.md +139 -0
  29. examples/sft/configs/crafter_fft_qwen0p6b.toml +44 -0
  30. examples/sft/configs/crafter_lora_qwen0p6b.toml +45 -0
  31. examples/sft/evaluate.py +117 -0
  32. examples/sft/export_dataset.py +117 -0
  33. examples/sft/generate_traces.py +162 -0
  34. examples/swe/__init__.py +12 -0
  35. examples/swe/task_app/README.md +105 -0
  36. examples/swe/task_app/__init__.py +2 -0
  37. examples/swe/task_app/grpo_swe_mini.py +571 -0
  38. examples/swe/task_app/grpo_swe_mini_task_app.py +136 -0
  39. examples/swe/task_app/hosted/README.md +173 -0
  40. examples/swe/task_app/hosted/__init__.py +5 -0
  41. examples/swe/task_app/hosted/branching.py +143 -0
  42. examples/swe/task_app/hosted/environment_routes.py +1289 -0
  43. examples/swe/task_app/hosted/envs/__init__.py +1 -0
  44. examples/swe/task_app/hosted/envs/crafter/__init__.py +6 -0
  45. examples/swe/task_app/hosted/envs/crafter/app.py +1 -0
  46. examples/swe/task_app/hosted/envs/crafter/environment.py +522 -0
  47. examples/swe/task_app/hosted/envs/crafter/policy.py +478 -0
  48. examples/swe/task_app/hosted/envs/crafter/react_agent.py +108 -0
  49. examples/swe/task_app/hosted/envs/crafter/shared.py +305 -0
  50. examples/swe/task_app/hosted/envs/crafter/tools.py +47 -0
  51. examples/swe/task_app/hosted/envs/mini_swe/__init__.py +8 -0
  52. examples/swe/task_app/hosted/envs/mini_swe/environment.py +1164 -0
  53. examples/swe/task_app/hosted/envs/mini_swe/policy.py +355 -0
  54. examples/swe/task_app/hosted/envs/mini_swe/shared.py +83 -0
  55. examples/swe/task_app/hosted/envs/mini_swe/tools.py +96 -0
  56. examples/swe/task_app/hosted/hosted_app.py +204 -0
  57. examples/swe/task_app/hosted/inference/__init__.py +5 -0
  58. examples/swe/task_app/hosted/inference/openai_client.py +618 -0
  59. examples/swe/task_app/hosted/main.py +100 -0
  60. examples/swe/task_app/hosted/policy_routes.py +1079 -0
  61. examples/swe/task_app/hosted/registry.py +195 -0
  62. examples/swe/task_app/hosted/rollout.py +1869 -0
  63. examples/swe/task_app/hosted/storage/__init__.py +5 -0
  64. examples/swe/task_app/hosted/storage/volume.py +211 -0
  65. examples/swe/task_app/hosted/test_agents.py +161 -0
  66. examples/swe/task_app/hosted/test_service.py +137 -0
  67. examples/swe/task_app/hosted/utils.py +62 -0
  68. examples/vlm/PROPOSAL.md +53 -0
  69. examples/vlm/README.md +68 -0
  70. examples/vlm/configs/crafter_vlm_gpt4o.toml +44 -0
  71. examples/vlm/crafter_image_only_agent.py +207 -0
  72. examples/vlm/crafter_openai_vlm_agent.py +277 -0
  73. examples/vlm/filter_image_rows.py +63 -0
  74. examples/vlm/run_crafter_vlm_benchmark.py +316 -0
  75. examples/warming_up_to_rl/analyze_trace_db.py +12 -10
  76. examples/warming_up_to_rl/configs/rl_from_base_qwen4b.toml +11 -1
  77. examples/warming_up_to_rl/export_trace_sft.py +218 -36
  78. examples/warming_up_to_rl/groq_test.py +15 -8
  79. examples/warming_up_to_rl/manage_secrets.py +29 -25
  80. examples/warming_up_to_rl/readme.md +9 -2
  81. examples/warming_up_to_rl/run_eval.py +137 -61
  82. examples/warming_up_to_rl/run_fft_and_save.py +131 -60
  83. examples/warming_up_to_rl/run_local_rollout.py +88 -39
  84. examples/warming_up_to_rl/run_local_rollout_modal.py +114 -28
  85. examples/warming_up_to_rl/run_local_rollout_parallel.py +81 -20
  86. examples/warming_up_to_rl/run_local_rollout_traced.py +126 -23
  87. examples/warming_up_to_rl/run_rl_and_save.py +35 -12
  88. examples/warming_up_to_rl/run_rollout_remote.py +44 -19
  89. examples/warming_up_to_rl/task_app/README.md +6 -2
  90. examples/warming_up_to_rl/task_app/grpo_crafter.py +319 -57
  91. examples/warming_up_to_rl/task_app/grpo_crafter_task_app.py +11 -30
  92. examples/warming_up_to_rl/task_app/synth_envs_hosted/__init__.py +1 -1
  93. examples/warming_up_to_rl/task_app/synth_envs_hosted/branching.py +9 -11
  94. examples/warming_up_to_rl/task_app/synth_envs_hosted/environment_routes.py +137 -182
  95. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/__init__.py +1 -1
  96. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/__init__.py +1 -1
  97. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/app.py +1 -1
  98. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/environment.py +150 -57
  99. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/policy.py +105 -69
  100. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/react_agent.py +19 -7
  101. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/shared.py +45 -42
  102. examples/warming_up_to_rl/task_app/synth_envs_hosted/envs/crafter/tools.py +1 -1
  103. examples/warming_up_to_rl/task_app/synth_envs_hosted/hosted_app.py +47 -45
  104. examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/__init__.py +1 -1
  105. examples/warming_up_to_rl/task_app/synth_envs_hosted/inference/openai_client.py +198 -92
  106. examples/warming_up_to_rl/task_app/synth_envs_hosted/main.py +0 -2
  107. examples/warming_up_to_rl/task_app/synth_envs_hosted/policy_routes.py +361 -263
  108. examples/warming_up_to_rl/task_app/synth_envs_hosted/registry.py +21 -23
  109. examples/warming_up_to_rl/task_app/synth_envs_hosted/rollout.py +394 -274
  110. examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/__init__.py +1 -1
  111. examples/warming_up_to_rl/task_app/synth_envs_hosted/storage/volume.py +56 -62
  112. examples/warming_up_to_rl/task_app/synth_envs_hosted/test_agents.py +1 -0
  113. examples/warming_up_to_rl/task_app/synth_envs_hosted/test_service.py +6 -15
  114. examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +4 -3
  115. synth_ai/__init__.py +1 -0
  116. synth_ai/api/models/supported.py +376 -0
  117. synth_ai/api/train/builders.py +157 -26
  118. synth_ai/api/train/cli.py +213 -57
  119. synth_ai/api/train/config_finder.py +65 -5
  120. synth_ai/api/train/env_resolver.py +33 -15
  121. synth_ai/api/train/pollers.py +13 -4
  122. synth_ai/api/train/supported_algos.py +139 -0
  123. synth_ai/api/train/task_app.py +5 -3
  124. synth_ai/api/train/utils.py +33 -48
  125. synth_ai/cli/__init__.py +19 -4
  126. synth_ai/cli/_modal_wrapper.py +28 -0
  127. synth_ai/cli/_typer_patch.py +49 -0
  128. synth_ai/cli/balance.py +2 -3
  129. synth_ai/cli/calc.py +1 -1
  130. synth_ai/cli/demo.py +21 -6
  131. synth_ai/cli/recent.py +2 -2
  132. synth_ai/cli/rl_demo.py +77 -17
  133. synth_ai/cli/root.py +116 -39
  134. synth_ai/cli/status.py +2 -2
  135. synth_ai/cli/task_apps.py +1699 -259
  136. synth_ai/cli/traces.py +7 -4
  137. synth_ai/cli/turso.py +73 -0
  138. synth_ai/cli/watch.py +12 -18
  139. synth_ai/core/experiment.py +0 -2
  140. synth_ai/demo_registry.py +68 -31
  141. synth_ai/demos/core/cli.py +516 -194
  142. synth_ai/demos/demo_task_apps/__init__.py +3 -3
  143. synth_ai/demos/demo_task_apps/core.py +64 -28
  144. synth_ai/demos/demo_task_apps/crafter/configs/crafter_fft_4b.toml +2 -3
  145. synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +37 -30
  146. synth_ai/demos/demo_task_apps/math/_common.py +1 -2
  147. synth_ai/demos/demo_task_apps/math/app.py +2 -1
  148. synth_ai/demos/demo_task_apps/math/deploy_modal.py +3 -6
  149. synth_ai/demos/demo_task_apps/math/modal_task_app.py +183 -82
  150. synth_ai/demos/demo_task_apps/math/task_app_entry.py +0 -2
  151. synth_ai/environments/examples/bandit/engine.py +12 -4
  152. synth_ai/environments/examples/bandit/taskset.py +4 -4
  153. synth_ai/environments/examples/crafter_classic/environment.py +76 -1
  154. synth_ai/environments/reproducibility/tree.py +5 -6
  155. synth_ai/environments/service/app.py +11 -12
  156. synth_ai/environments/service/core_routes.py +10 -9
  157. synth_ai/environments/stateful/engine.py +1 -1
  158. synth_ai/environments/tasks/core.py +1 -0
  159. synth_ai/environments/tasks/filters.py +5 -6
  160. synth_ai/environments/tasks/utils.py +4 -5
  161. synth_ai/evals/base.py +0 -2
  162. synth_ai/handshake.py +11 -9
  163. synth_ai/http.py +1 -1
  164. synth_ai/http_client.py +43 -11
  165. synth_ai/inference/__init__.py +0 -2
  166. synth_ai/inference/client.py +20 -6
  167. synth_ai/jobs/client.py +103 -78
  168. synth_ai/learning/__init__.py +41 -6
  169. synth_ai/learning/algorithms.py +14 -0
  170. synth_ai/learning/client.py +121 -29
  171. synth_ai/learning/config.py +2 -40
  172. synth_ai/learning/constants.py +0 -2
  173. synth_ai/learning/ft_client.py +4 -56
  174. synth_ai/learning/health.py +13 -7
  175. synth_ai/learning/jobs.py +43 -47
  176. synth_ai/{rl → learning/rl}/__init__.py +14 -5
  177. synth_ai/learning/rl/client.py +267 -0
  178. synth_ai/learning/rl/config.py +31 -0
  179. synth_ai/{rl → learning/rl}/contracts.py +5 -10
  180. synth_ai/{rl → learning/rl}/env_keys.py +45 -16
  181. synth_ai/learning/rl/secrets.py +13 -0
  182. synth_ai/learning/rl_client.py +2 -253
  183. synth_ai/learning/sft/__init__.py +29 -0
  184. synth_ai/learning/sft/client.py +68 -0
  185. synth_ai/learning/sft/config.py +270 -0
  186. synth_ai/learning/sft/data.py +295 -0
  187. synth_ai/learning/sse.py +25 -26
  188. synth_ai/learning/validators.py +25 -24
  189. synth_ai/lm/__init__.py +21 -47
  190. synth_ai/task/__init__.py +26 -27
  191. synth_ai/task/apps/__init__.py +18 -19
  192. synth_ai/task/auth.py +35 -23
  193. synth_ai/task/client.py +15 -13
  194. synth_ai/task/contracts.py +37 -35
  195. synth_ai/task/datasets.py +9 -6
  196. synth_ai/task/errors.py +11 -10
  197. synth_ai/task/health.py +17 -11
  198. synth_ai/task/json.py +58 -24
  199. synth_ai/task/proxy.py +15 -14
  200. synth_ai/task/rubrics.py +22 -15
  201. synth_ai/task/server.py +43 -17
  202. synth_ai/task/tracing_utils.py +12 -7
  203. synth_ai/task/validators.py +0 -1
  204. synth_ai/task/vendors.py +5 -7
  205. synth_ai/tracing_v3/__init__.py +2 -0
  206. synth_ai/tracing_v3/abstractions.py +21 -4
  207. synth_ai/tracing_v3/db_config.py +26 -1
  208. synth_ai/tracing_v3/decorators.py +18 -15
  209. synth_ai/tracing_v3/examples/basic_usage.py +3 -2
  210. synth_ai/tracing_v3/hooks.py +6 -4
  211. synth_ai/tracing_v3/llm_call_record_helpers.py +6 -6
  212. synth_ai/tracing_v3/replica_sync.py +1 -0
  213. synth_ai/tracing_v3/session_tracer.py +63 -16
  214. synth_ai/tracing_v3/storage/base.py +89 -1
  215. synth_ai/tracing_v3/storage/config.py +21 -8
  216. synth_ai/tracing_v3/storage/factory.py +10 -8
  217. synth_ai/tracing_v3/storage/utils.py +4 -2
  218. synth_ai/tracing_v3/turso/daemon.py +7 -2
  219. synth_ai/tracing_v3/turso/models.py +5 -2
  220. synth_ai/tracing_v3/turso/native_manager.py +1173 -0
  221. synth_ai/tracing_v3/utils.py +4 -3
  222. synth_ai/v0/api/__init__.py +8 -0
  223. synth_ai/v0/api/models/__init__.py +8 -0
  224. synth_ai/v0/api/models/supported.py +8 -0
  225. synth_ai/v0/config/__init__.py +15 -0
  226. synth_ai/v0/config/base_url.py +12 -0
  227. synth_ai/v0/lm/__init__.py +51 -0
  228. synth_ai/{lm → v0/lm}/caching/ephemeral.py +3 -5
  229. synth_ai/{lm → v0/lm}/caching/handler.py +4 -4
  230. synth_ai/{lm → v0/lm}/caching/initialize.py +1 -1
  231. synth_ai/{lm → v0/lm}/caching/persistent.py +1 -1
  232. synth_ai/{lm → v0/lm}/config.py +6 -1
  233. synth_ai/{lm → v0/lm}/core/all.py +9 -9
  234. synth_ai/{lm → v0/lm}/core/exceptions.py +0 -2
  235. synth_ai/{lm → v0/lm}/core/main.py +19 -7
  236. synth_ai/{lm → v0/lm}/core/main_v3.py +10 -10
  237. synth_ai/{lm → v0/lm}/core/synth_models.py +2 -15
  238. synth_ai/{lm → v0/lm}/core/vendor_clients.py +6 -4
  239. synth_ai/{lm → v0/lm}/overrides.py +4 -4
  240. synth_ai/{lm → v0/lm}/provider_support/anthropic.py +4 -4
  241. synth_ai/{lm → v0/lm}/provider_support/openai.py +5 -5
  242. synth_ai/{lm → v0/lm}/structured_outputs/handler.py +5 -5
  243. synth_ai/{lm → v0/lm}/structured_outputs/rehabilitate.py +1 -1
  244. synth_ai/{lm → v0/lm}/vendors/core/anthropic_api.py +16 -16
  245. synth_ai/{lm → v0/lm}/vendors/core/gemini_api.py +5 -5
  246. synth_ai/{lm → v0/lm}/vendors/core/mistral_api.py +5 -5
  247. synth_ai/{lm → v0/lm}/vendors/core/openai_api.py +12 -10
  248. synth_ai/{lm → v0/lm}/vendors/openai_standard.py +11 -9
  249. synth_ai/{lm → v0/lm}/vendors/openai_standard_responses.py +8 -5
  250. synth_ai/{lm → v0/lm}/vendors/supported/custom_endpoint.py +4 -6
  251. synth_ai/{lm → v0/lm}/vendors/supported/deepseek.py +2 -2
  252. synth_ai/{lm → v0/lm}/vendors/supported/grok.py +2 -2
  253. synth_ai/{lm → v0/lm}/vendors/supported/groq.py +1 -1
  254. synth_ai/{lm → v0/lm}/vendors/supported/ollama.py +1 -1
  255. synth_ai/{lm → v0/lm}/vendors/supported/openrouter.py +3 -3
  256. synth_ai/{lm → v0/lm}/vendors/supported/together.py +1 -1
  257. synth_ai/{lm → v0/lm}/vendors/synth_client.py +38 -11
  258. synth_ai/v0/tracing/upload.py +32 -135
  259. synth_ai/v0/tracing_v3/__init__.py +10 -0
  260. synth_ai/v0/tracing_v3/abstractions.py +3 -0
  261. synth_ai/v0/tracing_v3/decorators.py +3 -0
  262. synth_ai/v0/tracing_v3/llm_call_record_helpers.py +3 -0
  263. synth_ai/v0/tracing_v3/session_tracer.py +3 -0
  264. {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.10.dist-info}/METADATA +10 -7
  265. {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.10.dist-info}/RECORD +294 -258
  266. examples/common_old/backend.py +0 -21
  267. examples/evals_old/README.md +0 -98
  268. examples/evals_old/__init__.py +0 -6
  269. examples/evals_old/compare_models.py +0 -1037
  270. examples/evals_old/example_log.md +0 -145
  271. examples/evals_old/run_demo.sh +0 -126
  272. examples/evals_old/trace_analysis.py +0 -270
  273. examples/finetuning_old/_backup_synth_qwen/config.toml +0 -29
  274. examples/finetuning_old/_backup_synth_qwen/example_log.md +0 -324
  275. examples/finetuning_old/_backup_synth_qwen/filter_traces.py +0 -60
  276. examples/finetuning_old/_backup_synth_qwen/filter_traces_achievements.py +0 -239
  277. examples/finetuning_old/_backup_synth_qwen/purge_v3_traces.py +0 -109
  278. examples/finetuning_old/_backup_synth_qwen/react_agent_lm.py +0 -1924
  279. examples/finetuning_old/_backup_synth_qwen/readme.md +0 -49
  280. examples/finetuning_old/_backup_synth_qwen/run_crafter_qwen4b.py +0 -114
  281. examples/finetuning_old/_backup_synth_qwen/run_demo.sh +0 -195
  282. examples/finetuning_old/_backup_synth_qwen/sft_kickoff.py +0 -118
  283. examples/finetuning_old/synth_qwen_v1/README.md +0 -68
  284. examples/finetuning_old/synth_qwen_v1/filter_traces.py +0 -60
  285. examples/finetuning_old/synth_qwen_v1/filter_traces_achievements.py +0 -239
  286. examples/finetuning_old/synth_qwen_v1/finetune.py +0 -46
  287. examples/finetuning_old/synth_qwen_v1/hello_ft_model.py +0 -71
  288. examples/finetuning_old/synth_qwen_v1/infer.py +0 -37
  289. examples/finetuning_old/synth_qwen_v1/poll.py +0 -44
  290. examples/finetuning_old/synth_qwen_v1/prepare_data.py +0 -35
  291. examples/finetuning_old/synth_qwen_v1/purge_v3_traces.py +0 -109
  292. examples/finetuning_old/synth_qwen_v1/react_agent_lm.py +0 -1932
  293. examples/finetuning_old/synth_qwen_v1/run_crafter_sft_job.py +0 -207
  294. examples/finetuning_old/synth_qwen_v1/run_ft_job.py +0 -232
  295. examples/finetuning_old/synth_qwen_v1/upload_data.py +0 -34
  296. examples/finetuning_old/synth_qwen_v1/util.py +0 -147
  297. examples/rl_old/task_app.py +0 -962
  298. synth_ai/experimental/synth_oss.py +0 -446
  299. synth_ai/install_sqld.sh +0 -40
  300. synth_ai/learning/filtering.py +0 -0
  301. synth_ai/learning/offline/dpo.py +0 -0
  302. synth_ai/learning/offline/providers.py +0 -7
  303. synth_ai/learning/offline/sft.py +0 -0
  304. synth_ai/learning/offline/shared.py +0 -0
  305. synth_ai/learning/online/grpo.py +0 -0
  306. synth_ai/learning/online/irft.py +0 -0
  307. synth_ai/learning/prompts/banking77_injection_eval.py +0 -168
  308. synth_ai/learning/prompts/gepa.py +0 -0
  309. synth_ai/learning/prompts/hello_world_in_context_injection_ex.py +0 -213
  310. synth_ai/learning/prompts/mipro.py +0 -289
  311. synth_ai/learning/prompts/random_search.py +0 -246
  312. synth_ai/learning/prompts/run_mipro_banking77.py +0 -172
  313. synth_ai/learning/prompts/run_random_search_banking77.py +0 -324
  314. synth_ai/rl/secrets.py +0 -19
  315. synth_ai/scripts/verify_rewards.py +0 -100
  316. synth_ai/tracing/__init__.py +0 -30
  317. synth_ai/tracing_v1/__init__.py +0 -33
  318. synth_ai/tracing_v3/turso/__init__.py +0 -25
  319. synth_ai/tracing_v3/turso/manager.py +0 -774
  320. synth_ai/zyk/__init__.py +0 -30
  321. /synth_ai/{lm → v0/lm}/caching/__init__.py +0 -0
  322. /synth_ai/{lm → v0/lm}/caching/constants.py +0 -0
  323. /synth_ai/{lm → v0/lm}/caching/dbs.py +0 -0
  324. /synth_ai/{lm → v0/lm}/constants.py +0 -0
  325. /synth_ai/{lm → v0/lm}/core/__init__.py +0 -0
  326. /synth_ai/{lm → v0/lm}/cost/__init__.py +0 -0
  327. /synth_ai/{lm → v0/lm}/cost/monitor.py +0 -0
  328. /synth_ai/{lm → v0/lm}/cost/statefulness.py +0 -0
  329. /synth_ai/{lm → v0/lm}/injection.py +0 -0
  330. /synth_ai/{lm → v0/lm}/provider_support/__init__.py +0 -0
  331. /synth_ai/{lm → v0/lm}/provider_support/suppress_logging.py +0 -0
  332. /synth_ai/{lm → v0/lm}/structured_outputs/__init__.py +0 -0
  333. /synth_ai/{lm → v0/lm}/structured_outputs/inject.py +0 -0
  334. /synth_ai/{lm → v0/lm}/tools/__init__.py +0 -0
  335. /synth_ai/{lm → v0/lm}/tools/base.py +0 -0
  336. /synth_ai/{lm → v0/lm}/unified_interface.py +0 -0
  337. /synth_ai/{lm → v0/lm}/vendors/__init__.py +0 -0
  338. /synth_ai/{lm → v0/lm}/vendors/base.py +0 -0
  339. /synth_ai/{lm → v0/lm}/vendors/core/__init__.py +0 -0
  340. /synth_ai/{lm → v0/lm}/vendors/core/synth_dev_api.py +0 -0
  341. /synth_ai/{lm → v0/lm}/vendors/local/__init__.py +0 -0
  342. /synth_ai/{lm → v0/lm}/vendors/local/ollama.py +0 -0
  343. /synth_ai/{lm → v0/lm}/vendors/retries.py +0 -0
  344. /synth_ai/{lm → v0/lm}/vendors/supported/__init__.py +0 -0
  345. /synth_ai/{lm → v0/lm}/warmup.py +0 -0
  346. {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.10.dist-info}/WHEEL +0 -0
  347. {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.10.dist-info}/entry_points.txt +0 -0
  348. {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.10.dist-info}/licenses/LICENSE +0 -0
  349. {synth_ai-0.2.9.dev5.dist-info → synth_ai-0.2.10.dist-info}/top_level.txt +0 -0
@@ -9,20 +9,20 @@ import openai
9
9
  import pydantic_core
10
10
  from pydantic import BaseModel
11
11
 
12
- from synth_ai.lm.caching.initialize import (
12
+ from synth_ai.v0.lm.caching.initialize import (
13
13
  get_cache_handler,
14
14
  )
15
- from synth_ai.lm.constants import SPECIAL_BASE_TEMPS
16
- from synth_ai.lm.injection import apply_injection
17
- from synth_ai.lm.overrides import (
15
+ from synth_ai.v0.lm.constants import SPECIAL_BASE_TEMPS
16
+ from synth_ai.v0.lm.injection import apply_injection
17
+ from synth_ai.v0.lm.overrides import (
18
18
  apply_param_overrides,
19
19
  apply_tool_overrides,
20
20
  use_overrides_for_messages,
21
21
  )
22
- from synth_ai.lm.tools.base import BaseTool
23
- from synth_ai.lm.vendors.base import BaseLMResponse, VendorBase
24
- from synth_ai.lm.vendors.openai_standard_responses import OpenAIResponsesAPIMixin
25
- from synth_ai.lm.vendors.retries import MAX_BACKOFF
22
+ from synth_ai.v0.lm.tools.base import BaseTool
23
+ from synth_ai.v0.lm.vendors.base import BaseLMResponse, VendorBase
24
+ from synth_ai.v0.lm.vendors.openai_standard_responses import OpenAIResponsesAPIMixin
25
+ from synth_ai.v0.lm.vendors.retries import MAX_BACKOFF
26
26
 
27
27
  DEFAULT_EXCEPTIONS_TO_RETRY = (
28
28
  pydantic_core._pydantic_core.ValidationError,
@@ -427,7 +427,9 @@ class OpenAIStandard(VendorBase, OpenAIResponsesAPIMixin):
427
427
  "type": getattr(tc, "type", "function"),
428
428
  "function": {
429
429
  "name": getattr(getattr(tc, "function", None), "name", None),
430
- "arguments": getattr(getattr(tc, "function", None), "arguments", None),
430
+ "arguments": getattr(
431
+ getattr(tc, "function", None), "arguments", None
432
+ ),
431
433
  },
432
434
  }
433
435
  )
@@ -8,8 +8,8 @@ that extend the OpenAIStandard class functionality.
8
8
  import uuid
9
9
  from typing import Any
10
10
 
11
- from synth_ai.lm.tools.base import BaseTool
12
- from synth_ai.lm.vendors.base import BaseLMResponse
11
+ from synth_ai.v0.lm.tools.base import BaseTool
12
+ from synth_ai.v0.lm.vendors.base import BaseLMResponse
13
13
 
14
14
 
15
15
  def _silent_backoff_handler(_details):
@@ -223,7 +223,9 @@ class OpenAIResponsesAPIMixin:
223
223
  if not synth_gpu_endpoint:
224
224
  raise ValueError("SYNTH_GPU_HARMONY_ENDPOINT environment variable not set")
225
225
 
226
- async with aiohttp.ClientSession() as session, session.post(
226
+ async with (
227
+ aiohttp.ClientSession() as session,
228
+ session.post(
227
229
  f"{synth_gpu_endpoint}/v1/completions",
228
230
  json={
229
231
  "model": model,
@@ -231,8 +233,9 @@ class OpenAIResponsesAPIMixin:
231
233
  "max_tokens": lm_config.get("max_tokens", 4096),
232
234
  "temperature": lm_config.get("temperature", 0.8),
233
235
  },
234
- ) as resp:
235
- result = await resp.json()
236
+ ) as resp,
237
+ ):
238
+ result = await resp.json()
236
239
 
237
240
  # Parse response using Harmony
238
241
  response_tokens = result.get("choices", [{}])[0].get("text", "")
@@ -11,9 +11,9 @@ import requests
11
11
  from requests.adapters import HTTPAdapter
12
12
  from urllib3.util.retry import Retry
13
13
 
14
- from synth_ai.lm.caching.initialize import get_cache_handler
15
- from synth_ai.lm.tools.base import BaseTool
16
- from synth_ai.lm.vendors.base import BaseLMResponse, VendorBase
14
+ from synth_ai.v0.lm.caching.initialize import get_cache_handler
15
+ from synth_ai.v0.lm.tools.base import BaseTool
16
+ from synth_ai.v0.lm.vendors.base import BaseLMResponse, VendorBase
17
17
 
18
18
  # Exception types for retry
19
19
  CUSTOM_ENDPOINT_EXCEPTIONS_TO_RETRY: tuple[type[Exception], ...] = (
@@ -194,9 +194,7 @@ IMPORTANT: To use a tool, respond with JSON wrapped in ```json fences:
194
194
 
195
195
  For regular responses, just respond normally without JSON fences."""
196
196
 
197
- def _extract_tool_calls(
198
- self, content: str, tools: list[BaseTool]
199
- ) -> tuple[list | None, str]:
197
+ def _extract_tool_calls(self, content: str, tools: list[BaseTool]) -> tuple[list | None, str]:
200
198
  """Extract and validate tool calls from response."""
201
199
  # Look for JSON fenced blocks
202
200
  json_pattern = r"```json\s*(\{.*?\})\s*```"
@@ -3,8 +3,8 @@ from typing import Any
3
3
 
4
4
  from openai import AsyncOpenAI, OpenAI
5
5
 
6
- from synth_ai.lm.tools.base import BaseTool
7
- from synth_ai.lm.vendors.openai_standard import OpenAIStandard
6
+ from synth_ai.v0.lm.tools.base import BaseTool
7
+ from synth_ai.v0.lm.vendors.openai_standard import OpenAIStandard
8
8
 
9
9
 
10
10
  class DeepSeekAPI(OpenAIStandard):
@@ -3,8 +3,8 @@ from typing import Any
3
3
 
4
4
  from openai import AsyncOpenAI, OpenAI
5
5
 
6
- from synth_ai.lm.tools.base import BaseTool
7
- from synth_ai.lm.vendors.openai_standard import OpenAIStandard
6
+ from synth_ai.v0.lm.tools.base import BaseTool
7
+ from synth_ai.v0.lm.vendors.openai_standard import OpenAIStandard
8
8
 
9
9
 
10
10
  class GrokAPI(OpenAIStandard):
@@ -3,7 +3,7 @@ import os
3
3
  from dotenv import load_dotenv
4
4
  from groq import AsyncGroq, Groq
5
5
 
6
- from synth_ai.lm.vendors.openai_standard import OpenAIStandard
6
+ from synth_ai.v0.lm.vendors.openai_standard import OpenAIStandard
7
7
 
8
8
  load_dotenv()
9
9
 
@@ -1,6 +1,6 @@
1
1
  from openai import AsyncOpenAI, OpenAI
2
2
 
3
- from synth_ai.lm.vendors.openai_standard import OpenAIStandard
3
+ from synth_ai.v0.lm.vendors.openai_standard import OpenAIStandard
4
4
 
5
5
 
6
6
  class OllamaAPI(OpenAIStandard):
@@ -3,9 +3,9 @@ from typing import Any
3
3
 
4
4
  from openai import AsyncOpenAI, OpenAI
5
5
 
6
- from synth_ai.lm.tools.base import BaseTool
7
- from synth_ai.lm.vendors.base import BaseLMResponse
8
- from synth_ai.lm.vendors.openai_standard import OpenAIStandard
6
+ from synth_ai.v0.lm.tools.base import BaseTool
7
+ from synth_ai.v0.lm.vendors.base import BaseLMResponse
8
+ from synth_ai.v0.lm.vendors.openai_standard import OpenAIStandard
9
9
 
10
10
 
11
11
  class OpenRouterAPI(OpenAIStandard):
@@ -2,7 +2,7 @@ import os
2
2
 
3
3
  from together import AsyncTogether, Together
4
4
 
5
- from synth_ai.lm.vendors.openai_standard import OpenAIStandard
5
+ from synth_ai.v0.lm.vendors.openai_standard import OpenAIStandard
6
6
 
7
7
 
8
8
  class TogetherAPI(OpenAIStandard):
@@ -276,8 +276,20 @@ class AsyncSynthClient:
276
276
  This method provides the OpenAI client interface structure.
277
277
  """
278
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
279
+ model,
280
+ messages,
281
+ temperature,
282
+ max_tokens,
283
+ top_p,
284
+ frequency_penalty,
285
+ presence_penalty,
286
+ stop,
287
+ stream,
288
+ tools,
289
+ tool_choice,
290
+ response_format,
291
+ seed,
292
+ **kwargs,
281
293
  )
282
294
 
283
295
  async def _chat_completions_create(
@@ -368,7 +380,8 @@ class AsyncSynthClient:
368
380
  if isinstance(bt, int) and isinstance(mt, int) and bt > mt:
369
381
  logger.warning(
370
382
  "thinking_budget (%s) exceeds max_tokens (%s) – forwarding as-is",
371
- str(bt), str(mt)
383
+ str(bt),
384
+ str(mt),
372
385
  )
373
386
  except Exception:
374
387
  pass
@@ -387,6 +400,7 @@ class AsyncSynthClient:
387
400
 
388
401
  # If streaming requested, return an async stream adapter
389
402
  if stream:
403
+
390
404
  async def _astream():
391
405
  await self._ensure_client()
392
406
  async with self._client.stream("POST", url, json=payload) as r: # type: ignore
@@ -678,6 +692,7 @@ def create_sync_client(config: SynthConfig | None = None) -> SyncSynthClient:
678
692
  # Drop-in replacements for OpenAI clients
679
693
  # These allow Synth to be used as a complete replacement for OpenAI
680
694
 
695
+
681
696
  class AsyncOpenAI(AsyncSynthClient):
682
697
  """
683
698
  Drop-in replacement for openai.AsyncOpenAI.
@@ -685,7 +700,7 @@ class AsyncOpenAI(AsyncSynthClient):
685
700
  Use Synth backend instead of OpenAI while maintaining the same API.
686
701
 
687
702
  Example:
688
- from synth_ai.lm.vendors.synth_client import AsyncOpenAI
703
+ from synth_ai.v0.lm.vendors.synth_client import AsyncOpenAI
689
704
 
690
705
  client = AsyncOpenAI(
691
706
  api_key="sk_live_...",
@@ -710,16 +725,22 @@ class AsyncOpenAI(AsyncSynthClient):
710
725
  """
711
726
  # Handle OpenAI-style initialization
712
727
  from ..config import SynthConfig
728
+
713
729
  if api_key or base_url:
714
730
  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", "")
731
+ base_url=base_url
732
+ or os.getenv(
733
+ "OPENAI_API_BASE", "https://synth-backend-dev-docker.onrender.com/api"
734
+ ),
735
+ api_key=api_key or os.getenv("OPENAI_API_KEY", ""),
717
736
  )
718
737
  else:
719
738
  # Fallback to environment variables (OPENAI_* first, then SYNTH_*)
720
739
  env_base = os.getenv("OPENAI_API_BASE") or os.getenv("SYNTH_BASE_URL")
721
740
  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
741
+ config = (
742
+ SynthConfig(base_url=env_base, api_key=env_key) if env_base and env_key else None
743
+ )
723
744
 
724
745
  super().__init__(config, **kwargs)
725
746
 
@@ -742,15 +763,21 @@ class OpenAI(SyncSynthClient):
742
763
  """
743
764
  # Handle OpenAI-style initialization
744
765
  from ..config import SynthConfig
766
+
745
767
  if api_key or base_url:
746
768
  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", "")
769
+ base_url=base_url
770
+ or os.getenv(
771
+ "OPENAI_API_BASE", "https://synth-backend-dev-docker.onrender.com/api"
772
+ ),
773
+ api_key=api_key or os.getenv("OPENAI_API_KEY", ""),
749
774
  )
750
775
  else:
751
776
  env_base = os.getenv("OPENAI_API_BASE") or os.getenv("SYNTH_BASE_URL")
752
777
  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
778
+ config = (
779
+ SynthConfig(base_url=env_base, api_key=env_key) if env_base and env_key else None
780
+ )
754
781
 
755
782
  super().__init__(config, **kwargs)
756
783
 
@@ -760,7 +787,7 @@ __all__ = [
760
787
  "AsyncSynthClient",
761
788
  "SyncSynthClient",
762
789
  "AsyncOpenAI", # Drop-in replacement for openai.AsyncOpenAI
763
- "OpenAI", # Drop-in replacement for openai.OpenAI
790
+ "OpenAI", # Drop-in replacement for openai.OpenAI
764
791
  "create_async_client",
765
792
  "create_sync_client",
766
793
  "create_chat_completion_async",
@@ -373,140 +373,37 @@ def upload_helper(
373
373
  raise ValueError("SYNTH_API_KEY environment variable not set")
374
374
  base_url = os.getenv("SYNTH_ENDPOINT_OVERRIDE", PROD_BASE_URL_DEFAULT)
375
375
 
376
- """Legacy block below retained for reference and disabled for linting/parsing.
377
- Start disabled block.
378
- """
379
- """
380
- from .decorators import _local, active_events_var
381
- from .trackers import synth_tracker_async, synth_tracker_sync
382
-
383
- # First close any tracker events
384
- if hasattr(synth_tracker_async, "active_events"):
385
- for event_type, event in list(synth_tracker_async.active_events.items()):
386
- if event and event.closed is None:
387
- event.closed = time.time()
388
- try:
389
- event_store.add_event(
390
- event.system_name,
391
- event.system_id,
392
- event.system_instance_id,
393
- event,
394
- )
395
- if verbose:
396
- print(f"Closed and stored tracker async event: {event_type}")
397
- except Exception as e:
398
- logging.error(f"Failed to store tracker event {event_type}: {str(e)}")
399
- synth_tracker_async.active_events.clear()
400
-
401
- # End all active events before uploading
402
- if hasattr(_local, "active_events"):
403
- for event_type, event in _local.active_events.items():
404
- if event and event.closed is None:
405
- event.closed = time.time()
406
- if hasattr(_local, "system_instance_id"):
407
- try:
408
- event_store.add_event(
409
- _local.system_name,
410
- _local.system_id,
411
- _local.system_instance_id,
412
- event,
413
- )
414
- if verbose:
415
- print(f"Closed and stored active event: {event_type}")
416
- except Exception as e:
417
- logging.error(f"Failed to store event {event_type}: {str(e)}")
418
- _local.active_events.clear()
419
-
420
- # NEW: Close all open asynchronous events
421
- active_events_async = active_events_var.get()
422
- if active_events_async:
423
- current_time = time.time()
424
- for event_type, event in list(active_events_async.items()):
425
- if event and event.closed is None:
426
- event.closed = current_time
427
- try:
428
- event_store.add_event(
429
- event.system_name,
430
- event.system_id,
431
- event.system_instance_id,
432
- event,
433
- )
434
- if verbose:
435
- print(f"Closed and stored async event: {event_type}")
436
- except Exception as e:
437
- logging.error(f"Failed to store async event {event_type}: {str(e)}")
438
- active_events_var.set({})
439
-
440
- # Also close any unclosed events in existing traces
441
376
  logged_traces = event_store.get_system_traces()
442
- traces = logged_traces + traces
443
- # traces = event_store.get_system_traces() if len(traces) == 0 else traces
444
- current_time = time.time()
445
- for trace in traces:
446
- for partition in trace.partition:
447
- for event in partition.events:
448
- if event.closed is None:
449
- event.closed = current_time
450
- event_store.add_event(
451
- trace.system_name,
452
- trace.system_id,
453
- trace.system_instance_id,
454
- event,
455
- )
456
- if verbose:
457
- print(f"Closed existing unclosed event: {event.event_type}")
458
-
459
- try:
460
- # Get traces and convert to dict format
461
- if len(traces) == 0:
462
- raise ValueError("No system traces found")
463
- traces_dict = [trace.to_dict() for trace in traces]
464
- dataset_dict = dataset.to_dict()
465
-
466
- # Validate upload format
467
- if verbose:
468
- print("Validating upload format...")
469
- validate_upload(traces_dict, dataset_dict)
470
- if verbose:
471
- print("Upload format validation successful")
472
-
473
- # Send to server
474
- upload_id, signed_url = send_system_traces_s3(
475
- dataset=dataset,
476
- traces=traces,
477
- base_url=base_url,
478
- api_key=api_key,
479
- system_id=traces[0].system_id,
480
- system_name=traces[0].system_name,
481
- verbose=verbose,
482
- )
483
-
484
- questions_json, reward_signals_json, traces_json = format_upload_output(dataset, traces)
485
- return (
486
- {
487
- "status": "success",
488
- "upload_id": upload_id,
489
- "signed_url": signed_url,
490
- },
491
- questions_json,
492
- reward_signals_json,
493
- traces_json,
494
- )
377
+ combined_traces: List[SystemTrace] = list(logged_traces) + list(traces)
378
+
379
+ if not combined_traces:
380
+ raise ValueError("No system traces found")
381
+
382
+ traces_dict = [trace.to_dict() for trace in combined_traces]
383
+ dataset_dict = dataset.to_dict()
384
+
385
+ if verbose:
386
+ print("Validating upload format...")
387
+ validate_upload(traces_dict, dataset_dict)
388
+
389
+ upload_id, signed_url = send_system_traces_s3(
390
+ dataset=dataset,
391
+ traces=combined_traces,
392
+ base_url=base_url,
393
+ api_key=api_key,
394
+ system_id=combined_traces[0].system_id,
395
+ system_name=combined_traces[0].system_name,
396
+ verbose=verbose,
397
+ )
495
398
 
496
- except ValueError as e:
497
- if verbose:
498
- print("Validation error:", str(e))
499
- print("\nTraces:")
500
- print(json.dumps(traces_dict, indent=2))
501
- print("\nDataset:")
502
- print(json.dumps(dataset_dict, indent=2))
503
- raise
504
- except requests.exceptions.HTTPError as e:
505
- if verbose:
506
- print("HTTP error occurred:", e)
507
- print("\nTraces:")
508
- print(json.dumps(traces_dict, indent=2))
509
- print("\nDataset:")
510
- print(json.dumps(dataset_dict, indent=2))
511
- raise
512
- """
399
+ questions_json, reward_signals_json, traces_json = format_upload_output(dataset, combined_traces)
400
+ return (
401
+ {
402
+ "status": "success",
403
+ "upload_id": upload_id,
404
+ "signed_url": signed_url,
405
+ },
406
+ questions_json,
407
+ reward_signals_json,
408
+ traces_json,
409
+ )
@@ -0,0 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ # Backward-compat shim for legacy imports: `synth_ai.v0.tracing_v3.*`
4
+ # Re-export from the canonical `synth_ai.tracing_v3` package.
5
+
6
+ from synth_ai.tracing_v3 import * # type: ignore[F401,F403]
7
+
8
+ __all__ = [] # names are provided by the upstream module
9
+
10
+
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ from synth_ai.tracing_v3.abstractions import * # type: ignore[F401,F403]
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ from synth_ai.tracing_v3.decorators import * # type: ignore[F401,F403]
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ from synth_ai.tracing_v3.llm_call_record_helpers import * # type: ignore[F401,F403]
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ from synth_ai.tracing_v3.session_tracer import * # type: ignore[F401,F403]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synth-ai
3
- Version: 0.2.9.dev5
3
+ Version: 0.2.10
4
4
  Summary: RL as a service SDK - Core AI functionality and tracing
5
5
  Author-email: Synth AI <josh@usesynth.ai>
6
6
  License-Expression: MIT
@@ -45,19 +45,21 @@ Requires-Dist: pynacl>=1.5.0
45
45
  Requires-Dist: google-api-core>=2.25.1
46
46
  Requires-Dist: google-generativeai>=0.8.5
47
47
  Requires-Dist: crafter>=1.8.3
48
- Requires-Dist: click>=8.1.0
48
+ Requires-Dist: click<8.2,>=8.1.7
49
49
  Requires-Dist: textual>=1.1.0
50
50
  Requires-Dist: openai-harmony>=0.0.1
51
51
  Requires-Dist: asyncpg>=0.30.0
52
52
  Requires-Dist: aiohttp>=3.8.0
53
53
  Requires-Dist: datasets>=4.0.0
54
54
  Requires-Dist: transformers>=4.56.1
55
- Requires-Dist: modal>=1.1.0
55
+ Requires-Dist: modal==1.1.4
56
56
  Provides-Extra: dev
57
57
  Requires-Dist: build>=1.2.2.post1; extra == "dev"
58
58
  Requires-Dist: twine>=4.0.0; extra == "dev"
59
59
  Requires-Dist: keyring>=24.0.0; extra == "dev"
60
60
  Requires-Dist: pytest>=8.3.3; extra == "dev"
61
+ Requires-Dist: pytest-xdist>=3.6.1; extra == "dev"
62
+ Requires-Dist: pytest-timeout>=2.3.1; extra == "dev"
61
63
  Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
62
64
  Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
63
65
  Requires-Dist: pyright>=1.1.350; extra == "dev"
@@ -78,10 +80,11 @@ Dynamic: license-file
78
80
  [![Python](https://img.shields.io/badge/python-3.11+-blue)](https://www.python.org/)
79
81
  [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
80
82
  [![PyPI](https://img.shields.io/badge/PyPI-0.2.4.dev9-orange)](https://pypi.org/project/synth-ai/)
81
- ![Coverage](https://img.shields.io/badge/coverage-0.0%25-red)
82
- ![Tests](https://img.shields.io/badge/tests-17%2F17%20passing-brightgreen)
83
+ ![Coverage](https://img.shields.io/badge/coverage-9.09%25-red)
84
+ ![Tests](https://img.shields.io/badge/tests-37%2F38%20passing-brightgreen)
85
+ ![Blacksmith CI](https://img.shields.io/badge/CI-Blacksmith%20Worker-blue)
83
86
 
84
- Docs: [Synth‑AI Documentation](https://docs.usesynth.ai/synth-ai/introduction)
87
+ Docs: [Synth‑AI Documentation](https://docs.usesynth.ai/welcome/introduction)
85
88
 
86
89
  Fast and effective reinforcement learning for agents, via an API
87
90
 
@@ -105,7 +108,7 @@ uvx synth-ai deploy
105
108
  uvx synth-ai run
106
109
  ```
107
110
 
108
- To walk through kicking off your first RL run, see the [Synth‑AI Documentation](https://docs.usesynth.ai/synth-ai/introduction).
111
+ To walk through kicking off your first RL run, see the [Synth‑AI Documentation](https://docs.usesynth.ai/welcome/introduction).
109
112
 
110
113
  ### What `setup` does now
111
114