gatewaysdk 0.3.2__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.
Files changed (376) hide show
  1. gatewaysdk/__init__.py +540 -0
  2. gatewaysdk/adapter/__init__.py +15 -0
  3. gatewaysdk/adapter/base.py +94 -0
  4. gatewaysdk/adapter/messages.py +270 -0
  5. gatewaysdk/adapter/triplet.py +1026 -0
  6. gatewaysdk/algorithm/__init__.py +39 -0
  7. gatewaysdk/algorithm/apo/__init__.py +5 -0
  8. gatewaysdk/algorithm/apo/apo.py +898 -0
  9. gatewaysdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
  10. gatewaysdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
  11. gatewaysdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
  12. gatewaysdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
  13. gatewaysdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
  14. gatewaysdk/algorithm/base.py +262 -0
  15. gatewaysdk/algorithm/decorator.py +264 -0
  16. gatewaysdk/algorithm/evals/__init__.py +7 -0
  17. gatewaysdk/algorithm/evals/evals.py +217 -0
  18. gatewaysdk/algorithm/fast.py +250 -0
  19. gatewaysdk/algorithm/gepa/__init__.py +61 -0
  20. gatewaysdk/algorithm/gepa/adapter.py +495 -0
  21. gatewaysdk/algorithm/gepa/gepa.py +570 -0
  22. gatewaysdk/algorithm/gepa/lib/__init__.py +18 -0
  23. gatewaysdk/algorithm/gepa/lib/adapters/README.md +12 -0
  24. gatewaysdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
  25. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
  26. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
  27. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
  28. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
  29. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
  30. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
  31. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
  32. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
  33. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
  34. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
  35. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
  36. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
  37. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +268 -0
  38. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
  39. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
  40. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
  41. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
  42. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
  43. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
  44. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
  45. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
  46. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
  47. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
  48. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
  49. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
  50. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
  51. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
  52. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +699 -0
  53. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
  54. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
  55. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
  56. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
  57. gatewaysdk/algorithm/gepa/lib/api.py +382 -0
  58. gatewaysdk/algorithm/gepa/lib/core/__init__.py +0 -0
  59. gatewaysdk/algorithm/gepa/lib/core/adapter.py +180 -0
  60. gatewaysdk/algorithm/gepa/lib/core/data_loader.py +74 -0
  61. gatewaysdk/algorithm/gepa/lib/core/engine.py +379 -0
  62. gatewaysdk/algorithm/gepa/lib/core/result.py +233 -0
  63. gatewaysdk/algorithm/gepa/lib/core/state.py +636 -0
  64. gatewaysdk/algorithm/gepa/lib/examples/__init__.py +0 -0
  65. gatewaysdk/algorithm/gepa/lib/examples/aime.py +24 -0
  66. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
  67. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
  68. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
  69. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
  70. gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
  71. gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
  72. gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
  73. gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +456 -0
  74. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
  75. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
  76. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +820 -0
  77. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
  78. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
  79. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
  80. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
  81. gatewaysdk/algorithm/gepa/lib/gepa_utils.py +117 -0
  82. gatewaysdk/algorithm/gepa/lib/logging/__init__.py +0 -0
  83. gatewaysdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
  84. gatewaysdk/algorithm/gepa/lib/logging/logger.py +75 -0
  85. gatewaysdk/algorithm/gepa/lib/logging/utils.py +103 -0
  86. gatewaysdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
  87. gatewaysdk/algorithm/gepa/lib/proposer/base.py +31 -0
  88. gatewaysdk/algorithm/gepa/lib/proposer/merge.py +357 -0
  89. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
  90. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
  91. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
  92. gatewaysdk/algorithm/gepa/lib/py.typed +0 -0
  93. gatewaysdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
  94. gatewaysdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
  95. gatewaysdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
  96. gatewaysdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
  97. gatewaysdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
  98. gatewaysdk/algorithm/gepa/lib/strategies/instruction_proposal.py +126 -0
  99. gatewaysdk/algorithm/gepa/lib/utils/__init__.py +10 -0
  100. gatewaysdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
  101. gatewaysdk/algorithm/gepa/tracing.py +105 -0
  102. gatewaysdk/algorithm/utils.py +177 -0
  103. gatewaysdk/algorithm/verl/__init__.py +5 -0
  104. gatewaysdk/algorithm/verl/interface.py +202 -0
  105. gatewaysdk/automations.py +111 -0
  106. gatewaysdk/benchmark_hub/README.md +88 -0
  107. gatewaysdk/benchmark_hub/__init__.py +119 -0
  108. gatewaysdk/benchmark_hub/_archive.py +189 -0
  109. gatewaysdk/benchmark_hub/_tar.py +6 -0
  110. gatewaysdk/benchmark_hub/client.py +992 -0
  111. gatewaysdk/benchmark_hub/dispatch_shard.py +34 -0
  112. gatewaysdk/benchmark_hub/eval_config.py +20 -0
  113. gatewaysdk/benchmark_hub/evals.py +351 -0
  114. gatewaysdk/benchmark_hub/harbor_adapter.py +673 -0
  115. gatewaysdk/benchmark_hub/path_utils.py +81 -0
  116. gatewaysdk/benchmark_hub/save_utils.py +101 -0
  117. gatewaysdk/benchmark_hub/verifiers_adapter.py +327 -0
  118. gatewaysdk/benchmark_hub/versioning.py +72 -0
  119. gatewaysdk/build.py +515 -0
  120. gatewaysdk/cli/__init__.py +58 -0
  121. gatewaysdk/cli/agent_runner.py +132 -0
  122. gatewaysdk/cli/http_client.py +115 -0
  123. gatewaysdk/cli/platform.py +4086 -0
  124. gatewaysdk/cli/prometheus.py +115 -0
  125. gatewaysdk/cli/release_gate.py +215 -0
  126. gatewaysdk/cli/store.py +131 -0
  127. gatewaysdk/cli/vllm.py +29 -0
  128. gatewaysdk/client.py +406 -0
  129. gatewaysdk/config.py +348 -0
  130. gatewaysdk/connectors/__init__.py +25 -0
  131. gatewaysdk/connectors/client.py +203 -0
  132. gatewaysdk/connectors/skill.py +25 -0
  133. gatewaysdk/connectors/template.py +106 -0
  134. gatewaysdk/context.py +606 -0
  135. gatewaysdk/emitter/__init__.py +43 -0
  136. gatewaysdk/emitter/annotation.py +370 -0
  137. gatewaysdk/emitter/exception.py +54 -0
  138. gatewaysdk/emitter/message.py +61 -0
  139. gatewaysdk/emitter/object.py +117 -0
  140. gatewaysdk/emitter/reward.py +320 -0
  141. gatewaysdk/env_var.py +156 -0
  142. gatewaysdk/environment/__init__.py +108 -0
  143. gatewaysdk/environment/_bundle.py +281 -0
  144. gatewaysdk/environment/_harbor.py +276 -0
  145. gatewaysdk/environment/_materialize.py +97 -0
  146. gatewaysdk/environment/_tar.py +33 -0
  147. gatewaysdk/environment/_world.py +346 -0
  148. gatewaysdk/environment/core.py +527 -0
  149. gatewaysdk/environment/errors.py +58 -0
  150. gatewaysdk/environment/runtime.py +150 -0
  151. gatewaysdk/environment/schema/__init__.py +35 -0
  152. gatewaysdk/environment/schema/__main__.py +225 -0
  153. gatewaysdk/environment/schema/_slack_fidelity.py +116 -0
  154. gatewaysdk/environment/schema/_slack_scenario.py +183 -0
  155. gatewaysdk/environment/schema/api.py +1628 -0
  156. gatewaysdk/environment/schema/batch.py +755 -0
  157. gatewaysdk/environment/schema/compiler.py +615 -0
  158. gatewaysdk/environment/schema/conform.py +428 -0
  159. gatewaysdk/environment/schema/connector.py +777 -0
  160. gatewaysdk/environment/schema/connectors/apple-business-manager/handlers.py +17 -0
  161. gatewaysdk/environment/schema/connectors/apple-business-manager/parity.json +28 -0
  162. gatewaysdk/environment/schema/connectors/apple-business-manager/provenance.json +233 -0
  163. gatewaysdk/environment/schema/connectors/apple-business-manager/scope.toml +112 -0
  164. gatewaysdk/environment/schema/connectors/apple-business-manager/world.json +1380 -0
  165. gatewaysdk/environment/schema/connectors/base.json +28 -0
  166. gatewaysdk/environment/schema/connectors/custom/handlers.py +18 -0
  167. gatewaysdk/environment/schema/connectors/custom/world.json +123 -0
  168. gatewaysdk/environment/schema/connectors/github/handlers.py +81 -0
  169. gatewaysdk/environment/schema/connectors/github/parity.json +37 -0
  170. gatewaysdk/environment/schema/connectors/github/provenance.json +134 -0
  171. gatewaysdk/environment/schema/connectors/github/scope.toml +158 -0
  172. gatewaysdk/environment/schema/connectors/github/world.json +5869 -0
  173. gatewaysdk/environment/schema/connectors/google-calendar/handlers.py +23 -0
  174. gatewaysdk/environment/schema/connectors/google-calendar/world.json +209 -0
  175. gatewaysdk/environment/schema/connectors/google-drive/handlers.py +18 -0
  176. gatewaysdk/environment/schema/connectors/google-drive/world.json +286 -0
  177. gatewaysdk/environment/schema/connectors/jamf/handlers.py +34 -0
  178. gatewaysdk/environment/schema/connectors/jamf/parity.json +49 -0
  179. gatewaysdk/environment/schema/connectors/jamf/provenance.json +181 -0
  180. gatewaysdk/environment/schema/connectors/jamf/scope.toml +128 -0
  181. gatewaysdk/environment/schema/connectors/jamf/world.json +2218 -0
  182. gatewaysdk/environment/schema/connectors/jira/handlers.py +28 -0
  183. gatewaysdk/environment/schema/connectors/jira/world.json +389 -0
  184. gatewaysdk/environment/schema/connectors/kandji/handlers.py +38 -0
  185. gatewaysdk/environment/schema/connectors/kandji/parity.json +29 -0
  186. gatewaysdk/environment/schema/connectors/kandji/provenance.json +152 -0
  187. gatewaysdk/environment/schema/connectors/kandji/scope.toml +120 -0
  188. gatewaysdk/environment/schema/connectors/kandji/world.json +765 -0
  189. gatewaysdk/environment/schema/connectors/linear/handlers.py +20 -0
  190. gatewaysdk/environment/schema/connectors/linear/world.json +363 -0
  191. gatewaysdk/environment/schema/connectors/microsoft-teams/fidelity.json +45 -0
  192. gatewaysdk/environment/schema/connectors/microsoft-teams/handlers.py +1 -0
  193. gatewaysdk/environment/schema/connectors/microsoft-teams/provenance.json +851 -0
  194. gatewaysdk/environment/schema/connectors/microsoft-teams/scope.md +231 -0
  195. gatewaysdk/environment/schema/connectors/microsoft-teams/teams-types.json +1710 -0
  196. gatewaysdk/environment/schema/connectors/microsoft-teams/world.json +858 -0
  197. gatewaysdk/environment/schema/connectors/netsuite/handlers.py +32 -0
  198. gatewaysdk/environment/schema/connectors/netsuite/parity.json +50 -0
  199. gatewaysdk/environment/schema/connectors/netsuite/provenance.json +137 -0
  200. gatewaysdk/environment/schema/connectors/netsuite/scope.toml +78 -0
  201. gatewaysdk/environment/schema/connectors/netsuite/world.json +16243 -0
  202. gatewaysdk/environment/schema/connectors/salesforce/handlers.py +806 -0
  203. gatewaysdk/environment/schema/connectors/salesforce/parity.json +46 -0
  204. gatewaysdk/environment/schema/connectors/salesforce/provenance.json +143 -0
  205. gatewaysdk/environment/schema/connectors/salesforce/scope.toml +174 -0
  206. gatewaysdk/environment/schema/connectors/salesforce/world.json +4695 -0
  207. gatewaysdk/environment/schema/connectors/slack/MODEL.md +236 -0
  208. gatewaysdk/environment/schema/connectors/slack/capabilities.json +1039 -0
  209. gatewaysdk/environment/schema/connectors/slack/handlers.py +762 -0
  210. gatewaysdk/environment/schema/connectors/slack/parity.json +65 -0
  211. gatewaysdk/environment/schema/connectors/slack/provenance.json +294 -0
  212. gatewaysdk/environment/schema/connectors/slack/scope.toml +44 -0
  213. gatewaysdk/environment/schema/connectors/slack/world.json +4993 -0
  214. gatewaysdk/environment/schema/connectors/workday/handlers.py +75 -0
  215. gatewaysdk/environment/schema/connectors/workday/parity.json +36 -0
  216. gatewaysdk/environment/schema/connectors/workday/provenance.json +179 -0
  217. gatewaysdk/environment/schema/connectors/workday/scope.toml +180 -0
  218. gatewaysdk/environment/schema/connectors/workday/world.json +806 -0
  219. gatewaysdk/environment/schema/data.py +593 -0
  220. gatewaysdk/environment/schema/extract.py +263 -0
  221. gatewaysdk/environment/schema/host.py +2437 -0
  222. gatewaysdk/environment/schema/host_surfaces.py +275 -0
  223. gatewaysdk/environment/schema/platform.py +1272 -0
  224. gatewaysdk/environment/schema/scaffold.py +250 -0
  225. gatewaysdk/environment/schema/skill.py +118 -0
  226. gatewaysdk/environment/schema/skills/agents/connector-template-author.md +202 -0
  227. gatewaysdk/environment/schema/skills/connector-schema-authoring/CONNECTORS.md +331 -0
  228. gatewaysdk/environment/schema/skills/connector-schema-authoring/CONVENTIONS.md +100 -0
  229. gatewaysdk/environment/schema/skills/connector-schema-authoring/SKILL.md +313 -0
  230. gatewaysdk/environment/schema/skills/world-data-ingestion/ROWS.md +223 -0
  231. gatewaysdk/environment/schema/skills/world-data-ingestion/SKILL.md +293 -0
  232. gatewaysdk/environment/schema/skills/worlds-getting-started/SKILL.md +390 -0
  233. gatewaysdk/environment/schema/slack.py +757 -0
  234. gatewaysdk/environment/schema/snapshot.py +479 -0
  235. gatewaysdk/environment/schema/store.py +904 -0
  236. gatewaysdk/environment/schema/tasks.py +525 -0
  237. gatewaysdk/environment/schema/tools_world.py +322 -0
  238. gatewaysdk/environment/schema/validation.py +577 -0
  239. gatewaysdk/environment/schema/worker.py +78 -0
  240. gatewaysdk/environment/schema/workers.py +500 -0
  241. gatewaysdk/environment/schema/world_tests.py +336 -0
  242. gatewaysdk/environments/__init__.py +24 -0
  243. gatewaysdk/environments/client.py +486 -0
  244. gatewaysdk/environments/types.py +318 -0
  245. gatewaysdk/execution/__init__.py +15 -0
  246. gatewaysdk/execution/base.py +64 -0
  247. gatewaysdk/execution/client_server.py +443 -0
  248. gatewaysdk/execution/events.py +69 -0
  249. gatewaysdk/execution/inter_process.py +16 -0
  250. gatewaysdk/execution/shared_memory.py +282 -0
  251. gatewaysdk/experiments/__init__.py +90 -0
  252. gatewaysdk/experiments/assignment.py +177 -0
  253. gatewaysdk/experiments/client.py +877 -0
  254. gatewaysdk/experiments/exposure.py +222 -0
  255. gatewaysdk/experiments/types.py +81 -0
  256. gatewaysdk/importers/__init__.py +49 -0
  257. gatewaysdk/importers/_normalize.py +91 -0
  258. gatewaysdk/importers/builder.py +173 -0
  259. gatewaysdk/importers/client.py +95 -0
  260. gatewaysdk/importers/langsmith.py +196 -0
  261. gatewaysdk/importers/recipes.py +249 -0
  262. gatewaysdk/instrumentation/__init__.py +300 -0
  263. gatewaysdk/instrumentation/agentops.py +314 -0
  264. gatewaysdk/instrumentation/agentops_langchain.py +45 -0
  265. gatewaysdk/instrumentation/base.py +119 -0
  266. gatewaysdk/instrumentation/litellm.py +83 -0
  267. gatewaysdk/instrumentation/registry.py +273 -0
  268. gatewaysdk/instrumentation/vllm.py +81 -0
  269. gatewaysdk/instrumentation/weave.py +500 -0
  270. gatewaysdk/integrations/__init__.py +15 -0
  271. gatewaysdk/integrations/gateway/__init__.py +11 -0
  272. gatewaysdk/integrations/gateway/client.py +171 -0
  273. gatewaysdk/integrations/tool_access.py +549 -0
  274. gatewaysdk/litagent/__init__.py +11 -0
  275. gatewaysdk/litagent/decorator.py +536 -0
  276. gatewaysdk/litagent/litagent.py +252 -0
  277. gatewaysdk/llm_proxy.py +1742 -0
  278. gatewaysdk/logging.py +370 -0
  279. gatewaysdk/memory.py +278 -0
  280. gatewaysdk/personas.py +186 -0
  281. gatewaysdk/platform/__init__.py +17 -0
  282. gatewaysdk/platform/builder.py +221 -0
  283. gatewaysdk/platform/compatibility.py +67 -0
  284. gatewaysdk/platform/manifest.py +185 -0
  285. gatewaysdk/platform/orchestrator.py +901 -0
  286. gatewaysdk/platform/registry.py +122 -0
  287. gatewaysdk/platform/worker.py +864 -0
  288. gatewaysdk/replay/__init__.py +1032 -0
  289. gatewaysdk/replay/pytest.py +56 -0
  290. gatewaysdk/reward.py +7 -0
  291. gatewaysdk/run.py +1781 -0
  292. gatewaysdk/runner/__init__.py +11 -0
  293. gatewaysdk/runner/agent.py +878 -0
  294. gatewaysdk/runner/base.py +182 -0
  295. gatewaysdk/runner/legacy.py +309 -0
  296. gatewaysdk/security.py +700 -0
  297. gatewaysdk/semconv.py +170 -0
  298. gatewaysdk/server.py +399 -0
  299. gatewaysdk/sessions.py +282 -0
  300. gatewaysdk/store/__init__.py +45 -0
  301. gatewaysdk/store/base.py +908 -0
  302. gatewaysdk/store/client_server.py +2093 -0
  303. gatewaysdk/store/collection/__init__.py +30 -0
  304. gatewaysdk/store/collection/base.py +587 -0
  305. gatewaysdk/store/collection/memory.py +970 -0
  306. gatewaysdk/store/collection/mongo.py +1412 -0
  307. gatewaysdk/store/collection_based.py +1823 -0
  308. gatewaysdk/store/gateway.py +983 -0
  309. gatewaysdk/store/gateway_listener.py +465 -0
  310. gatewaysdk/store/listener.py +58 -0
  311. gatewaysdk/store/memory.py +396 -0
  312. gatewaysdk/store/mongo.py +165 -0
  313. gatewaysdk/store/redis_stream.py +517 -0
  314. gatewaysdk/store/sqlite.py +3 -0
  315. gatewaysdk/store/threading.py +370 -0
  316. gatewaysdk/store/utils.py +142 -0
  317. gatewaysdk/tracer/__init__.py +14 -0
  318. gatewaysdk/tracer/base.py +286 -0
  319. gatewaysdk/tracer/dummy.py +106 -0
  320. gatewaysdk/tracer/otel.py +559 -0
  321. gatewaysdk/tracing/__init__.py +110 -0
  322. gatewaysdk/tracing/api.py +808 -0
  323. gatewaysdk/tracing/attributes.py +9 -0
  324. gatewaysdk/tracing/context.py +272 -0
  325. gatewaysdk/tracing/exporters/__init__.py +10 -0
  326. gatewaysdk/tracing/exporters/gateway.py +228 -0
  327. gatewaysdk/tracing/identity.py +288 -0
  328. gatewaysdk/tracing/init.py +620 -0
  329. gatewaysdk/tracing/instrumentors/__init__.py +15 -0
  330. gatewaysdk/tracing/instrumentors/claude_agent_sdk.py +766 -0
  331. gatewaysdk/tracing/instrumentors/instrumentation_principles.md +294 -0
  332. gatewaysdk/tracing/instrumentors/registry.py +352 -0
  333. gatewaysdk/tracing/mapping.py +729 -0
  334. gatewaysdk/tracing/processors.py +393 -0
  335. gatewaysdk/tracing/push.py +617 -0
  336. gatewaysdk/tracing/push_models.py +247 -0
  337. gatewaysdk/tracing/semconv.py +294 -0
  338. gatewaysdk/tracing/span_builder.py +356 -0
  339. gatewaysdk/trainer/__init__.py +6 -0
  340. gatewaysdk/trainer/init_utils.py +263 -0
  341. gatewaysdk/trainer/legacy.py +359 -0
  342. gatewaysdk/trainer/registry.py +12 -0
  343. gatewaysdk/trainer/trainer.py +638 -0
  344. gatewaysdk/types/__init__.py +63 -0
  345. gatewaysdk/types/core.py +556 -0
  346. gatewaysdk/types/resources.py +204 -0
  347. gatewaysdk/types/tracer.py +515 -0
  348. gatewaysdk/types/tracing.py +162 -0
  349. gatewaysdk/users.py +251 -0
  350. gatewaysdk/utils/__init__.py +1 -0
  351. gatewaysdk/utils/id.py +18 -0
  352. gatewaysdk/utils/metrics.py +1025 -0
  353. gatewaysdk/utils/otel.py +550 -0
  354. gatewaysdk/utils/otlp.py +556 -0
  355. gatewaysdk/utils/redact.py +22 -0
  356. gatewaysdk/utils/server_launcher.py +1045 -0
  357. gatewaysdk/utils/system_snapshot.py +90 -0
  358. gatewaysdk/verl/__init__.py +8 -0
  359. gatewaysdk/verl/__main__.py +6 -0
  360. gatewaysdk/verl/async_server.py +46 -0
  361. gatewaysdk/verl/config.yaml +27 -0
  362. gatewaysdk/verl/daemon.py +1154 -0
  363. gatewaysdk/verl/dataset.py +44 -0
  364. gatewaysdk/verl/entrypoint.py +248 -0
  365. gatewaysdk/verl/trainer.py +549 -0
  366. gatewaysdk/world_browser.py +748 -0
  367. gatewaysdk/world_data.py +453 -0
  368. gatewaysdk/world_sessions.py +978 -0
  369. gatewaysdk/world_tasks.py +285 -0
  370. gatewaysdk/world_tools.py +115 -0
  371. gatewaysdk/worlds.py +639 -0
  372. gatewaysdk-0.3.2.dist-info/METADATA +236 -0
  373. gatewaysdk-0.3.2.dist-info/RECORD +376 -0
  374. gatewaysdk-0.3.2.dist-info/WHEEL +4 -0
  375. gatewaysdk-0.3.2.dist-info/entry_points.txt +5 -0
  376. gatewaysdk-0.3.2.dist-info/licenses/LICENSE +19 -0
@@ -0,0 +1,570 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import logging
7
+ from typing import Any, ClassVar, Dict, Generic, List, Optional, TypeVar
8
+
9
+ import openai
10
+
11
+ from gatewaysdk.adapter import TraceAdapter
12
+ from gatewaysdk.adapter.messages import TraceToMessages
13
+ from gatewaysdk.algorithm.base import Algorithm
14
+ from gatewaysdk.algorithm.gepa.adapter import (
15
+ GatewayDataInst,
16
+ GatewayGEPAAdapter,
17
+ )
18
+ from gatewaysdk.algorithm.gepa.lib.api import optimize
19
+ from gatewaysdk.algorithm.gepa.tracing import GEPATracingContext
20
+ from gatewaysdk.algorithm.utils import with_llm_proxy, with_store
21
+ from gatewaysdk.types import Dataset, PromptTemplate, TracingConfig
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+ T_task = TypeVar("T_task")
26
+
27
+
28
+ TEMPLATE_AWARE_REFLECTION_PROMPT = """You are an expert at improving LLM prompts based on observed failures.
29
+
30
+ ## Current Prompt Template
31
+ ```
32
+ <curr_instructions>
33
+ ```
34
+
35
+ ## Observed Failures
36
+ The following examples show where the current prompt gave INCORRECT outputs. Study the pattern of failures carefully:
37
+ ```
38
+ <inputs_outputs_feedback>
39
+ ```
40
+
41
+ ## Your Task
42
+ Write an IMPROVED prompt template that fixes the observed failures.
43
+
44
+ **CRITICAL REQUIREMENTS**:
45
+ 1. **Analyze the failure pattern**: Look at WHAT the prompt got wrong. Is it too strict? Too lenient? Missing context? Misunderstanding the task?
46
+ 2. **Make a CONCEPTUAL FIX**: Don't just tweak wording - fundamentally change the approach if the current strategy is flawed
47
+ 3. **Preserve placeholders**: Keep any {variable_name} placeholders exactly as they appear (e.g., {session}, {input}, {output}, or {{session}}, {{input}}, {{output}})
48
+ 4. **Be specific**: Add concrete criteria, examples, or decision rules based on what the failures reveal
49
+ 5. Read the inputs carefully and identify the input format and infer detailed task description about the task I wish to solve with the assistant
50
+ 6. Read all the assistant responses and the corresponding feedback. Identify all niche and domain specific factual information about the task and include it in the instruction, as a lot of it may not be available to the assistant in the future. The assistant may have utilized a generalizable strategy to solve the task, if so, include that in the instruction as well.
51
+
52
+ **Think step by step**:
53
+ - What is the PATTERN in the failures?
54
+ - WHY is the current prompt failing on these cases?
55
+ - What SPECIFIC change would fix this pattern?
56
+
57
+ Output your improved template within ``` blocks."""
58
+
59
+
60
+ class GEPA(Algorithm, Generic[T_task]):
61
+ """GEPA (Genetic-Pareto) algorithm for GatewaySDK.
62
+
63
+ This algorithm optimizes prompt templates (and potentially other text resources)
64
+ using an evolutionary approach with LLM-based reflection.
65
+
66
+ GEPA maintains a population of candidate prompts and evolves them by:
67
+ 1. Evaluating candidates on training data
68
+ 2. Using an LLM to reflect on failures and propose improvements
69
+ 3. Selecting the best candidates based on validation performance
70
+ """
71
+
72
+ # Platform metadata
73
+ name: ClassVar[str] = "gepa"
74
+ display_name: ClassVar[str] = "GEPA"
75
+ description: ClassVar[str] = "Genetic-Pareto Prompt Adaptation"
76
+ requirements: ClassVar[Dict[str, Any]] = {"gpu": False, "min_runners": 1}
77
+ config_schema: ClassVar[Optional[Dict[str, Any]]] = {
78
+ "type": "object",
79
+ "properties": {
80
+ "reflection_model": {
81
+ "type": "string",
82
+ "default": "anthropic/claude-haiku-4-5",
83
+ "description": "LLM model used by the algorithm to analyze agent failures and generate improved prompts. Accepts any LiteLLM model string.",
84
+ },
85
+ "max_metric_calls": {
86
+ "type": "integer",
87
+ "default": 1000,
88
+ "minimum": 1,
89
+ "description": "Maximum number of evaluations (budget)",
90
+ },
91
+ "population_size": {
92
+ "type": "integer",
93
+ "default": 5,
94
+ "minimum": 1,
95
+ "maximum": 50,
96
+ "description": "Size of the population in evolutionary search",
97
+ },
98
+ "reflection_minibatch_size": {
99
+ "type": "integer",
100
+ "default": 3,
101
+ "minimum": 1,
102
+ "description": "Number of examples per reflection batch",
103
+ },
104
+ "rollout_batch_timeout": {
105
+ "type": "number",
106
+ "default": 300.0,
107
+ "minimum": 30.0,
108
+ "description": "Timeout in seconds for waiting for rollout results",
109
+ },
110
+ "candidate_selection_strategy": {
111
+ "type": "string",
112
+ "default": "pareto",
113
+ "enum": ["pareto", "current_best", "epsilon_greedy"],
114
+ "description": "Strategy for selecting the next candidate to optimize",
115
+ },
116
+ "perfect_score": {
117
+ "type": "number",
118
+ "default": 1.0,
119
+ "description": "Score at which an example is considered perfectly solved",
120
+ },
121
+ "seed": {
122
+ "type": "integer",
123
+ "default": 0,
124
+ "description": "Random seed for reproducibility",
125
+ },
126
+ "initial_prompt": {
127
+ "type": "string",
128
+ "description": "Initial system prompt template to optimize (uses {input} placeholder)",
129
+ },
130
+ "val_fraction": {
131
+ "type": "number",
132
+ "default": 0.2,
133
+ "minimum": 0.0,
134
+ "maximum": 0.5,
135
+ "description": "Fraction of dataset held out for validation",
136
+ },
137
+ },
138
+ }
139
+
140
+ # Algorithm-owned tracing configuration
141
+ TRACING_CONFIG = TracingConfig(
142
+ environment="gatewaysdk-gepa",
143
+ algorithm_name="gepa",
144
+ )
145
+
146
+ def _get_tracing_config_with_session(self, session_id: str) -> TracingConfig:
147
+ """Create a TracingConfig with a specific session_id for this run."""
148
+ return TracingConfig(
149
+ environment="gatewaysdk-gepa",
150
+ algorithm_name="gepa",
151
+ session_id=session_id,
152
+ )
153
+
154
+ def __init__(
155
+ self,
156
+ *,
157
+ max_metric_calls: int = 100,
158
+ reflection_minibatch_size: int = 5,
159
+ population_size: int = 4,
160
+ adapter: Optional[TraceAdapter] = None,
161
+ rollout_batch_timeout: float = 600.0,
162
+ reflection_model: str = "anthropic/claude-haiku-4-5",
163
+ reflection_prompt_template: Optional[str] = None,
164
+ reflection_metadata: Optional[Dict[str, Any]] = None,
165
+ target_model_config: Optional[Dict[str, Any]] = None,
166
+ **gepa_kwargs: Any,
167
+ ) -> None:
168
+ """Initialize the GEPA algorithm.
169
+
170
+ Args:
171
+ max_metric_calls: Maximum number of evaluations (budget).
172
+ reflection_minibatch_size: Batch size for reflection.
173
+ population_size: Size of the population in evolutionary search.
174
+ adapter: TraceAdapter to convert spans to messages. Defaults to TraceToMessages.
175
+ rollout_batch_timeout: Timeout for waiting for rollouts.
176
+ reflection_model: LiteLLM model string for the reflection LLM.
177
+ reflection_prompt_template: Custom prompt template for reflection.
178
+ reflection_metadata: Metadata for reflection LLM traces (Langfuse).
179
+ target_model_config: Direct model configuration (apiKey, baseUrl) to bypass proxy if needed.
180
+ **gepa_kwargs: Additional arguments passed to gepa.optimize.
181
+ """
182
+ super().__init__()
183
+ self.max_metric_calls = max_metric_calls
184
+ self.reflection_minibatch_size = reflection_minibatch_size
185
+ self.population_size = population_size
186
+ self.adapter = adapter or TraceToMessages()
187
+ self.rollout_batch_timeout = rollout_batch_timeout
188
+ self.reflection_model = reflection_model
189
+ self.reflection_metadata = reflection_metadata
190
+ self.target_model_config = target_model_config
191
+
192
+ # Set default reflection prompt template if not provided
193
+ if reflection_prompt_template is not None:
194
+ gepa_kwargs["reflection_prompt_template"] = reflection_prompt_template
195
+ elif "reflection_prompt_template" not in gepa_kwargs:
196
+ gepa_kwargs["reflection_prompt_template"] = TEMPLATE_AWARE_REFLECTION_PROMPT
197
+
198
+ self.gepa_kwargs = gepa_kwargs
199
+ self._best_candidate: Optional[Dict[str, str]] = None
200
+ self._best_score: float = 0.0
201
+ self._full_result: Optional[Any] = None # Store full GEPAResult for history access
202
+ self._engine: Optional[Any] = None # GEPAEngine reference for cancellation
203
+
204
+ def request_cancel(self) -> None:
205
+ """Signal GEPA to stop at the next iteration boundary."""
206
+ super().request_cancel()
207
+ if self._engine is not None:
208
+ self._engine.request_stop()
209
+ logger.info("GEPA engine stop requested via cancellation")
210
+
211
+ def get_best_prompt(self) -> Optional[PromptTemplate]:
212
+ """Get the best prompt found during optimization."""
213
+ if self._best_candidate:
214
+ # Return the first PromptTemplate value
215
+ for key, value in self._best_candidate.items():
216
+ return PromptTemplate(template=value, engine="f-string")
217
+ return None
218
+
219
+ @with_store
220
+ @with_llm_proxy(required=False)
221
+ async def run(
222
+ self,
223
+ llm_proxy, # injected by decorator (may be None)
224
+ store, # injected by decorator
225
+ train_dataset: Optional[Dataset[T_task]] = None,
226
+ val_dataset: Optional[Dataset[T_task]] = None,
227
+ ) -> None:
228
+ """Run the GEPA optimization loop.
229
+
230
+ Args:
231
+ train_dataset: Dataset used for optimization (training).
232
+ val_dataset: Dataset used for validation.
233
+ """
234
+ if train_dataset is None:
235
+ raise ValueError("train_dataset is required for GEPA optimization.")
236
+
237
+ store = self.get_store()
238
+ assert store is not None
239
+
240
+ loop = asyncio.get_running_loop()
241
+
242
+ # Get initial resources to find the target resource to optimize
243
+ initial_resources = self.get_initial_resources()
244
+ if not initial_resources:
245
+ raise ValueError("Initial resources must be set before running GEPA.")
246
+
247
+ # Find the target resource to optimize
248
+ target_resource_name = None
249
+ initial_candidate: Dict[str, str] = {}
250
+
251
+ for name, res in initial_resources.items():
252
+ if isinstance(res, PromptTemplate):
253
+ target_resource_name = name
254
+ initial_candidate[name] = res.template
255
+
256
+ if not target_resource_name:
257
+ raise ValueError("No PromptTemplate found in initial resources to optimize.")
258
+
259
+ logger.info(f"GEPA will optimize resource: {target_resource_name}")
260
+ logger.info(f"Initial prompt: {initial_candidate[target_resource_name][:100]}...")
261
+
262
+ # Setup Reflection LLM -- via proxy if available, otherwise direct
263
+ llm_resource = llm_proxy.as_resource() if llm_proxy is not None else None
264
+ reflection_model = self.reflection_model
265
+
266
+ if llm_resource is not None:
267
+ logger.info(f"GEPA reflection via LLM proxy: {llm_resource.model}")
268
+ else:
269
+ logger.info(f"GEPA reflection via direct litellm: {reflection_model}")
270
+
271
+ # Create tracing context for detailed execution tracking
272
+ # This generates a unique session_id for grouping all traces in this run
273
+ tracing_context = GEPATracingContext()
274
+
275
+ # Create a TracingConfig with this run's session_id
276
+ run_tracing_config = self._get_tracing_config_with_session(tracing_context.session_id)
277
+
278
+ logger.info(f"GEPA session started: {tracing_context.session_id}")
279
+
280
+ # Create the bridge adapter with tracing config and context
281
+ gepa_adapter = GatewayGEPAAdapter(
282
+ store=store,
283
+ loop=loop,
284
+ resource_name=target_resource_name,
285
+ adapter=self.adapter,
286
+ llm_proxy_resource=llm_resource,
287
+ rollout_batch_timeout=self.rollout_batch_timeout,
288
+ tracing_config=run_tracing_config,
289
+ tracing_context=tracing_context,
290
+ )
291
+
292
+ # Import here (inside run) to avoid circular imports:
293
+ # `gatewaysdk.algorithm.gepa.__init__` re-exports `GEPA` from this module.
294
+ from gatewaysdk.algorithm import gepa as gepa_module
295
+
296
+ reflection_failures = 0
297
+
298
+ @gepa_module.reflection
299
+ def reflection_lm(prompt: str) -> str:
300
+ """GEPA reflection LM callable -- string in, string out.
301
+
302
+ Two modes:
303
+ - With LLM proxy: routes through the proxy for centralized
304
+ key management and tracing.
305
+ - Without proxy: calls litellm directly using API keys from
306
+ the environment. Tracing still works via tracing.init().
307
+ """
308
+ import litellm
309
+
310
+ tracing_context.set_phase("reflection")
311
+
312
+ model_name = llm_resource.model if llm_resource else reflection_model
313
+ logger.info(f"[reflection_lm] === REFLECTION (gen-{tracing_context.generation}) ===")
314
+ logger.info(f"[reflection_lm] Model: {model_name}, prompt: {len(prompt)} chars")
315
+
316
+ try:
317
+ from gatewaysdk.tracing.context import tracing_context as _tracing_ctx
318
+
319
+ gepa_tags = run_tracing_config.get_detailed_tags(
320
+ phase="reflection",
321
+ extra_tags=[f"gen-{tracing_context.generation}"],
322
+ )
323
+ reflection_session = f"{tracing_context.session_id}-reflection-gen{tracing_context.generation}"
324
+
325
+ with _tracing_ctx(
326
+ tags=gepa_tags, environment=run_tracing_config.environment, session_id=reflection_session
327
+ ):
328
+ if llm_resource is not None:
329
+ # Route through LLM proxy
330
+ proxy_endpoint = llm_resource.get_base_url(None, None)
331
+ response = litellm.completion(
332
+ model=llm_resource.model,
333
+ messages=[{"role": "user", "content": prompt}],
334
+ api_base=proxy_endpoint,
335
+ api_key="dummy",
336
+ temperature=0.7,
337
+ extra_headers={"x-gateway-session-id": reflection_session},
338
+ )
339
+ else:
340
+ # Direct litellm call -- API key from environment
341
+ response = litellm.completion(
342
+ model=reflection_model,
343
+ messages=[{"role": "user", "content": prompt}],
344
+ temperature=0.7,
345
+ )
346
+
347
+ content = response.choices[0].message.content or ""
348
+ logger.info(f"[reflection_lm] SUCCESS - {len(content)} chars")
349
+
350
+ tracing_context.next_generation()
351
+ tracing_context.set_phase("train-eval")
352
+ return content
353
+
354
+ except Exception as e:
355
+ nonlocal reflection_failures
356
+ reflection_failures += 1
357
+ logger.error(f"[reflection_lm] FAILED ({reflection_failures} total): {e}", exc_info=True)
358
+ if reflection_failures > 3:
359
+ raise RuntimeError(
360
+ f"GEPA reflection failed {reflection_failures} times consecutively. "
361
+ "Check LLM endpoint configuration."
362
+ ) from e
363
+ logger.warning(f"[reflection_lm] Returning fallback (seed prompt)")
364
+ tracing_context.next_generation()
365
+ tracing_context.set_phase("train-eval")
366
+ return f"```\n{initial_candidate.get(target_resource_name, '')}\n```"
367
+
368
+ # Prepare Training Data
369
+ gepa_train_data: List[GatewayDataInst] = []
370
+ for i, item in enumerate(train_dataset):
371
+ item_id = str(i)
372
+ if isinstance(item, dict):
373
+ gepa_train_data.append({"input": item, "id": item.get("id", item_id)})
374
+ else:
375
+ gepa_train_data.append({"input": {"task": item}, "id": item_id})
376
+
377
+ # Prepare Validation Data (use train if not provided)
378
+ gepa_val_data: Optional[List[GatewayDataInst]] = None
379
+ if val_dataset is not None:
380
+ gepa_val_data = []
381
+ for i, item in enumerate(val_dataset):
382
+ item_id = f"val-{i}"
383
+ if isinstance(item, dict):
384
+ gepa_val_data.append({"input": item, "id": item.get("id", item_id)})
385
+ else:
386
+ gepa_val_data.append({"input": {"task": item}, "id": item_id})
387
+
388
+ logger.info(f"Starting GEPA optimization with {len(gepa_train_data)} training samples")
389
+ if gepa_val_data:
390
+ logger.info(f"Using {len(gepa_val_data)} validation samples")
391
+
392
+ # Create live state callback for real-time visualization
393
+ def on_step_callback(state) -> None:
394
+ """Update live state for real-time visualization after each GEPA iteration."""
395
+ logger.info(f"[on_step_callback] Called for iteration {state.i}")
396
+
397
+ if not hasattr(store, "log_state"):
398
+ logger.info(f"[on_step_callback] store has no log_state method")
399
+ return
400
+
401
+ logger.info(f"[on_step_callback] calling store.log_state")
402
+
403
+ try:
404
+ # Build candidates list with full data
405
+ candidates = []
406
+ for idx, cand in enumerate(state.program_candidates):
407
+ # Get prompt text from candidate dict
408
+ prompt_text = ""
409
+ prompt_key = ""
410
+ if cand:
411
+ first_key = next(iter(cand.keys()), None)
412
+ if first_key:
413
+ prompt_key = first_key
414
+ prompt_text = cand.get(first_key, "")
415
+
416
+ # Get score from prog_candidate_val_subscores (dict of val_id -> score)
417
+ val_scores = (
418
+ state.prog_candidate_val_subscores[idx] if idx < len(state.prog_candidate_val_subscores) else {}
419
+ )
420
+ score = sum(val_scores.values()) / len(val_scores) if val_scores else None
421
+
422
+ # Get parent indices from parent_program_for_candidate
423
+ parent_list = (
424
+ state.parent_program_for_candidate[idx] if idx < len(state.parent_program_for_candidate) else []
425
+ )
426
+ parent_idx = parent_list[0] if parent_list and parent_list[0] is not None else None
427
+
428
+ candidates.append(
429
+ {
430
+ "idx": idx,
431
+ "prompt": prompt_text[:2000], # Truncate for sanity
432
+ "promptKey": prompt_key,
433
+ "score": score,
434
+ "parent": parent_idx,
435
+ }
436
+ )
437
+
438
+ # Build pareto front from program_at_pareto_front_valset
439
+ pareto_front = {}
440
+ if hasattr(state, "program_at_pareto_front_valset"):
441
+ for instance_id, best_idxs in state.program_at_pareto_front_valset.items():
442
+ pareto_front[str(instance_id)] = list(best_idxs) if best_idxs else []
443
+
444
+ # Find best candidate by computing average validation score
445
+ best_idx = 0
446
+ best_score = 0.0
447
+ for idx, val_scores in enumerate(state.prog_candidate_val_subscores):
448
+ if val_scores:
449
+ avg = sum(val_scores.values()) / len(val_scores)
450
+ if avg > best_score:
451
+ best_score = avg
452
+ best_idx = idx
453
+
454
+ # Log the live state via public API (F14)
455
+ store.log_state(
456
+ {
457
+ "candidates": candidates,
458
+ "pareto_front": pareto_front,
459
+ "best_idx": best_idx,
460
+ "best_score": best_score,
461
+ "generation": tracing_context.generation,
462
+ "total_metric_calls": state.total_num_evals,
463
+ "iteration": state.i,
464
+ }
465
+ )
466
+
467
+ logger.info(
468
+ f"[on_step_callback] Updated live state: {len(candidates)} candidates, best={best_score:.3f}"
469
+ )
470
+
471
+ # Log per-step metrics for the Metrics tab time series
472
+ if hasattr(store, "_run") and store._run:
473
+ try:
474
+ store._run.log(
475
+ {
476
+ "best_score": best_score,
477
+ "num_candidates": len(candidates),
478
+ "metric_calls": state.total_num_evals,
479
+ },
480
+ step=max(0, state.i),
481
+ )
482
+ except Exception:
483
+ pass # Metrics are best-effort; Evolution tab is primary
484
+ except Exception as e:
485
+ logger.warning(f"[on_step_callback] Failed to update live state: {e}")
486
+
487
+ # Create a cancellation stopper that checks Algorithm._cancel_event
488
+ cancel_event = self._cancel_event
489
+
490
+ class _CancelStopper:
491
+ """Bridges Algorithm.request_cancel() → GEPA engine stop."""
492
+
493
+ def __call__(self, gepa_state: Any) -> bool:
494
+ return cancel_event.is_set()
495
+
496
+ # Merge with any existing stop_callbacks from gepa_kwargs
497
+ extra_kwargs = dict(self.gepa_kwargs)
498
+ existing_stop_cbs = extra_kwargs.pop("stop_callbacks", None)
499
+ stop_cbs: list = []
500
+ if existing_stop_cbs is not None:
501
+ if isinstance(existing_stop_cbs, (list, tuple)):
502
+ stop_cbs.extend(existing_stop_cbs)
503
+ else:
504
+ stop_cbs.append(existing_stop_cbs)
505
+ stop_cbs.append(_CancelStopper())
506
+
507
+ # Run Optimization in Executor (GEPA is synchronous)
508
+ def run_optimization():
509
+ return optimize(
510
+ trainset=gepa_train_data,
511
+ valset=gepa_val_data,
512
+ adapter=gepa_adapter,
513
+ seed_candidate=initial_candidate,
514
+ reflection_lm=reflection_lm,
515
+ max_metric_calls=self.max_metric_calls,
516
+ reflection_minibatch_size=self.reflection_minibatch_size,
517
+ on_step_callback=on_step_callback,
518
+ stop_callbacks=stop_cbs,
519
+ **extra_kwargs,
520
+ )
521
+
522
+ try:
523
+ result = await loop.run_in_executor(None, run_optimization)
524
+
525
+ logger.info(f"GEPA optimization finished. Total metric calls: {result.total_metric_calls}")
526
+ logger.info(
527
+ f"Best candidate index: {result.best_idx}, score: {result.val_aggregate_scores[result.best_idx]}"
528
+ )
529
+ logger.info(f"Best candidate: {result.best_candidate}")
530
+
531
+ self._best_candidate = result.best_candidate
532
+ self._best_score = result.val_aggregate_scores[result.best_idx]
533
+ self._full_result = result # Store full result for candidate history
534
+
535
+ # Log final summary metrics (these complement the per-step
536
+ # best_score series logged by on_step_callback above)
537
+ if hasattr(store, "_run") and store._run:
538
+ try:
539
+ store._run.log(
540
+ {
541
+ "best_score": self._best_score,
542
+ "num_candidates": len(result.candidates),
543
+ "metric_calls": result.total_metric_calls,
544
+ },
545
+ step=result.total_metric_calls,
546
+ )
547
+ logger.info(f"Logged final GEPA metrics: best_score={self._best_score}")
548
+ except Exception as e:
549
+ logger.warning(f"Failed to log final metrics: {e}")
550
+
551
+ # Update the store with the best candidate
552
+ final_resources = {}
553
+ for key, value in result.best_candidate.items():
554
+ original = initial_resources.get(key)
555
+ engine = original.engine if isinstance(original, PromptTemplate) else "f-string"
556
+ final_resources[key] = PromptTemplate(template=value, engine=engine)
557
+
558
+ await store.update_resources("gepa-final", final_resources)
559
+ logger.info("Updated store with best candidate resources (version: 'gepa-final').")
560
+
561
+ # Send full GEPA result to Gateway for experiment tracking
562
+ if hasattr(store, "complete_job"):
563
+ summary = result.to_dict()
564
+ # Add session_id for trace filtering in the UI
565
+ summary["session_id"] = tracing_context.session_id
566
+ store.complete_job(summary)
567
+
568
+ except Exception as e:
569
+ logger.error(f"GEPA optimization failed: {e}")
570
+ raise
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2025 Lakshya A Agrawal and the GEPA contributors
2
+ # https://github.com/gepa-ai/gepa
3
+
4
+ from .adapters import default_adapter
5
+ from .api import optimize
6
+ from .core.adapter import EvaluationBatch, GEPAAdapter
7
+ from .core.result import GEPAResult
8
+ from .examples import aime
9
+ from .utils.stop_condition import (
10
+ CompositeStopper,
11
+ FileStopper,
12
+ MaxMetricCallsStopper,
13
+ NoImprovementStopper,
14
+ ScoreThresholdStopper,
15
+ SignalStopper,
16
+ StopperProtocol,
17
+ TimeoutStopCondition,
18
+ )
@@ -0,0 +1,12 @@
1
+ # GEPA Adapters
2
+
3
+ > GEPA 🤝 Any Framework
4
+
5
+ This directory provides the interface to allow GEPA to plug into systems and frameworks of your choice! GEPA can interface with any system consisting of text components, by implementing `GEPAAdapter` in [../core/adapter.py](../core/adapter.py).
6
+
7
+ Currently, GEPA has the following adapters:
8
+ - [DSPy Adapter](./dspy_adapter/): This adapter integrates GEPA into [DSPy](https://dspy.ai/), to allow it to optimize any DSPy module's signature instructions.
9
+ - [Default Adapter](./default_adapter/): This adapter integrates GEPA into a single-turn LLM environment, where the task is specified as a user message, and an answer string must be present in the assistant response. GEPA optimizes the system prompt.
10
+ - [AnyMaths Adapter](./anymaths_adapter/): This adapter integrates GEPA with litellm and ollama to solve single-turn mathematical problems.
11
+
12
+ If there are any frameworks you would like GEPA integrated into, please create an issue or PR!
File without changes