orizu 0.5.19 → 0.5.21

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 (378) hide show
  1. package/README.md +23 -0
  2. package/dist/archive-artifacts-cli.d.ts +50 -0
  3. package/dist/archive-artifacts-cli.d.ts.map +1 -0
  4. package/dist/artifact-archive.d.ts +48 -0
  5. package/dist/artifact-archive.d.ts.map +1 -0
  6. package/dist/artifact-pull.d.ts +22 -0
  7. package/dist/artifact-pull.d.ts.map +1 -0
  8. package/dist/banner.d.ts +3 -0
  9. package/dist/banner.d.ts.map +1 -0
  10. package/dist/connectors-cli.d.ts +31 -0
  11. package/dist/connectors-cli.d.ts.map +1 -0
  12. package/dist/credentials.d.ts +46 -0
  13. package/dist/credentials.d.ts.map +1 -0
  14. package/dist/csv.d.ts +49 -0
  15. package/dist/csv.d.ts.map +1 -0
  16. package/dist/dataset-download.d.ts +6 -0
  17. package/dist/dataset-download.d.ts.map +1 -0
  18. package/dist/dataset-edit-rows.d.ts +10 -0
  19. package/dist/dataset-edit-rows.d.ts.map +1 -0
  20. package/dist/dataset-upload-snapshot.d.ts +13 -0
  21. package/dist/dataset-upload-snapshot.d.ts.map +1 -0
  22. package/dist/daytona-slice-rehearsal.d.ts +89 -0
  23. package/dist/daytona-slice-rehearsal.d.ts.map +1 -0
  24. package/dist/daytona-slice.d.ts +106 -0
  25. package/dist/daytona-slice.d.ts.map +1 -0
  26. package/dist/deploy-key-merge-core.d.ts +121 -0
  27. package/dist/deploy-key-merge-core.d.ts.map +1 -0
  28. package/dist/diff-comments-cli.d.ts +12 -0
  29. package/dist/diff-comments-cli.d.ts.map +1 -0
  30. package/dist/diff-comments-cli.js +21 -2
  31. package/dist/egress-allowlist-cli.d.ts +23 -0
  32. package/dist/egress-allowlist-cli.d.ts.map +1 -0
  33. package/dist/egress-policy.d.ts +108 -0
  34. package/dist/egress-policy.d.ts.map +1 -0
  35. package/dist/error-response.d.ts +9 -0
  36. package/dist/error-response.d.ts.map +1 -0
  37. package/dist/file-parser.d.ts +5 -0
  38. package/dist/file-parser.d.ts.map +1 -0
  39. package/dist/gepa-engine-dispatch.d.ts +9 -0
  40. package/dist/gepa-engine-dispatch.d.ts.map +1 -0
  41. package/dist/gepa-engine-dispatch.js +307 -0
  42. package/dist/gepa-python-command.d.ts +6 -0
  43. package/dist/gepa-python-command.d.ts.map +1 -0
  44. package/dist/gepa-python-command.js +26 -0
  45. package/dist/gepa-python-paths.d.ts +6 -0
  46. package/dist/gepa-python-paths.d.ts.map +1 -0
  47. package/dist/gepa-python-paths.js +42 -0
  48. package/dist/git-credential.d.ts +69 -0
  49. package/dist/git-credential.d.ts.map +1 -0
  50. package/dist/git-recovery-environment.d.ts +31 -0
  51. package/dist/git-recovery-environment.d.ts.map +1 -0
  52. package/dist/github-setup.d.ts +122 -0
  53. package/dist/github-setup.d.ts.map +1 -0
  54. package/dist/global-flags.d.ts +12 -0
  55. package/dist/global-flags.d.ts.map +1 -0
  56. package/dist/help.d.ts +46 -0
  57. package/dist/help.d.ts.map +1 -0
  58. package/dist/help.js +93 -25
  59. package/dist/hosted-boot.d.ts +273 -0
  60. package/dist/hosted-boot.d.ts.map +1 -0
  61. package/dist/hosted-bootstrap-rehearsal.d.ts +86 -0
  62. package/dist/hosted-bootstrap-rehearsal.d.ts.map +1 -0
  63. package/dist/hosted-bootstrap.d.ts +188 -0
  64. package/dist/hosted-bootstrap.d.ts.map +1 -0
  65. package/dist/hosted-broker-server.d.ts +50 -0
  66. package/dist/hosted-broker-server.d.ts.map +1 -0
  67. package/dist/hosted-git-http-server.d.ts +36 -0
  68. package/dist/hosted-git-http-server.d.ts.map +1 -0
  69. package/dist/hosted-harness-claude.d.ts +195 -0
  70. package/dist/hosted-harness-claude.d.ts.map +1 -0
  71. package/dist/hosted-harness-opencode.d.ts +227 -0
  72. package/dist/hosted-harness-opencode.d.ts.map +1 -0
  73. package/dist/hosted-harness.d.ts +118 -0
  74. package/dist/hosted-harness.d.ts.map +1 -0
  75. package/dist/hosted-harvest.d.ts +68 -0
  76. package/dist/hosted-harvest.d.ts.map +1 -0
  77. package/dist/hosted-headless.d.ts +72 -0
  78. package/dist/hosted-headless.d.ts.map +1 -0
  79. package/dist/hosted-loop-lifecycle.d.ts +206 -0
  80. package/dist/hosted-loop-lifecycle.d.ts.map +1 -0
  81. package/dist/hosted-loop.d.ts +170 -0
  82. package/dist/hosted-loop.d.ts.map +1 -0
  83. package/dist/hosted-run-event-sink.d.ts +222 -0
  84. package/dist/hosted-run-event-sink.d.ts.map +1 -0
  85. package/dist/hosted-runtime-assets.d.ts +186 -0
  86. package/dist/hosted-runtime-assets.d.ts.map +1 -0
  87. package/dist/hosted-session-cli.d.ts +258 -0
  88. package/dist/hosted-session-cli.d.ts.map +1 -0
  89. package/dist/hosted-skill-staging.d.ts +73 -0
  90. package/dist/hosted-skill-staging.d.ts.map +1 -0
  91. package/dist/http.d.ts +8 -0
  92. package/dist/http.d.ts.map +1 -0
  93. package/dist/index.d.ts +22 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +119 -129
  96. package/dist/instruction-set-gepa-launch.d.ts +3 -0
  97. package/dist/instruction-set-gepa-launch.d.ts.map +1 -0
  98. package/dist/instruction-set-gepa-launch.js +15 -0
  99. package/dist/instruction-set-loader.d.ts +6 -0
  100. package/dist/instruction-set-loader.d.ts.map +1 -0
  101. package/dist/instruction-set-loader.js +59 -0
  102. package/dist/instruction-set-manifest.d.ts +14 -0
  103. package/dist/instruction-set-manifest.d.ts.map +1 -0
  104. package/dist/instruction-set-manifest.js +162 -0
  105. package/dist/instruction-sets-cli.d.ts +40 -0
  106. package/dist/instruction-sets-cli.d.ts.map +1 -0
  107. package/dist/instruction-sets-cli.js +361 -0
  108. package/dist/json-response.d.ts +4 -0
  109. package/dist/json-response.d.ts.map +1 -0
  110. package/dist/jsonl-stream.d.ts +8 -0
  111. package/dist/jsonl-stream.d.ts.map +1 -0
  112. package/dist/kill-switch-cli.d.ts +30 -0
  113. package/dist/kill-switch-cli.d.ts.map +1 -0
  114. package/dist/loopback-serve.d.ts +25 -0
  115. package/dist/loopback-serve.d.ts.map +1 -0
  116. package/dist/manifests-cli.d.ts +22 -0
  117. package/dist/manifests-cli.d.ts.map +1 -0
  118. package/dist/markdown-report-input.d.ts +7 -0
  119. package/dist/markdown-report-input.d.ts.map +1 -0
  120. package/dist/markdown-report-input.js +15 -1
  121. package/dist/merge-job.d.ts +155 -0
  122. package/dist/merge-job.d.ts.map +1 -0
  123. package/dist/model-configs-cli.d.ts +19 -0
  124. package/dist/model-configs-cli.d.ts.map +1 -0
  125. package/dist/model-configs-cli.js +104 -0
  126. package/dist/optimization-export-cli.d.ts +19 -0
  127. package/dist/optimization-export-cli.d.ts.map +1 -0
  128. package/dist/optimizations-list-cli.d.ts +20 -0
  129. package/dist/optimizations-list-cli.d.ts.map +1 -0
  130. package/dist/optimizations-promote-cli.d.ts +8 -0
  131. package/dist/optimizations-promote-cli.d.ts.map +1 -0
  132. package/dist/optimizations-promote-cli.js +34 -0
  133. package/dist/option-validation.d.ts +15 -0
  134. package/dist/option-validation.d.ts.map +1 -0
  135. package/dist/preview-runtime.d.ts +63 -0
  136. package/dist/preview-runtime.d.ts.map +1 -0
  137. package/dist/prompt-draft-push.d.ts +60 -0
  138. package/dist/prompt-draft-push.d.ts.map +1 -0
  139. package/dist/prompt-label-cli.d.ts +11 -0
  140. package/dist/prompt-label-cli.d.ts.map +1 -0
  141. package/dist/prompt-label-cli.js +29 -0
  142. package/dist/prompt-length-wire.d.ts +28 -0
  143. package/dist/prompt-length-wire.d.ts.map +1 -0
  144. package/dist/prompt-length-wire.js +2 -2
  145. package/dist/prompt-report-cli.d.ts +10 -0
  146. package/dist/prompt-report-cli.d.ts.map +1 -0
  147. package/dist/prompt-report-cli.js +2 -2
  148. package/dist/prompt-summary-table.d.ts +15 -0
  149. package/dist/prompt-summary-table.d.ts.map +1 -0
  150. package/dist/prompt-summary-table.js +6 -0
  151. package/dist/registration-tag-warning.d.ts +32 -0
  152. package/dist/registration-tag-warning.d.ts.map +1 -0
  153. package/dist/report-comments-cli.d.ts +16 -0
  154. package/dist/report-comments-cli.d.ts.map +1 -0
  155. package/dist/report-markdown-blankness.d.ts +2 -0
  156. package/dist/report-markdown-blankness.d.ts.map +1 -0
  157. package/dist/report-markdown-blankness.js +6 -0
  158. package/dist/report-replacement-warning.d.ts +17 -0
  159. package/dist/report-replacement-warning.d.ts.map +1 -0
  160. package/dist/report-replacement-warning.js +31 -0
  161. package/dist/repository-backup-core.d.ts +225 -0
  162. package/dist/repository-backup-core.d.ts.map +1 -0
  163. package/dist/repository-recovery-manifest.d.ts +83 -0
  164. package/dist/repository-recovery-manifest.d.ts.map +1 -0
  165. package/dist/run-event-digest.d.ts +74 -0
  166. package/dist/run-event-digest.d.ts.map +1 -0
  167. package/dist/runner-dir-verify.d.ts +66 -0
  168. package/dist/runner-dir-verify.d.ts.map +1 -0
  169. package/dist/runner-instruction-set-contract.d.ts +24 -0
  170. package/dist/runner-instruction-set-contract.d.ts.map +1 -0
  171. package/dist/runner-instruction-set-contract.js +50 -0
  172. package/dist/sandbox-hygiene.d.ts +45 -0
  173. package/dist/sandbox-hygiene.d.ts.map +1 -0
  174. package/dist/sandbox-provider.d.ts +193 -0
  175. package/dist/sandbox-provider.d.ts.map +1 -0
  176. package/dist/scorer-draft-push.d.ts +50 -0
  177. package/dist/scorer-draft-push.d.ts.map +1 -0
  178. package/dist/scorers-cli.d.ts +20 -0
  179. package/dist/scorers-cli.d.ts.map +1 -0
  180. package/dist/scorers-cli.js +22 -0
  181. package/dist/scorers-verify-parity-bridge.d.ts +16 -0
  182. package/dist/scorers-verify-parity-bridge.d.ts.map +1 -0
  183. package/dist/scorers-verify-parity-bridge.js +90 -0
  184. package/dist/scorers-verify-parity.d.ts +81 -0
  185. package/dist/scorers-verify-parity.d.ts.map +1 -0
  186. package/dist/scorers-verify-parity.js +502 -0
  187. package/dist/scores-accept-cli.d.ts +21 -0
  188. package/dist/scores-accept-cli.d.ts.map +1 -0
  189. package/dist/secret-redaction.d.ts +47 -0
  190. package/dist/secret-redaction.d.ts.map +1 -0
  191. package/dist/session-timeline.d.ts +54 -0
  192. package/dist/session-timeline.d.ts.map +1 -0
  193. package/dist/setup-prompt.d.ts +5 -0
  194. package/dist/setup-prompt.d.ts.map +1 -0
  195. package/dist/skill-installer.d.ts +68 -0
  196. package/dist/skill-installer.d.ts.map +1 -0
  197. package/dist/skilled-proposer-launch.d.ts +7 -0
  198. package/dist/skilled-proposer-launch.d.ts.map +1 -0
  199. package/dist/skilled-proposer-launch.js +60 -0
  200. package/dist/smoke.d.ts +102 -0
  201. package/dist/smoke.d.ts.map +1 -0
  202. package/dist/start-intent.d.ts +12 -0
  203. package/dist/start-intent.d.ts.map +1 -0
  204. package/dist/task-assignment-manifest.d.ts +15 -0
  205. package/dist/task-assignment-manifest.d.ts.map +1 -0
  206. package/dist/task-create-error.d.ts +18 -0
  207. package/dist/task-create-error.d.ts.map +1 -0
  208. package/dist/team-connectors-cli.d.ts +29 -0
  209. package/dist/team-connectors-cli.d.ts.map +1 -0
  210. package/dist/types.d.ts +39 -0
  211. package/dist/types.d.ts.map +1 -0
  212. package/dist/vercel-sandbox-provider.d.ts +156 -0
  213. package/dist/vercel-sandbox-provider.d.ts.map +1 -0
  214. package/dist/workbench-cli.d.ts +233 -0
  215. package/dist/workbench-cli.d.ts.map +1 -0
  216. package/dist/workspace-sync.d.ts +207 -0
  217. package/dist/workspace-sync.d.ts.map +1 -0
  218. package/dist/workspace.d.ts +92 -0
  219. package/dist/workspace.d.ts.map +1 -0
  220. package/dist/zip-draft-push.d.ts +55 -0
  221. package/dist/zip-draft-push.d.ts.map +1 -0
  222. package/package.json +15 -2
  223. package/requirements/README.md +138 -0
  224. package/requirements/skilled-proposer.in +66 -0
  225. package/requirements/skilled-proposer.lock +265 -0
  226. package/scripts/build-cli-dist.mjs +30 -0
  227. package/scripts/ensure-skilled-proposer-venv.mjs +5 -0
  228. package/scripts/orizu-source-checkout.d.mts +1 -0
  229. package/scripts/orizu-source-checkout.mjs +10 -0
  230. package/scripts/refresh-skilled-proposer-lock.mjs +256 -0
  231. package/scripts/vendor-gepa-python.mjs +187 -4
  232. package/src/diff-comments-cli.ts +41 -3
  233. package/src/gepa-engine-dispatch.ts +340 -0
  234. package/src/gepa-python-command.ts +31 -0
  235. package/src/gepa-python-paths.ts +56 -0
  236. package/src/help.ts +95 -25
  237. package/src/index.ts +131 -166
  238. package/src/instruction-set-gepa-launch.ts +28 -0
  239. package/src/instruction-set-loader.ts +37 -0
  240. package/src/instruction-set-manifest.ts +120 -0
  241. package/src/instruction-sets-cli.ts +306 -0
  242. package/src/markdown-report-input.ts +19 -1
  243. package/src/model-configs-cli.ts +119 -0
  244. package/src/optimizations-promote-cli.ts +41 -0
  245. package/src/prompt-label-cli.ts +55 -0
  246. package/src/prompt-length-wire.ts +1 -1
  247. package/src/prompt-report-cli.ts +2 -2
  248. package/src/prompt-summary-table.ts +12 -0
  249. package/src/report-markdown-blankness.ts +6 -0
  250. package/src/report-replacement-warning.ts +35 -0
  251. package/src/runner-instruction-set-contract.ts +64 -0
  252. package/src/scorers-cli.ts +40 -0
  253. package/src/scorers-verify-parity-bridge.ts +90 -0
  254. package/src/scorers-verify-parity.ts +564 -0
  255. package/src/skilled-proposer-launch.ts +89 -0
  256. package/src/skilled-proposer-venv-manager.mjs +757 -0
  257. package/tsconfig.json +2 -0
  258. package/vendor/gepa-python/LICENSE +7 -0
  259. package/vendor/gepa-python/manifest.json +107 -0
  260. package/vendor/gepa-python/src/gepa/__init__.py +22 -0
  261. package/vendor/gepa-python/src/gepa/adapters/__init__.py +0 -0
  262. package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/__init__.py +1 -0
  263. package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
  264. package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/__init__.py +26 -0
  265. package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/confidence_adapter.py +618 -0
  266. package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/scoring.py +206 -0
  267. package/vendor/gepa-python/src/gepa/adapters/default_adapter/__init__.py +0 -0
  268. package/vendor/gepa-python/src/gepa/adapters/default_adapter/default_adapter.py +206 -0
  269. package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/__init__.py +0 -0
  270. package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/dspy_adapter.py +525 -0
  271. package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/instruction_proposal.py +500 -0
  272. package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/__init__.py +6 -0
  273. package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
  274. package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/full_program_adapter.py +269 -0
  275. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/__init__.py +56 -0
  276. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
  277. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
  278. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
  279. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
  280. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
  281. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
  282. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
  283. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
  284. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
  285. package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
  286. package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/__init__.py +11 -0
  287. package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/langchain_adapter.py +261 -0
  288. package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/__init__.py +37 -0
  289. package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_adapter.py +693 -0
  290. package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_client.py +364 -0
  291. package/vendor/gepa-python/src/gepa/adapters/optimize_anything_adapter/optimize_anything_adapter.py +879 -0
  292. package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/__init__.py +0 -0
  293. package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
  294. package/vendor/gepa-python/src/gepa/api.py +468 -0
  295. package/vendor/gepa-python/src/gepa/core/__init__.py +0 -0
  296. package/vendor/gepa-python/src/gepa/core/adapter.py +227 -0
  297. package/vendor/gepa-python/src/gepa/core/callbacks.py +551 -0
  298. package/vendor/gepa-python/src/gepa/core/data_loader.py +74 -0
  299. package/vendor/gepa-python/src/gepa/core/engine.py +1025 -0
  300. package/vendor/gepa-python/src/gepa/core/result.py +271 -0
  301. package/vendor/gepa-python/src/gepa/core/state.py +706 -0
  302. package/vendor/gepa-python/src/gepa/examples/__init__.py +0 -0
  303. package/vendor/gepa-python/src/gepa/examples/aime.py +24 -0
  304. package/vendor/gepa-python/src/gepa/examples/anymaths-bench/eval_default.py +111 -0
  305. package/vendor/gepa-python/src/gepa/examples/anymaths-bench/train_anymaths.py +177 -0
  306. package/vendor/gepa-python/src/gepa/examples/mcp_adapter/__init__.py +4 -0
  307. package/vendor/gepa-python/src/gepa/examples/mcp_adapter/mcp_optimization_example.py +456 -0
  308. package/vendor/gepa-python/src/gepa/examples/rag_adapter/__init__.py +9 -0
  309. package/vendor/gepa-python/src/gepa/examples/rag_adapter/rag_optimization.py +824 -0
  310. package/vendor/gepa-python/src/gepa/examples/terminal-bench/train_terminus.py +161 -0
  311. package/vendor/gepa-python/src/gepa/gepa_utils.py +117 -0
  312. package/vendor/gepa-python/src/gepa/gskill/__init__.py +1 -0
  313. package/vendor/gepa-python/src/gepa/gskill/gskill/__init__.py +0 -0
  314. package/vendor/gepa-python/src/gepa/gskill/gskill/cost_tracker.py +194 -0
  315. package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/__init__.py +0 -0
  316. package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code.py +1117 -0
  317. package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code_skills.py +613 -0
  318. package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/mini_swe_agent.py +440 -0
  319. package/vendor/gepa-python/src/gepa/gskill/gskill/experiment_logger.py +367 -0
  320. package/vendor/gepa-python/src/gepa/gskill/gskill/swe_fitness_fn.py +209 -0
  321. package/vendor/gepa-python/src/gepa/gskill/gskill/swe_harness.py +352 -0
  322. package/vendor/gepa-python/src/gepa/gskill/gskill/train_optimize_anything.py +830 -0
  323. package/vendor/gepa-python/src/gepa/image.py +104 -0
  324. package/vendor/gepa-python/src/gepa/lm.py +261 -0
  325. package/vendor/gepa-python/src/gepa/logging/__init__.py +0 -0
  326. package/vendor/gepa-python/src/gepa/logging/experiment_tracker.py +457 -0
  327. package/vendor/gepa-python/src/gepa/logging/logger.py +75 -0
  328. package/vendor/gepa-python/src/gepa/logging/utils.py +130 -0
  329. package/vendor/gepa-python/src/gepa/optimize_anything.py +1701 -0
  330. package/vendor/gepa-python/src/gepa/proposer/__init__.py +0 -0
  331. package/vendor/gepa-python/src/gepa/proposer/base.py +53 -0
  332. package/vendor/gepa-python/src/gepa/proposer/merge.py +403 -0
  333. package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/__init__.py +0 -0
  334. package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/base.py +64 -0
  335. package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflection_lm.py +178 -0
  336. package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflective_mutation.py +641 -0
  337. package/vendor/gepa-python/src/gepa/py.typed +0 -0
  338. package/vendor/gepa-python/src/gepa/strategies/__init__.py +0 -0
  339. package/vendor/gepa-python/src/gepa/strategies/acceptance.py +66 -0
  340. package/vendor/gepa-python/src/gepa/strategies/batch_sampler.py +103 -0
  341. package/vendor/gepa-python/src/gepa/strategies/candidate_selector.py +82 -0
  342. package/vendor/gepa-python/src/gepa/strategies/component_selector.py +36 -0
  343. package/vendor/gepa-python/src/gepa/strategies/eval_policy.py +64 -0
  344. package/vendor/gepa-python/src/gepa/strategies/instruction_proposal.py +153 -0
  345. package/vendor/gepa-python/src/gepa/strategies/proposal_sampling.py +128 -0
  346. package/vendor/gepa-python/src/gepa/strategies/proposal_selection.py +84 -0
  347. package/vendor/gepa-python/src/gepa/utils/__init__.py +63 -0
  348. package/vendor/gepa-python/src/gepa/utils/code_execution.py +626 -0
  349. package/vendor/gepa-python/src/gepa/utils/stdio_capture.py +145 -0
  350. package/vendor/gepa-python/src/gepa/utils/stop_condition.py +230 -0
  351. package/vendor/gepa-python/src/gepa/visualization.py +359 -0
  352. package/vendor/orizu-gepa/pyproject.toml +18 -0
  353. package/vendor/orizu-gepa/src/orizu_gepa_connector/__init__.py +9 -0
  354. package/vendor/orizu-gepa/src/orizu_gepa_connector/__main__.py +5 -0
  355. package/vendor/orizu-gepa/src/orizu_gepa_connector/adapter.py +138 -0
  356. package/vendor/orizu-gepa/src/orizu_gepa_connector/callbacks.py +666 -0
  357. package/vendor/orizu-gepa/src/orizu_gepa_connector/cli.py +7 -0
  358. package/vendor/orizu-gepa/src/orizu_gepa_connector/engine.py +269 -0
  359. package/vendor/orizu-gepa/src/orizu_gepa_connector/instruction_set_loader.py +52 -0
  360. package/vendor/orizu-gepa/src/orizu_gepa_connector/preflight.py +64 -0
  361. package/vendor/orizu-gepa/src/orizu_gepa_connector/reflection.py +186 -0
  362. package/vendor/orizu-gepa/src/orizu_gepa_connector/runtime.py +721 -0
  363. package/vendor/orizu-gepa/src/orizu_gepa_connector/skilled_proposer_bridge.py +381 -0
  364. package/vendor/orizu-gepa/src/orizu_gepa_connector/stop_conditions.py +55 -0
  365. package/vendor/orizu-gepa/src/orizu_gepa_connector/translator.py +203 -0
  366. package/vendor/orizu-gepa-python/pyproject.toml +1 -1
  367. package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +1 -0
  368. package/vendor/orizu-gepa-python/src/orizu_gepa/client.py +52 -7
  369. package/vendor/orizu-gepa-python/src/orizu_gepa/local_log.py +52 -0
  370. package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +10 -5
  371. package/vendor/orizu-gepa-python/src/orizu_gepa/reflection.py +323 -68
  372. package/vendor/orizu-gepa-python/src/orizu_gepa/runner.py +207 -13
  373. package/vendor/skills/orizu-cli/SKILL.md +3 -1
  374. package/vendor/skills/orizu-cli/references/cli-reference.md +85 -1
  375. package/vendor/skills/orizu-cli/references/migrate-existing-gepa-setup.md +303 -0
  376. package/vendor/skills/orizu-cli/references/optimization-reports.md +1 -1
  377. package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +26 -1
  378. package/vendor/skills/orizu-cli/references/prompt-control-plane.md +113 -10
@@ -0,0 +1,618 @@
1
+ # Copyright (c) 2025 Lakshya A Agrawal and the GEPA contributors
2
+ # https://github.com/gepa-ai/gepa
3
+
4
+ """Confidence-aware adapter for structured-output classification tasks.
5
+
6
+ Uses token-level logprobs from ``llm-structured-confidence`` to detect
7
+ and penalise lucky guesses, feeding rich confidence diagnostics into
8
+ the reflection LLM. Requires structured output with enum constraints
9
+ and a model that supports ``logprobs=True``.
10
+
11
+ See the full guide: https://gepa-ai.github.io/gepa/guides/confidence-adapter/
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import logging
18
+ import math
19
+ from collections.abc import Mapping, Sequence
20
+ from typing import Any, Protocol, TypedDict
21
+
22
+ from gepa.adapters.confidence_adapter.scoring import LinearBlendScoring, ScoringStrategy
23
+ from gepa.core.adapter import EvaluationBatch, GEPAAdapter, ProposalFn
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ TOP_ALTERNATIVES_IN_FEEDBACK = 3
28
+
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Data types
32
+ # ---------------------------------------------------------------------------
33
+
34
+
35
+ class ConfidenceDataInst(TypedDict):
36
+ """Input data instance for confidence-aware evaluation.
37
+
38
+ Attributes
39
+ ----------
40
+ input:
41
+ The user-facing text to classify (e.g. a transaction description).
42
+ additional_context:
43
+ Optional key-value pairs surfaced in reflective feedback.
44
+ answer:
45
+ The expected classification label (must match an enum value).
46
+ """
47
+
48
+ input: str
49
+ additional_context: dict[str, str]
50
+ answer: str
51
+
52
+
53
+ class ConfidenceTrajectory(TypedDict):
54
+ """Per-example execution trace used to build reflective feedback.
55
+
56
+ Attributes
57
+ ----------
58
+ data:
59
+ The original input data instance.
60
+ full_assistant_response:
61
+ Raw text returned by the LLM.
62
+ parsed_value:
63
+ Value extracted from the JSON response at ``answer_field``.
64
+ logprob_score:
65
+ Joint logprob (sum of per-token logprobs) for the target field.
66
+ Always ``<= 0``; closer to 0 = more confident. ``None`` when
67
+ logprobs are unavailable.
68
+ top_alternatives:
69
+ Top alternative tokens with their probabilities and resolved
70
+ enum values (when ``response_schema`` is provided).
71
+ is_correct:
72
+ Whether ``parsed_value`` matches the expected answer.
73
+ score:
74
+ Blended score produced by the scoring strategy.
75
+ feedback:
76
+ Human-readable feedback string including confidence details.
77
+ """
78
+
79
+ data: ConfidenceDataInst
80
+ full_assistant_response: str
81
+ parsed_value: str | None
82
+ logprob_score: float | None
83
+ top_alternatives: list[dict[str, Any]]
84
+ is_correct: bool
85
+ score: float
86
+ feedback: str
87
+
88
+
89
+ class ConfidenceRolloutOutput(TypedDict):
90
+ """Per-example output exposed to GEPA (opaque to the engine).
91
+
92
+ Attributes
93
+ ----------
94
+ full_assistant_response:
95
+ Raw text returned by the LLM.
96
+ parsed_value:
97
+ Value extracted from the JSON response at ``answer_field``.
98
+ logprob_score:
99
+ Joint logprob for the target field.
100
+ """
101
+
102
+ full_assistant_response: str
103
+ parsed_value: str | None
104
+ logprob_score: float | None
105
+
106
+
107
+ ConfidenceReflectiveRecord = TypedDict(
108
+ "ConfidenceReflectiveRecord",
109
+ {
110
+ "Inputs": str,
111
+ "Generated Outputs": str,
112
+ "Feedback": str,
113
+ },
114
+ )
115
+
116
+
117
+ class ChatMessage(TypedDict):
118
+ role: str
119
+ content: str
120
+
121
+
122
+ class ChatCompletionCallable(Protocol):
123
+ """Protocol for callables that return the raw LLM response object.
124
+
125
+ The callable must return the **full** response object (e.g.
126
+ ``litellm.ModelResponse``) so that logprobs can be extracted.
127
+ """
128
+
129
+ def __call__(self, messages: Sequence[ChatMessage]) -> Any: ...
130
+
131
+
132
+ # ---------------------------------------------------------------------------
133
+ # Helpers
134
+ # ---------------------------------------------------------------------------
135
+
136
+
137
+ def _extract_answer_from_json(text: str, field_path: str) -> str | None:
138
+ """Walk *field_path* (dot-separated) into parsed JSON and return the leaf value."""
139
+ try:
140
+ obj = json.loads(text)
141
+ except (json.JSONDecodeError, TypeError):
142
+ return None
143
+ for key in field_path.split("."):
144
+ if isinstance(obj, dict):
145
+ obj = obj.get(key)
146
+ else:
147
+ return None
148
+ return str(obj) if obj is not None else None
149
+
150
+
151
+ def _build_feedback(
152
+ *,
153
+ is_correct: bool,
154
+ expected: str,
155
+ got: str | None,
156
+ logprob_score: float | None,
157
+ top_alternatives: list[dict[str, Any]],
158
+ additional_context: dict[str, str],
159
+ high_confidence_prob: float,
160
+ low_confidence_prob: float,
161
+ ) -> str:
162
+ """Build feedback for the reflection LLM using probability only.
163
+
164
+ Design principles:
165
+ - **Correct + confident**: just ``"Correct."`` -- no noise.
166
+ - **Correct + uncertain**: flag it as risky with alternatives.
167
+ - **Incorrect**: rich detail scaled by confidence -- the higher the
168
+ model's certainty on the wrong answer, the stronger the language.
169
+
170
+ Parameters
171
+ ----------
172
+ high_confidence_prob:
173
+ Probability threshold above which a prediction is considered
174
+ "highly confident".
175
+ low_confidence_prob:
176
+ Probability threshold below which a *correct* prediction is
177
+ labelled "unreliable".
178
+ """
179
+ probability = math.exp(logprob_score) if logprob_score is not None else None
180
+ got_str = got or "<parse error>"
181
+
182
+ if is_correct:
183
+ if probability is None or probability >= high_confidence_prob:
184
+ feedback = "Correct."
185
+ elif probability < low_confidence_prob:
186
+ alt_str = _format_alternatives(top_alternatives, exclude=expected)
187
+ feedback = (
188
+ f"Correct but uncertain ({probability:.0%} probability). "
189
+ f"Model answered '{expected}' but was nearly split with alternatives."
190
+ )
191
+ if alt_str:
192
+ feedback += f" Top alternatives: {alt_str}."
193
+ feedback += " The model cannot reliably distinguish between these categories with the current prompt."
194
+ else:
195
+ alt_str = _format_alternatives(top_alternatives, exclude=expected)
196
+ feedback = f"Correct ({probability:.0%} probability)."
197
+ if alt_str:
198
+ feedback += f" Close alternatives: {alt_str}."
199
+ else:
200
+ alt_str = _format_alternatives(top_alternatives, exclude=got_str)
201
+ correct_alt_prob = _find_alternative_prob(top_alternatives, expected)
202
+
203
+ if probability is not None and probability >= high_confidence_prob:
204
+ feedback = (
205
+ f"WRONG — model has {probability:.0%} certainty on '{got_str}' "
206
+ f"but the correct answer is '{expected}'. "
207
+ "The model has no doubt about its wrong answer; "
208
+ "the prompt is actively misleading it for this type of input."
209
+ )
210
+ if correct_alt_prob is not None:
211
+ feedback += f" The correct category '{expected}' only had {correct_alt_prob:.1%} probability."
212
+ if alt_str:
213
+ feedback += f" Alternatives: {alt_str}."
214
+ feedback += f" The prompt must add explicit rules to disambiguate '{got_str}' vs '{expected}'."
215
+ elif probability is not None and probability >= low_confidence_prob:
216
+ feedback = f"Wrong ({probability:.0%} probability). Expected '{expected}' but got '{got_str}'."
217
+ if alt_str:
218
+ feedback += f" Alternatives: {alt_str}."
219
+ feedback += " The prompt should better guide the model for this case."
220
+ else:
221
+ prob_str = f"{probability:.0%} probability" if probability is not None else "unknown confidence"
222
+ feedback = (
223
+ f"Wrong ({prob_str}). "
224
+ f"Expected '{expected}' but got '{got_str}'. "
225
+ "The model was uncertain — better prompt guidance could fix this."
226
+ )
227
+ if alt_str:
228
+ feedback += f" Alternatives: {alt_str}."
229
+
230
+ ctx = "\n".join(f"{k}: {v}" for k, v in additional_context.items())
231
+ if ctx:
232
+ feedback += f"\nAdditional context:\n{ctx}"
233
+
234
+ return feedback
235
+
236
+
237
+ def _find_alternative_prob(
238
+ alts: list[dict[str, Any]],
239
+ target: str,
240
+ ) -> float | None:
241
+ """Find the probability of *target* in the alternatives list."""
242
+ for alt in alts:
243
+ val = alt.get("resolved_value") or alt.get("token", "")
244
+ if val == target:
245
+ return alt.get("probability", 0.0)
246
+ return None
247
+
248
+
249
+ def _format_alternatives(alts: list[dict[str, Any]], exclude: str | None = None) -> str:
250
+ parts: list[str] = []
251
+ for alt in alts[:TOP_ALTERNATIVES_IN_FEEDBACK]:
252
+ val = alt.get("resolved_value") or alt.get("token", "")
253
+ prob = alt.get("probability", 0.0)
254
+ if val and val != exclude:
255
+ parts.append(f"'{val}' ({prob:.0%})")
256
+ return ", ".join(parts)
257
+
258
+
259
+ # ---------------------------------------------------------------------------
260
+ # ConfidenceAdapter
261
+ # ---------------------------------------------------------------------------
262
+
263
+
264
+ class ConfidenceAdapter(GEPAAdapter[ConfidenceDataInst, ConfidenceTrajectory, ConfidenceRolloutOutput]):
265
+ """GEPA adapter for structured-output classification with logprob confidence.
266
+
267
+
268
+ This adapter is specifically designed for **classification tasks** where
269
+ the LLM returns a structured JSON output with an ``enum``-constrained
270
+ field. The ``enum`` constraint is critical: it forces the model to
271
+ choose from a closed set of categories, and the logprobs then represent
272
+ the model's true probability distribution over those categories.
273
+
274
+ The adapter owns the full LLM call lifecycle:
275
+
276
+ 1. Sends requests with ``logprobs=True`` and ``response_format``
277
+ 2. Parses the structured JSON output
278
+ 3. Extracts the **joint logprob** (sum of per-token logprobs) for the
279
+ target field via ``llm-structured-confidence``
280
+ 4. Computes a blended score via the pluggable :class:`ScoringStrategy`
281
+ 5. Generates rich reflective feedback with confidence details
282
+
283
+ Why joint logprob?
284
+ ~~~~~~~~~~~~~~~~~~
285
+ The ``joint_logprob`` is the sum of all per-token logprobs for the
286
+ value tokens of the target field. For example, if the model outputs
287
+ ``"Bills/Electricity"`` and the tokens are ``["Bills", "/", "Elec",
288
+ "tricity"]`` with logprobs ``[-0.02, -0.01, -0.10, -0.01]``, the
289
+ joint logprob is ``-0.14``.
290
+
291
+ This is the most natural confidence measure because:
292
+
293
+ * It captures the **total uncertainty** across all tokens (not just
294
+ the average), so longer values with one uncertain token are correctly
295
+ penalised.
296
+ * ``exp(joint_logprob)`` gives the **joint probability** -- the
297
+ probability the model assigns to the entire value as a whole.
298
+ * It is numerically stable and works well across different tokenisations.
299
+
300
+ Parameters
301
+ ----------
302
+ model:
303
+ Either a litellm model string (e.g. ``"openai/gpt-4.1-mini"``) or a
304
+ callable that takes ``messages`` and returns the full response object
305
+ (must include logprobs).
306
+ field_path:
307
+ Path to the target field in the JSON response, using the syntax of
308
+ ``llm-structured-confidence``: ``"category_name"`` for a top-level
309
+ field, ``"classification.name"`` for a nested field, or
310
+ ``"results[].category"`` for an array of objects.
311
+ response_format:
312
+ JSON schema dict passed to litellm as ``response_format``. Should
313
+ define ``enum`` constraints on the target field for meaningful
314
+ confidence extraction. Required when *model* is a string.
315
+ response_schema:
316
+ Optional Pydantic model or dict schema passed to
317
+ ``extract_logprobs(response_schema=…)`` for enum resolution.
318
+ When provided, ``TopAlternative.resolved_value`` maps token
319
+ prefixes back to full enum values (e.g. ``"Pos"`` -> ``"Positive"``).
320
+ scoring_strategy:
321
+ How to blend correctness and logprob confidence into a single score.
322
+ Defaults to :class:`LinearBlendScoring`.
323
+ answer_field:
324
+ JSON field path used to extract the answer from the response text.
325
+ Defaults to *field_path* (they are usually the same).
326
+ high_confidence_threshold:
327
+ Probability threshold (in ``(0, 1]``) above which a prediction is
328
+ labelled "high confidence" in reflective feedback. Models using
329
+ structured output with enum constraints typically produce
330
+ probabilities above 95%, so this should be set high (e.g. ``0.99``)
331
+ to produce useful feedback gradients. Default ``0.99``.
332
+ low_confidence_threshold:
333
+ Probability threshold (in ``(0, 1)``) below which a *correct*
334
+ prediction is labelled "unreliable" in reflective feedback.
335
+ Default ``0.90``.
336
+ top_logprobs:
337
+ Number of top logprobs to request from the LLM (1-20).
338
+ failure_score:
339
+ Score assigned when an example fails (parse error, API error, etc.).
340
+ max_litellm_workers:
341
+ Concurrency for litellm calls (only used when *model* is a string).
342
+ litellm_batch_completion_kwargs:
343
+ Extra keyword arguments forwarded to every ``litellm.batch_completion``
344
+ call (e.g. ``temperature``, ``max_tokens``).
345
+ """
346
+
347
+ propose_new_texts: ProposalFn | None = None
348
+
349
+ def __init__(
350
+ self,
351
+ model: str | ChatCompletionCallable,
352
+ field_path: str,
353
+ response_format: dict[str, Any] | None = None,
354
+ response_schema: type | dict[str, Any] | None = None,
355
+ scoring_strategy: ScoringStrategy | None = None,
356
+ answer_field: str | None = None,
357
+ high_confidence_threshold: float = 0.99,
358
+ low_confidence_threshold: float = 0.90,
359
+ top_logprobs: int = 5,
360
+ failure_score: float = 0.0,
361
+ max_litellm_workers: int = 10,
362
+ litellm_batch_completion_kwargs: dict[str, Any] | None = None,
363
+ ) -> None:
364
+ if isinstance(model, str):
365
+ import litellm
366
+
367
+ self.litellm = litellm
368
+ if response_format is None:
369
+ raise ValueError(
370
+ "response_format is required when model is a string (LiteLLM path). "
371
+ "Provide a JSON schema with enum constraints for structured classification output."
372
+ )
373
+ self.model = model
374
+ self.field_path = field_path
375
+ self.response_format = response_format
376
+ self.response_schema = response_schema
377
+ self.scoring_strategy: ScoringStrategy = scoring_strategy or LinearBlendScoring(
378
+ low_confidence_threshold=high_confidence_threshold,
379
+ )
380
+ self.answer_field = answer_field or field_path
381
+ self.high_confidence_threshold = high_confidence_threshold
382
+ self.low_confidence_threshold = low_confidence_threshold
383
+ self.top_logprobs = top_logprobs
384
+ self.failure_score = failure_score
385
+ self.max_litellm_workers = max_litellm_workers
386
+ self.litellm_batch_completion_kwargs = litellm_batch_completion_kwargs or {}
387
+
388
+ # ------------------------------------------------------------------
389
+ # evaluate
390
+ # ------------------------------------------------------------------
391
+
392
+ def _process_response(
393
+ self,
394
+ response: Any,
395
+ data: ConfidenceDataInst,
396
+ capture_traces: bool,
397
+ ) -> tuple[ConfidenceRolloutOutput, float, dict[str, float], ConfidenceTrajectory | None]:
398
+ """Extract logprobs, compute score, and build feedback from a single response."""
399
+ from llm_structured_confidence import extract_logprobs
400
+
401
+ try:
402
+ if isinstance(response, Exception):
403
+ raise response
404
+
405
+ response_text = self._extract_text(response)
406
+ parsed_value = _extract_answer_from_json(response_text, self.answer_field)
407
+
408
+ logprob_score: float | None = None
409
+ top_alternatives: list[dict[str, Any]] = []
410
+
411
+ try:
412
+ entries = extract_logprobs(
413
+ response,
414
+ field_path=self.field_path,
415
+ response_schema=self.response_schema,
416
+ )
417
+ if entries:
418
+ fl = entries[0].field_logprob
419
+ logprob_score = fl.joint_logprob
420
+ top_alternatives = [
421
+ {
422
+ "token": alt.token,
423
+ "probability": alt.probability,
424
+ "resolved_value": alt.resolved_value,
425
+ }
426
+ for alt in fl.top_logprobs
427
+ ]
428
+ except Exception:
429
+ logger.debug("Logprob extraction failed for an example", exc_info=True)
430
+
431
+ is_correct = self._check_correctness(parsed_value, data["answer"])
432
+ score = self.scoring_strategy.score(is_correct, logprob_score)
433
+
434
+ except Exception:
435
+ logger.debug("LLM call or parsing failed for an example", exc_info=True)
436
+ response_text = ""
437
+ parsed_value = None
438
+ logprob_score = None
439
+ top_alternatives = []
440
+ is_correct = False
441
+ score = self.failure_score
442
+
443
+ feedback = _build_feedback(
444
+ is_correct=is_correct,
445
+ expected=data["answer"],
446
+ got=parsed_value,
447
+ logprob_score=logprob_score,
448
+ top_alternatives=top_alternatives,
449
+ additional_context=data.get("additional_context", {}),
450
+ high_confidence_prob=self.high_confidence_threshold,
451
+ low_confidence_prob=self.low_confidence_threshold,
452
+ )
453
+
454
+ output: ConfidenceRolloutOutput = {
455
+ "full_assistant_response": response_text,
456
+ "parsed_value": parsed_value,
457
+ "logprob_score": logprob_score,
458
+ }
459
+
460
+ probability = math.exp(logprob_score) if logprob_score is not None else 0.0
461
+ obj_scores = {
462
+ "accuracy": 1.0 if is_correct else 0.0,
463
+ "probability": probability,
464
+ }
465
+
466
+ trajectory = None
467
+ if capture_traces:
468
+ trajectory = {
469
+ "data": data,
470
+ "full_assistant_response": response_text,
471
+ "parsed_value": parsed_value,
472
+ "logprob_score": logprob_score,
473
+ "top_alternatives": top_alternatives,
474
+ "is_correct": is_correct,
475
+ "score": score,
476
+ "feedback": feedback,
477
+ }
478
+
479
+ return output, score, obj_scores, trajectory
480
+
481
+ def evaluate(
482
+ self,
483
+ batch: list[ConfidenceDataInst],
484
+ candidate: dict[str, str],
485
+ capture_traces: bool = False,
486
+ ) -> EvaluationBatch[ConfidenceTrajectory, ConfidenceRolloutOutput]:
487
+ """Run *candidate* on *batch*, extracting logprob confidence.
488
+
489
+ Uses ``litellm.batch_completion`` for parallel LLM calls, then
490
+ post-processes each response to extract logprobs and build feedback.
491
+ """
492
+ system_content = next(iter(candidate.values()))
493
+
494
+ all_messages: list[list[ChatMessage]] = [
495
+ [
496
+ {"role": "system", "content": system_content},
497
+ {"role": "user", "content": data["input"]},
498
+ ]
499
+ for data in batch
500
+ ]
501
+
502
+ if isinstance(self.model, str):
503
+ batch_kwargs: dict[str, Any] = {
504
+ "model": self.model,
505
+ "messages": all_messages,
506
+ "max_workers": self.max_litellm_workers,
507
+ "logprobs": True,
508
+ "top_logprobs": self.top_logprobs,
509
+ **self.litellm_batch_completion_kwargs,
510
+ }
511
+ if self.response_format is not None:
512
+ batch_kwargs["response_format"] = self.response_format
513
+ responses = list(self.litellm.batch_completion(**batch_kwargs))
514
+ else:
515
+ responses: list[Any] = []
516
+ for msgs in all_messages:
517
+ try:
518
+ responses.append(self.model(msgs))
519
+ except Exception as exc:
520
+ responses.append(exc)
521
+
522
+ outputs: list[ConfidenceRolloutOutput] = []
523
+ scores: list[float] = []
524
+ objective_scores_list: list[dict[str, float]] = []
525
+ trajectories: list[ConfidenceTrajectory] | None = [] if capture_traces else None
526
+
527
+ for data, response in zip(batch, responses, strict=True):
528
+ output, score, obj_scores, trajectory = self._process_response(
529
+ response,
530
+ data,
531
+ capture_traces,
532
+ )
533
+ outputs.append(output)
534
+ scores.append(score)
535
+ objective_scores_list.append(obj_scores)
536
+ if trajectories is not None and trajectory is not None:
537
+ trajectories.append(trajectory)
538
+
539
+ return EvaluationBatch(
540
+ outputs=outputs,
541
+ scores=scores,
542
+ trajectories=trajectories,
543
+ objective_scores=objective_scores_list,
544
+ )
545
+
546
+ # ------------------------------------------------------------------
547
+ # make_reflective_dataset
548
+ # ------------------------------------------------------------------
549
+
550
+ def make_reflective_dataset(
551
+ self,
552
+ candidate: dict[str, str],
553
+ eval_batch: EvaluationBatch[ConfidenceTrajectory, ConfidenceRolloutOutput],
554
+ components_to_update: list[str],
555
+ ) -> Mapping[str, Sequence[Mapping[str, Any]]]:
556
+ """Build reflective dataset with confidence-enriched feedback.
557
+
558
+ The feedback tells the reflection LLM *why* the task model was
559
+ uncertain, not just whether it was correct. This enables GEPA to
560
+ evolve prompts that resolve specific ambiguities between categories.
561
+
562
+ Each record in the dataset contains:
563
+
564
+ * **Inputs**: the original user input text.
565
+ * **Generated Outputs**: the model's answer annotated with
566
+ probability.
567
+ * **Feedback**: a diagnosis including the probability, the top
568
+ competing alternatives, and guidance for what the prompt should
569
+ improve.
570
+ """
571
+ assert len(components_to_update) == 1
572
+ comp = components_to_update[0]
573
+
574
+ trajectories = eval_batch.trajectories
575
+ assert trajectories is not None, "Trajectories are required to build a reflective dataset."
576
+
577
+ items: list[ConfidenceReflectiveRecord] = []
578
+ for traj in trajectories:
579
+ generated = traj["parsed_value"] or traj["full_assistant_response"]
580
+ if traj["logprob_score"] is not None:
581
+ probability = math.exp(traj["logprob_score"])
582
+ generated += f" ({probability:.0%} probability)"
583
+
584
+ items.append(
585
+ {
586
+ "Inputs": traj["data"]["input"],
587
+ "Generated Outputs": generated,
588
+ "Feedback": traj["feedback"],
589
+ }
590
+ )
591
+
592
+ if not items:
593
+ raise Exception("No valid predictions found for any module.")
594
+
595
+ return {comp: items}
596
+
597
+ # ------------------------------------------------------------------
598
+ # Private helpers
599
+ # ------------------------------------------------------------------
600
+
601
+ def _extract_text(self, response: Any) -> str:
602
+ """Extract the text content from a response object."""
603
+ if hasattr(response, "choices"):
604
+ return response.choices[0].message.content.strip()
605
+ if isinstance(response, str):
606
+ return response.strip()
607
+ if isinstance(response, dict):
608
+ choices = response.get("choices", [])
609
+ if choices:
610
+ return choices[0].get("message", {}).get("content", "").strip()
611
+ raise TypeError(f"Cannot extract text from response of type {type(response).__name__}")
612
+
613
+ @staticmethod
614
+ def _check_correctness(parsed_value: str | None, expected: str) -> bool:
615
+ """Check if the parsed answer matches the expected answer."""
616
+ if parsed_value is None:
617
+ return False
618
+ return parsed_value.strip().lower() == expected.strip().lower()