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.
- package/README.md +23 -0
- package/dist/archive-artifacts-cli.d.ts +50 -0
- package/dist/archive-artifacts-cli.d.ts.map +1 -0
- package/dist/artifact-archive.d.ts +48 -0
- package/dist/artifact-archive.d.ts.map +1 -0
- package/dist/artifact-pull.d.ts +22 -0
- package/dist/artifact-pull.d.ts.map +1 -0
- package/dist/banner.d.ts +3 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/connectors-cli.d.ts +31 -0
- package/dist/connectors-cli.d.ts.map +1 -0
- package/dist/credentials.d.ts +46 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/csv.d.ts +49 -0
- package/dist/csv.d.ts.map +1 -0
- package/dist/dataset-download.d.ts +6 -0
- package/dist/dataset-download.d.ts.map +1 -0
- package/dist/dataset-edit-rows.d.ts +10 -0
- package/dist/dataset-edit-rows.d.ts.map +1 -0
- package/dist/dataset-upload-snapshot.d.ts +13 -0
- package/dist/dataset-upload-snapshot.d.ts.map +1 -0
- package/dist/daytona-slice-rehearsal.d.ts +89 -0
- package/dist/daytona-slice-rehearsal.d.ts.map +1 -0
- package/dist/daytona-slice.d.ts +106 -0
- package/dist/daytona-slice.d.ts.map +1 -0
- package/dist/deploy-key-merge-core.d.ts +121 -0
- package/dist/deploy-key-merge-core.d.ts.map +1 -0
- package/dist/diff-comments-cli.d.ts +12 -0
- package/dist/diff-comments-cli.d.ts.map +1 -0
- package/dist/diff-comments-cli.js +21 -2
- package/dist/egress-allowlist-cli.d.ts +23 -0
- package/dist/egress-allowlist-cli.d.ts.map +1 -0
- package/dist/egress-policy.d.ts +108 -0
- package/dist/egress-policy.d.ts.map +1 -0
- package/dist/error-response.d.ts +9 -0
- package/dist/error-response.d.ts.map +1 -0
- package/dist/file-parser.d.ts +5 -0
- package/dist/file-parser.d.ts.map +1 -0
- package/dist/gepa-engine-dispatch.d.ts +9 -0
- package/dist/gepa-engine-dispatch.d.ts.map +1 -0
- package/dist/gepa-engine-dispatch.js +307 -0
- package/dist/gepa-python-command.d.ts +6 -0
- package/dist/gepa-python-command.d.ts.map +1 -0
- package/dist/gepa-python-command.js +26 -0
- package/dist/gepa-python-paths.d.ts +6 -0
- package/dist/gepa-python-paths.d.ts.map +1 -0
- package/dist/gepa-python-paths.js +42 -0
- package/dist/git-credential.d.ts +69 -0
- package/dist/git-credential.d.ts.map +1 -0
- package/dist/git-recovery-environment.d.ts +31 -0
- package/dist/git-recovery-environment.d.ts.map +1 -0
- package/dist/github-setup.d.ts +122 -0
- package/dist/github-setup.d.ts.map +1 -0
- package/dist/global-flags.d.ts +12 -0
- package/dist/global-flags.d.ts.map +1 -0
- package/dist/help.d.ts +46 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +93 -25
- package/dist/hosted-boot.d.ts +273 -0
- package/dist/hosted-boot.d.ts.map +1 -0
- package/dist/hosted-bootstrap-rehearsal.d.ts +86 -0
- package/dist/hosted-bootstrap-rehearsal.d.ts.map +1 -0
- package/dist/hosted-bootstrap.d.ts +188 -0
- package/dist/hosted-bootstrap.d.ts.map +1 -0
- package/dist/hosted-broker-server.d.ts +50 -0
- package/dist/hosted-broker-server.d.ts.map +1 -0
- package/dist/hosted-git-http-server.d.ts +36 -0
- package/dist/hosted-git-http-server.d.ts.map +1 -0
- package/dist/hosted-harness-claude.d.ts +195 -0
- package/dist/hosted-harness-claude.d.ts.map +1 -0
- package/dist/hosted-harness-opencode.d.ts +227 -0
- package/dist/hosted-harness-opencode.d.ts.map +1 -0
- package/dist/hosted-harness.d.ts +118 -0
- package/dist/hosted-harness.d.ts.map +1 -0
- package/dist/hosted-harvest.d.ts +68 -0
- package/dist/hosted-harvest.d.ts.map +1 -0
- package/dist/hosted-headless.d.ts +72 -0
- package/dist/hosted-headless.d.ts.map +1 -0
- package/dist/hosted-loop-lifecycle.d.ts +206 -0
- package/dist/hosted-loop-lifecycle.d.ts.map +1 -0
- package/dist/hosted-loop.d.ts +170 -0
- package/dist/hosted-loop.d.ts.map +1 -0
- package/dist/hosted-run-event-sink.d.ts +222 -0
- package/dist/hosted-run-event-sink.d.ts.map +1 -0
- package/dist/hosted-runtime-assets.d.ts +186 -0
- package/dist/hosted-runtime-assets.d.ts.map +1 -0
- package/dist/hosted-session-cli.d.ts +258 -0
- package/dist/hosted-session-cli.d.ts.map +1 -0
- package/dist/hosted-skill-staging.d.ts +73 -0
- package/dist/hosted-skill-staging.d.ts.map +1 -0
- package/dist/http.d.ts +8 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +119 -129
- package/dist/instruction-set-gepa-launch.d.ts +3 -0
- package/dist/instruction-set-gepa-launch.d.ts.map +1 -0
- package/dist/instruction-set-gepa-launch.js +15 -0
- package/dist/instruction-set-loader.d.ts +6 -0
- package/dist/instruction-set-loader.d.ts.map +1 -0
- package/dist/instruction-set-loader.js +59 -0
- package/dist/instruction-set-manifest.d.ts +14 -0
- package/dist/instruction-set-manifest.d.ts.map +1 -0
- package/dist/instruction-set-manifest.js +162 -0
- package/dist/instruction-sets-cli.d.ts +40 -0
- package/dist/instruction-sets-cli.d.ts.map +1 -0
- package/dist/instruction-sets-cli.js +361 -0
- package/dist/json-response.d.ts +4 -0
- package/dist/json-response.d.ts.map +1 -0
- package/dist/jsonl-stream.d.ts +8 -0
- package/dist/jsonl-stream.d.ts.map +1 -0
- package/dist/kill-switch-cli.d.ts +30 -0
- package/dist/kill-switch-cli.d.ts.map +1 -0
- package/dist/loopback-serve.d.ts +25 -0
- package/dist/loopback-serve.d.ts.map +1 -0
- package/dist/manifests-cli.d.ts +22 -0
- package/dist/manifests-cli.d.ts.map +1 -0
- package/dist/markdown-report-input.d.ts +7 -0
- package/dist/markdown-report-input.d.ts.map +1 -0
- package/dist/markdown-report-input.js +15 -1
- package/dist/merge-job.d.ts +155 -0
- package/dist/merge-job.d.ts.map +1 -0
- package/dist/model-configs-cli.d.ts +19 -0
- package/dist/model-configs-cli.d.ts.map +1 -0
- package/dist/model-configs-cli.js +104 -0
- package/dist/optimization-export-cli.d.ts +19 -0
- package/dist/optimization-export-cli.d.ts.map +1 -0
- package/dist/optimizations-list-cli.d.ts +20 -0
- package/dist/optimizations-list-cli.d.ts.map +1 -0
- package/dist/optimizations-promote-cli.d.ts +8 -0
- package/dist/optimizations-promote-cli.d.ts.map +1 -0
- package/dist/optimizations-promote-cli.js +34 -0
- package/dist/option-validation.d.ts +15 -0
- package/dist/option-validation.d.ts.map +1 -0
- package/dist/preview-runtime.d.ts +63 -0
- package/dist/preview-runtime.d.ts.map +1 -0
- package/dist/prompt-draft-push.d.ts +60 -0
- package/dist/prompt-draft-push.d.ts.map +1 -0
- package/dist/prompt-label-cli.d.ts +11 -0
- package/dist/prompt-label-cli.d.ts.map +1 -0
- package/dist/prompt-label-cli.js +29 -0
- package/dist/prompt-length-wire.d.ts +28 -0
- package/dist/prompt-length-wire.d.ts.map +1 -0
- package/dist/prompt-length-wire.js +2 -2
- package/dist/prompt-report-cli.d.ts +10 -0
- package/dist/prompt-report-cli.d.ts.map +1 -0
- package/dist/prompt-report-cli.js +2 -2
- package/dist/prompt-summary-table.d.ts +15 -0
- package/dist/prompt-summary-table.d.ts.map +1 -0
- package/dist/prompt-summary-table.js +6 -0
- package/dist/registration-tag-warning.d.ts +32 -0
- package/dist/registration-tag-warning.d.ts.map +1 -0
- package/dist/report-comments-cli.d.ts +16 -0
- package/dist/report-comments-cli.d.ts.map +1 -0
- package/dist/report-markdown-blankness.d.ts +2 -0
- package/dist/report-markdown-blankness.d.ts.map +1 -0
- package/dist/report-markdown-blankness.js +6 -0
- package/dist/report-replacement-warning.d.ts +17 -0
- package/dist/report-replacement-warning.d.ts.map +1 -0
- package/dist/report-replacement-warning.js +31 -0
- package/dist/repository-backup-core.d.ts +225 -0
- package/dist/repository-backup-core.d.ts.map +1 -0
- package/dist/repository-recovery-manifest.d.ts +83 -0
- package/dist/repository-recovery-manifest.d.ts.map +1 -0
- package/dist/run-event-digest.d.ts +74 -0
- package/dist/run-event-digest.d.ts.map +1 -0
- package/dist/runner-dir-verify.d.ts +66 -0
- package/dist/runner-dir-verify.d.ts.map +1 -0
- package/dist/runner-instruction-set-contract.d.ts +24 -0
- package/dist/runner-instruction-set-contract.d.ts.map +1 -0
- package/dist/runner-instruction-set-contract.js +50 -0
- package/dist/sandbox-hygiene.d.ts +45 -0
- package/dist/sandbox-hygiene.d.ts.map +1 -0
- package/dist/sandbox-provider.d.ts +193 -0
- package/dist/sandbox-provider.d.ts.map +1 -0
- package/dist/scorer-draft-push.d.ts +50 -0
- package/dist/scorer-draft-push.d.ts.map +1 -0
- package/dist/scorers-cli.d.ts +20 -0
- package/dist/scorers-cli.d.ts.map +1 -0
- package/dist/scorers-cli.js +22 -0
- package/dist/scorers-verify-parity-bridge.d.ts +16 -0
- package/dist/scorers-verify-parity-bridge.d.ts.map +1 -0
- package/dist/scorers-verify-parity-bridge.js +90 -0
- package/dist/scorers-verify-parity.d.ts +81 -0
- package/dist/scorers-verify-parity.d.ts.map +1 -0
- package/dist/scorers-verify-parity.js +502 -0
- package/dist/scores-accept-cli.d.ts +21 -0
- package/dist/scores-accept-cli.d.ts.map +1 -0
- package/dist/secret-redaction.d.ts +47 -0
- package/dist/secret-redaction.d.ts.map +1 -0
- package/dist/session-timeline.d.ts +54 -0
- package/dist/session-timeline.d.ts.map +1 -0
- package/dist/setup-prompt.d.ts +5 -0
- package/dist/setup-prompt.d.ts.map +1 -0
- package/dist/skill-installer.d.ts +68 -0
- package/dist/skill-installer.d.ts.map +1 -0
- package/dist/skilled-proposer-launch.d.ts +7 -0
- package/dist/skilled-proposer-launch.d.ts.map +1 -0
- package/dist/skilled-proposer-launch.js +60 -0
- package/dist/smoke.d.ts +102 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/start-intent.d.ts +12 -0
- package/dist/start-intent.d.ts.map +1 -0
- package/dist/task-assignment-manifest.d.ts +15 -0
- package/dist/task-assignment-manifest.d.ts.map +1 -0
- package/dist/task-create-error.d.ts +18 -0
- package/dist/task-create-error.d.ts.map +1 -0
- package/dist/team-connectors-cli.d.ts +29 -0
- package/dist/team-connectors-cli.d.ts.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vercel-sandbox-provider.d.ts +156 -0
- package/dist/vercel-sandbox-provider.d.ts.map +1 -0
- package/dist/workbench-cli.d.ts +233 -0
- package/dist/workbench-cli.d.ts.map +1 -0
- package/dist/workspace-sync.d.ts +207 -0
- package/dist/workspace-sync.d.ts.map +1 -0
- package/dist/workspace.d.ts +92 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/zip-draft-push.d.ts +55 -0
- package/dist/zip-draft-push.d.ts.map +1 -0
- package/package.json +15 -2
- package/requirements/README.md +138 -0
- package/requirements/skilled-proposer.in +66 -0
- package/requirements/skilled-proposer.lock +265 -0
- package/scripts/build-cli-dist.mjs +30 -0
- package/scripts/ensure-skilled-proposer-venv.mjs +5 -0
- package/scripts/orizu-source-checkout.d.mts +1 -0
- package/scripts/orizu-source-checkout.mjs +10 -0
- package/scripts/refresh-skilled-proposer-lock.mjs +256 -0
- package/scripts/vendor-gepa-python.mjs +187 -4
- package/src/diff-comments-cli.ts +41 -3
- package/src/gepa-engine-dispatch.ts +340 -0
- package/src/gepa-python-command.ts +31 -0
- package/src/gepa-python-paths.ts +56 -0
- package/src/help.ts +95 -25
- package/src/index.ts +131 -166
- package/src/instruction-set-gepa-launch.ts +28 -0
- package/src/instruction-set-loader.ts +37 -0
- package/src/instruction-set-manifest.ts +120 -0
- package/src/instruction-sets-cli.ts +306 -0
- package/src/markdown-report-input.ts +19 -1
- package/src/model-configs-cli.ts +119 -0
- package/src/optimizations-promote-cli.ts +41 -0
- package/src/prompt-label-cli.ts +55 -0
- package/src/prompt-length-wire.ts +1 -1
- package/src/prompt-report-cli.ts +2 -2
- package/src/prompt-summary-table.ts +12 -0
- package/src/report-markdown-blankness.ts +6 -0
- package/src/report-replacement-warning.ts +35 -0
- package/src/runner-instruction-set-contract.ts +64 -0
- package/src/scorers-cli.ts +40 -0
- package/src/scorers-verify-parity-bridge.ts +90 -0
- package/src/scorers-verify-parity.ts +564 -0
- package/src/skilled-proposer-launch.ts +89 -0
- package/src/skilled-proposer-venv-manager.mjs +757 -0
- package/tsconfig.json +2 -0
- package/vendor/gepa-python/LICENSE +7 -0
- package/vendor/gepa-python/manifest.json +107 -0
- package/vendor/gepa-python/src/gepa/__init__.py +22 -0
- package/vendor/gepa-python/src/gepa/adapters/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/__init__.py +1 -0
- package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/__init__.py +26 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/confidence_adapter.py +618 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/scoring.py +206 -0
- package/vendor/gepa-python/src/gepa/adapters/default_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/default_adapter/default_adapter.py +206 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/dspy_adapter.py +525 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/instruction_proposal.py +500 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/__init__.py +6 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/full_program_adapter.py +269 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/__init__.py +56 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/__init__.py +11 -0
- package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/langchain_adapter.py +261 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/__init__.py +37 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_adapter.py +693 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_client.py +364 -0
- package/vendor/gepa-python/src/gepa/adapters/optimize_anything_adapter/optimize_anything_adapter.py +879 -0
- package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- package/vendor/gepa-python/src/gepa/api.py +468 -0
- package/vendor/gepa-python/src/gepa/core/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/core/adapter.py +227 -0
- package/vendor/gepa-python/src/gepa/core/callbacks.py +551 -0
- package/vendor/gepa-python/src/gepa/core/data_loader.py +74 -0
- package/vendor/gepa-python/src/gepa/core/engine.py +1025 -0
- package/vendor/gepa-python/src/gepa/core/result.py +271 -0
- package/vendor/gepa-python/src/gepa/core/state.py +706 -0
- package/vendor/gepa-python/src/gepa/examples/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/examples/aime.py +24 -0
- package/vendor/gepa-python/src/gepa/examples/anymaths-bench/eval_default.py +111 -0
- package/vendor/gepa-python/src/gepa/examples/anymaths-bench/train_anymaths.py +177 -0
- package/vendor/gepa-python/src/gepa/examples/mcp_adapter/__init__.py +4 -0
- package/vendor/gepa-python/src/gepa/examples/mcp_adapter/mcp_optimization_example.py +456 -0
- package/vendor/gepa-python/src/gepa/examples/rag_adapter/__init__.py +9 -0
- package/vendor/gepa-python/src/gepa/examples/rag_adapter/rag_optimization.py +824 -0
- package/vendor/gepa-python/src/gepa/examples/terminal-bench/train_terminus.py +161 -0
- package/vendor/gepa-python/src/gepa/gepa_utils.py +117 -0
- package/vendor/gepa-python/src/gepa/gskill/__init__.py +1 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/cost_tracker.py +194 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code.py +1117 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code_skills.py +613 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/mini_swe_agent.py +440 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/experiment_logger.py +367 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/swe_fitness_fn.py +209 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/swe_harness.py +352 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/train_optimize_anything.py +830 -0
- package/vendor/gepa-python/src/gepa/image.py +104 -0
- package/vendor/gepa-python/src/gepa/lm.py +261 -0
- package/vendor/gepa-python/src/gepa/logging/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/logging/experiment_tracker.py +457 -0
- package/vendor/gepa-python/src/gepa/logging/logger.py +75 -0
- package/vendor/gepa-python/src/gepa/logging/utils.py +130 -0
- package/vendor/gepa-python/src/gepa/optimize_anything.py +1701 -0
- package/vendor/gepa-python/src/gepa/proposer/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/proposer/base.py +53 -0
- package/vendor/gepa-python/src/gepa/proposer/merge.py +403 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/base.py +64 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflection_lm.py +178 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflective_mutation.py +641 -0
- package/vendor/gepa-python/src/gepa/py.typed +0 -0
- package/vendor/gepa-python/src/gepa/strategies/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/strategies/acceptance.py +66 -0
- package/vendor/gepa-python/src/gepa/strategies/batch_sampler.py +103 -0
- package/vendor/gepa-python/src/gepa/strategies/candidate_selector.py +82 -0
- package/vendor/gepa-python/src/gepa/strategies/component_selector.py +36 -0
- package/vendor/gepa-python/src/gepa/strategies/eval_policy.py +64 -0
- package/vendor/gepa-python/src/gepa/strategies/instruction_proposal.py +153 -0
- package/vendor/gepa-python/src/gepa/strategies/proposal_sampling.py +128 -0
- package/vendor/gepa-python/src/gepa/strategies/proposal_selection.py +84 -0
- package/vendor/gepa-python/src/gepa/utils/__init__.py +63 -0
- package/vendor/gepa-python/src/gepa/utils/code_execution.py +626 -0
- package/vendor/gepa-python/src/gepa/utils/stdio_capture.py +145 -0
- package/vendor/gepa-python/src/gepa/utils/stop_condition.py +230 -0
- package/vendor/gepa-python/src/gepa/visualization.py +359 -0
- package/vendor/orizu-gepa/pyproject.toml +18 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/__init__.py +9 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/__main__.py +5 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/adapter.py +138 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/callbacks.py +666 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/cli.py +7 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/engine.py +269 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/instruction_set_loader.py +52 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/preflight.py +64 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/reflection.py +186 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/runtime.py +721 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/skilled_proposer_bridge.py +381 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/stop_conditions.py +55 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/translator.py +203 -0
- package/vendor/orizu-gepa-python/pyproject.toml +1 -1
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +1 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/client.py +52 -7
- package/vendor/orizu-gepa-python/src/orizu_gepa/local_log.py +52 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +10 -5
- package/vendor/orizu-gepa-python/src/orizu_gepa/reflection.py +323 -68
- package/vendor/orizu-gepa-python/src/orizu_gepa/runner.py +207 -13
- package/vendor/skills/orizu-cli/SKILL.md +3 -1
- package/vendor/skills/orizu-cli/references/cli-reference.md +85 -1
- package/vendor/skills/orizu-cli/references/migrate-existing-gepa-setup.md +303 -0
- package/vendor/skills/orizu-cli/references/optimization-reports.md +1 -1
- package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +26 -1
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +113 -10
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import dspy
|
|
6
|
+
from dspy.adapters.types.base_type import Type
|
|
7
|
+
|
|
8
|
+
from gepa.core.adapter import ProposalFn
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Type alias for reflective examples
|
|
14
|
+
ReflectiveExample = dict[str, Any]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GenerateEnhancedMultimodalInstructionFromFeedback(dspy.Signature):
|
|
18
|
+
"""I provided an assistant with instructions to perform a task involving visual content, but the assistant's performance needs improvement based on the examples and feedback below.
|
|
19
|
+
|
|
20
|
+
Your task is to write a better instruction for the assistant that addresses the specific issues identified in the feedback, with particular attention to how visual and textual information should be analyzed and integrated.
|
|
21
|
+
|
|
22
|
+
## Analysis Steps:
|
|
23
|
+
1. **Read the inputs carefully** and identify both the visual and textual input formats, understanding how they work together
|
|
24
|
+
2. **Read all the assistant responses and corresponding feedback** to understand what went wrong with visual analysis, text processing, or their integration
|
|
25
|
+
3. **Identify visual analysis patterns** - what visual features, relationships, or details are important for this task
|
|
26
|
+
4. **Identify domain-specific knowledge** about both visual and textual aspects, as this information may not be available to the assistant in the future
|
|
27
|
+
5. **Look for successful visual-textual integration strategies** and include these patterns in the instruction
|
|
28
|
+
6. **Address specific visual analysis issues** mentioned in the feedback
|
|
29
|
+
|
|
30
|
+
## Instruction Requirements:
|
|
31
|
+
- **Clear task definition** explaining how to process both visual and textual inputs
|
|
32
|
+
- **Visual analysis guidance** specific to this task (what to look for, how to describe, what features matter)
|
|
33
|
+
- **Integration strategies** for combining visual observations with textual information
|
|
34
|
+
- **Domain-specific knowledge** about visual concepts, terminology, or relationships
|
|
35
|
+
- **Error prevention guidance** for common visual analysis mistakes shown in the feedback
|
|
36
|
+
- **Precise, actionable language** for both visual and textual processing
|
|
37
|
+
|
|
38
|
+
Focus on creating an instruction that helps the assistant properly analyze visual content, integrate it with textual information, and avoid the specific visual analysis mistakes shown in the examples."""
|
|
39
|
+
|
|
40
|
+
current_instruction = dspy.InputField(
|
|
41
|
+
desc="The current instruction that was provided to the assistant to perform the multimodal task"
|
|
42
|
+
)
|
|
43
|
+
examples_with_feedback = dspy.InputField(
|
|
44
|
+
desc="Task examples with visual content showing inputs, assistant outputs, and feedback. "
|
|
45
|
+
"Pay special attention to feedback about visual analysis accuracy, visual-textual integration, "
|
|
46
|
+
"and any domain-specific visual knowledge that the assistant missed."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
improved_instruction = dspy.OutputField(
|
|
50
|
+
desc="A better instruction for the assistant that addresses visual analysis issues, provides "
|
|
51
|
+
"clear guidance on how to process and integrate visual and textual information, includes "
|
|
52
|
+
"necessary visual domain knowledge, and prevents the visual analysis mistakes shown in the examples."
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SingleComponentMultiModalProposer(dspy.Module):
|
|
57
|
+
"""
|
|
58
|
+
dspy.Module for proposing improved instructions based on feedback.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self):
|
|
62
|
+
super().__init__()
|
|
63
|
+
self.propose_instruction = dspy.Predict(GenerateEnhancedMultimodalInstructionFromFeedback)
|
|
64
|
+
|
|
65
|
+
def forward(self, current_instruction: str, reflective_dataset: list[ReflectiveExample]) -> str:
|
|
66
|
+
"""
|
|
67
|
+
Generate an improved instruction based on current instruction and feedback examples.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
current_instruction: The current instruction that needs improvement
|
|
71
|
+
reflective_dataset: List of examples with inputs, outputs, and feedback
|
|
72
|
+
May contain dspy.Image objects in inputs
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
str: Improved instruction text
|
|
76
|
+
"""
|
|
77
|
+
# Format examples with enhanced pattern recognition
|
|
78
|
+
formatted_examples, image_map = self._format_examples_with_pattern_analysis(reflective_dataset)
|
|
79
|
+
|
|
80
|
+
# Build kwargs for the prediction call
|
|
81
|
+
predict_kwargs = {
|
|
82
|
+
"current_instruction": current_instruction,
|
|
83
|
+
"examples_with_feedback": formatted_examples,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Create a rich multimodal examples_with_feedback that includes both text and images
|
|
87
|
+
predict_kwargs["examples_with_feedback"] = self._create_multimodal_examples(formatted_examples, image_map)
|
|
88
|
+
|
|
89
|
+
# Use current dspy LM settings (GEPA will pass reflection_lm via context)
|
|
90
|
+
result = self.propose_instruction(**predict_kwargs)
|
|
91
|
+
|
|
92
|
+
return result.improved_instruction
|
|
93
|
+
|
|
94
|
+
def _format_examples_with_pattern_analysis(
|
|
95
|
+
self, reflective_dataset: list[ReflectiveExample]
|
|
96
|
+
) -> tuple[str, dict[int, list[Type]]]:
|
|
97
|
+
"""
|
|
98
|
+
Format examples with pattern analysis and feedback categorization.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
tuple: (formatted_text_with_patterns, image_map)
|
|
102
|
+
"""
|
|
103
|
+
# First, use the existing proven formatting approach
|
|
104
|
+
formatted_examples, image_map = self._format_examples_for_instruction_generation(reflective_dataset)
|
|
105
|
+
|
|
106
|
+
# Enhanced analysis: categorize feedback patterns
|
|
107
|
+
feedback_analysis = self._analyze_feedback_patterns(reflective_dataset)
|
|
108
|
+
|
|
109
|
+
# Add pattern analysis to the formatted examples
|
|
110
|
+
if feedback_analysis["summary"]:
|
|
111
|
+
pattern_summary = self._create_pattern_summary(feedback_analysis)
|
|
112
|
+
enhanced_examples = f"{pattern_summary}\n\n{formatted_examples}"
|
|
113
|
+
return enhanced_examples, image_map
|
|
114
|
+
|
|
115
|
+
return formatted_examples, image_map
|
|
116
|
+
|
|
117
|
+
def _analyze_feedback_patterns(self, reflective_dataset: list[ReflectiveExample]) -> dict[str, Any]:
|
|
118
|
+
"""
|
|
119
|
+
Analyze feedback patterns to provide better context for instruction generation.
|
|
120
|
+
|
|
121
|
+
Categorizes feedback into:
|
|
122
|
+
- Error patterns: Common mistakes and their types
|
|
123
|
+
- Success patterns: What worked well and should be preserved/emphasized
|
|
124
|
+
- Domain knowledge gaps: Missing information that should be included
|
|
125
|
+
- Task-specific guidance: Specific requirements or edge cases
|
|
126
|
+
"""
|
|
127
|
+
analysis = {
|
|
128
|
+
"error_patterns": [],
|
|
129
|
+
"success_patterns": [],
|
|
130
|
+
"domain_knowledge_gaps": [],
|
|
131
|
+
"task_specific_guidance": [],
|
|
132
|
+
"summary": "",
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# Simple pattern recognition - could be enhanced further
|
|
136
|
+
for example in reflective_dataset:
|
|
137
|
+
feedback = example.get("Feedback", "").lower()
|
|
138
|
+
|
|
139
|
+
# Identify error patterns
|
|
140
|
+
if any(error_word in feedback for error_word in ["incorrect", "wrong", "error", "failed", "missing"]):
|
|
141
|
+
analysis["error_patterns"].append(feedback)
|
|
142
|
+
|
|
143
|
+
# Identify success patterns
|
|
144
|
+
if any(
|
|
145
|
+
success_word in feedback for success_word in ["correct", "good", "accurate", "well", "successfully"]
|
|
146
|
+
):
|
|
147
|
+
analysis["success_patterns"].append(feedback)
|
|
148
|
+
|
|
149
|
+
# Identify domain knowledge needs
|
|
150
|
+
if any(
|
|
151
|
+
knowledge_word in feedback
|
|
152
|
+
for knowledge_word in ["should know", "domain", "specific", "context", "background"]
|
|
153
|
+
):
|
|
154
|
+
analysis["domain_knowledge_gaps"].append(feedback)
|
|
155
|
+
|
|
156
|
+
# Create summary if patterns were found
|
|
157
|
+
if any(analysis[key] for key in ["error_patterns", "success_patterns", "domain_knowledge_gaps"]):
|
|
158
|
+
analysis["summary"] = (
|
|
159
|
+
f"Patterns identified: {len(analysis['error_patterns'])} error(s), {len(analysis['success_patterns'])} success(es), {len(analysis['domain_knowledge_gaps'])} knowledge gap(s)"
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
return analysis
|
|
163
|
+
|
|
164
|
+
def _create_pattern_summary(self, feedback_analysis: dict[str, Any]) -> str:
|
|
165
|
+
"""Create a summary of feedback patterns to help guide instruction generation."""
|
|
166
|
+
|
|
167
|
+
summary_parts = ["## Feedback Pattern Analysis\n"]
|
|
168
|
+
|
|
169
|
+
if feedback_analysis["error_patterns"]:
|
|
170
|
+
summary_parts.append(f"**Common Issues Found ({len(feedback_analysis['error_patterns'])} examples):**")
|
|
171
|
+
summary_parts.append("Focus on preventing these types of mistakes in the new instruction.\n")
|
|
172
|
+
|
|
173
|
+
if feedback_analysis["success_patterns"]:
|
|
174
|
+
summary_parts.append(
|
|
175
|
+
f"**Successful Approaches Found ({len(feedback_analysis['success_patterns'])} examples):**"
|
|
176
|
+
)
|
|
177
|
+
summary_parts.append("Build on these successful strategies in the new instruction.\n")
|
|
178
|
+
|
|
179
|
+
if feedback_analysis["domain_knowledge_gaps"]:
|
|
180
|
+
summary_parts.append(
|
|
181
|
+
f"**Domain Knowledge Needs Identified ({len(feedback_analysis['domain_knowledge_gaps'])} examples):**"
|
|
182
|
+
)
|
|
183
|
+
summary_parts.append("Include this specialized knowledge in the new instruction.\n")
|
|
184
|
+
|
|
185
|
+
return "\n".join(summary_parts)
|
|
186
|
+
|
|
187
|
+
def _format_examples_for_instruction_generation(
|
|
188
|
+
self, reflective_dataset: list[ReflectiveExample]
|
|
189
|
+
) -> tuple[str, dict[int, list[Type]]]:
|
|
190
|
+
"""
|
|
191
|
+
Format examples using GEPA's markdown structure while preserving image objects.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
tuple: (formatted_text, image_map) where image_map maps example_index -> list[images]
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
def render_value_with_images(value, level=3, example_images=None):
|
|
198
|
+
if example_images is None:
|
|
199
|
+
example_images = []
|
|
200
|
+
|
|
201
|
+
if isinstance(value, Type):
|
|
202
|
+
image_idx = len(example_images) + 1
|
|
203
|
+
example_images.append(value)
|
|
204
|
+
return f"[IMAGE-{image_idx} - see visual content]\n\n"
|
|
205
|
+
elif isinstance(value, dict):
|
|
206
|
+
s = ""
|
|
207
|
+
for k, v in value.items():
|
|
208
|
+
s += f"{'#' * level} {k}\n"
|
|
209
|
+
s += render_value_with_images(v, min(level + 1, 6), example_images)
|
|
210
|
+
if not value:
|
|
211
|
+
s += "\n"
|
|
212
|
+
return s
|
|
213
|
+
elif isinstance(value, list | tuple):
|
|
214
|
+
s = ""
|
|
215
|
+
for i, item in enumerate(value):
|
|
216
|
+
s += f"{'#' * level} Item {i + 1}\n"
|
|
217
|
+
s += render_value_with_images(item, min(level + 1, 6), example_images)
|
|
218
|
+
if not value:
|
|
219
|
+
s += "\n"
|
|
220
|
+
return s
|
|
221
|
+
else:
|
|
222
|
+
return f"{str(value).strip()}\n\n"
|
|
223
|
+
|
|
224
|
+
def convert_sample_to_markdown_with_images(sample, example_num):
|
|
225
|
+
example_images = []
|
|
226
|
+
s = f"# Example {example_num}\n"
|
|
227
|
+
|
|
228
|
+
for key, val in sample.items():
|
|
229
|
+
s += f"## {key}\n"
|
|
230
|
+
s += render_value_with_images(val, level=3, example_images=example_images)
|
|
231
|
+
|
|
232
|
+
return s, example_images
|
|
233
|
+
|
|
234
|
+
formatted_parts = []
|
|
235
|
+
image_map = {}
|
|
236
|
+
|
|
237
|
+
for i, example_data in enumerate(reflective_dataset):
|
|
238
|
+
formatted_example, example_images = convert_sample_to_markdown_with_images(example_data, i + 1)
|
|
239
|
+
formatted_parts.append(formatted_example)
|
|
240
|
+
|
|
241
|
+
if example_images:
|
|
242
|
+
image_map[i] = example_images
|
|
243
|
+
|
|
244
|
+
formatted_text = "\n\n".join(formatted_parts)
|
|
245
|
+
|
|
246
|
+
if image_map:
|
|
247
|
+
total_images = sum(len(imgs) for imgs in image_map.values())
|
|
248
|
+
formatted_text = (
|
|
249
|
+
f"The examples below include visual content ({total_images} images total). "
|
|
250
|
+
"Please analyze both the text and visual elements when suggesting improvements.\n\n" + formatted_text
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
return formatted_text, image_map
|
|
254
|
+
|
|
255
|
+
def _create_multimodal_examples(self, formatted_text: str, image_map: dict[int, list[Type]]) -> Any:
|
|
256
|
+
"""
|
|
257
|
+
Create a multimodal input that contains both text and images for the reflection LM.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
formatted_text: The formatted text with image placeholders
|
|
261
|
+
image_map: Dictionary mapping example_index -> list[images] for structured access
|
|
262
|
+
"""
|
|
263
|
+
if not image_map:
|
|
264
|
+
return formatted_text
|
|
265
|
+
|
|
266
|
+
# Collect all images from all examples
|
|
267
|
+
all_images = []
|
|
268
|
+
for example_images in image_map.values():
|
|
269
|
+
all_images.extend(example_images)
|
|
270
|
+
|
|
271
|
+
multimodal_content = [formatted_text]
|
|
272
|
+
multimodal_content.extend(all_images)
|
|
273
|
+
return multimodal_content
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class MultiModalInstructionProposer(ProposalFn):
|
|
277
|
+
"""GEPA-compatible multimodal instruction proposer.
|
|
278
|
+
|
|
279
|
+
This class handles multimodal inputs (like dspy.Image) during GEPA optimization by using
|
|
280
|
+
a single-component proposer for each component that needs to be updated.
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
def __init__(self):
|
|
284
|
+
self.single_proposer = SingleComponentMultiModalProposer()
|
|
285
|
+
|
|
286
|
+
def __call__(
|
|
287
|
+
self,
|
|
288
|
+
candidate: dict[str, str],
|
|
289
|
+
reflective_dataset: dict[str, list[ReflectiveExample]],
|
|
290
|
+
components_to_update: list[str],
|
|
291
|
+
) -> dict[str, str]:
|
|
292
|
+
"""GEPA-compatible proposal function.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
candidate: Current component name -> instruction mapping
|
|
296
|
+
reflective_dataset: Component name -> list of reflective examples
|
|
297
|
+
components_to_update: List of component names to update
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
dict: Component name -> new instruction mapping
|
|
301
|
+
"""
|
|
302
|
+
updated_components = {}
|
|
303
|
+
|
|
304
|
+
for component_name in components_to_update:
|
|
305
|
+
if component_name in candidate and component_name in reflective_dataset:
|
|
306
|
+
current_instruction = candidate[component_name]
|
|
307
|
+
component_reflective_data = reflective_dataset[component_name]
|
|
308
|
+
|
|
309
|
+
# Call the single-instruction proposer.
|
|
310
|
+
#
|
|
311
|
+
# In the future, proposals could consider multiple components instructions,
|
|
312
|
+
# instead of just the current instruction, for more holistic instruction proposals.
|
|
313
|
+
new_instruction = self.single_proposer(
|
|
314
|
+
current_instruction=current_instruction, reflective_dataset=component_reflective_data
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
updated_components[component_name] = new_instruction
|
|
318
|
+
|
|
319
|
+
return updated_components
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class GenerateImprovedToolModuleDescriptionsFromFeedback(dspy.Signature):
|
|
323
|
+
"""I provided an assistant with predictor instructions and tool descriptions,
|
|
324
|
+
but its performance needs improvement based on the examples_with_feedback below.
|
|
325
|
+
|
|
326
|
+
Your task is to propose better predictor instructions, tool descriptions, and tool argument descriptions that address the issues shown in these examples.
|
|
327
|
+
Focus on reinforcing patterns that clearly improve the assistant's performance on similar tasks, rather than rewriting everything from scratch unless necessary.
|
|
328
|
+
These components are progressively optimized - refine only what needs to change.
|
|
329
|
+
|
|
330
|
+
Analyze the examples_with_feedback to identify success and failure patterns, and write improved instructions and descriptions at their appropriate level of abstraction and/or specificity,
|
|
331
|
+
so that each layer plays a clear, complementary role without unnecessary repetition or verbosity unless redundancy clearly helps the assistant's performance.
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
current_predictor_instruction = dspy.InputField(desc="Current instruction guiding the predictor")
|
|
335
|
+
current_tools = dspy.InputField(annotation=list[dspy.Tool], desc="Available tools with their complete schemas")
|
|
336
|
+
examples_with_feedback = dspy.InputField(desc="Execution examples with feedback showing successes and failures")
|
|
337
|
+
|
|
338
|
+
improved_predictor_instruction: str | None = dspy.OutputField(
|
|
339
|
+
desc="Improved instruction for the predictor", default=None
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
class ToolProposer(ProposalFn):
|
|
344
|
+
"""Proposer for optimizing tool-using module configurations.
|
|
345
|
+
|
|
346
|
+
Supports two types of modules:
|
|
347
|
+
- Tool modules (1 predictor): Optimizes predictor instruction and tool descriptions
|
|
348
|
+
- ReAct modules (2 predictors): Jointly optimizes react instruction, extract instruction, and tool descriptions
|
|
349
|
+
|
|
350
|
+
Uses dynamic signature generation to create output fields for each tool and parameter,
|
|
351
|
+
enabling the reflection LM to optimize all components cohesively based on execution feedback.
|
|
352
|
+
|
|
353
|
+
This joint optimization approach allows the LM to see how instructions and tool descriptions
|
|
354
|
+
work together, leading to more coherent improvements than optimizing each component separately.
|
|
355
|
+
"""
|
|
356
|
+
|
|
357
|
+
def __call__(
|
|
358
|
+
self,
|
|
359
|
+
candidate: dict[str, str],
|
|
360
|
+
reflective_dataset: dict[str, list[ReflectiveExample]],
|
|
361
|
+
components_to_update: list[str],
|
|
362
|
+
) -> dict[str, str]:
|
|
363
|
+
"""Optimize tool-using module components.
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
candidate: Current component name -> JSON config mapping
|
|
367
|
+
reflective_dataset: Component name -> list of reflective examples
|
|
368
|
+
components_to_update: List of tool-using module component names to update
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
dict: Mapping of component names to improved JSON configs
|
|
372
|
+
"""
|
|
373
|
+
|
|
374
|
+
updated_components = {}
|
|
375
|
+
|
|
376
|
+
for module_key in components_to_update:
|
|
377
|
+
if module_key not in candidate or module_key not in reflective_dataset:
|
|
378
|
+
logger.debug(
|
|
379
|
+
f"Skipping {module_key}: not in candidate={module_key not in candidate}, not in "
|
|
380
|
+
"reflective_dataset={module_key not in reflective_dataset}"
|
|
381
|
+
)
|
|
382
|
+
continue
|
|
383
|
+
current_module_config = json.loads(candidate[module_key])
|
|
384
|
+
|
|
385
|
+
# Predictor keys: ReAct has 2 predictors (react + extract)
|
|
386
|
+
predictor_keys = [k for k, v in current_module_config.items() if isinstance(v, str)]
|
|
387
|
+
primary_predictor_key = predictor_keys[0]
|
|
388
|
+
extract_predictor_key = predictor_keys[1] if len(predictor_keys) > 1 else None
|
|
389
|
+
|
|
390
|
+
# Reconstruct Tool objects from JSON (func is placeholder since it can't be serialized)
|
|
391
|
+
current_tools_dict = current_module_config.get("tools", {})
|
|
392
|
+
tools_list = []
|
|
393
|
+
for tool_name, tool_info in current_tools_dict.items():
|
|
394
|
+
tool = dspy.Tool(
|
|
395
|
+
func=lambda *args, **kwargs: None, # Placeholder - Tool requires Callable, but only schema is used
|
|
396
|
+
name=tool_name,
|
|
397
|
+
desc=tool_info.get("desc", ""),
|
|
398
|
+
)
|
|
399
|
+
tool.args = tool_info.get("args", {})
|
|
400
|
+
tools_list.append(tool)
|
|
401
|
+
|
|
402
|
+
# Build dynamic signature with tool-specific output fields
|
|
403
|
+
signature = GenerateImprovedToolModuleDescriptionsFromFeedback
|
|
404
|
+
|
|
405
|
+
for tool in tools_list:
|
|
406
|
+
tool_name = tool.name
|
|
407
|
+
tool_info = current_tools_dict[tool_name]
|
|
408
|
+
|
|
409
|
+
signature = signature.append(
|
|
410
|
+
f"improved_tool_{tool_name}_desc",
|
|
411
|
+
dspy.OutputField(desc=f"Improved description of tool '{tool_name}'", default=None),
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
for arg_name in tool_info["args"].keys():
|
|
415
|
+
signature = signature.append(
|
|
416
|
+
f"improved_tool_{tool_name}_arg_{arg_name}_desc",
|
|
417
|
+
dspy.OutputField(
|
|
418
|
+
desc=f"Improved description of the argument '{arg_name}' of tool '{tool_name}'",
|
|
419
|
+
default=None,
|
|
420
|
+
),
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
kwargs = {
|
|
424
|
+
"current_predictor_instruction": current_module_config[primary_predictor_key],
|
|
425
|
+
"current_tools": tools_list,
|
|
426
|
+
"examples_with_feedback": self._format_examples(reflective_dataset[module_key]),
|
|
427
|
+
}
|
|
428
|
+
# If module has extract predictor, add extract fields
|
|
429
|
+
if extract_predictor_key is not None:
|
|
430
|
+
signature = signature.append(
|
|
431
|
+
"current_extract_instruction", dspy.InputField(desc="Current instruction for extraction predictor")
|
|
432
|
+
)
|
|
433
|
+
signature = signature.append(
|
|
434
|
+
"improved_extract_instruction",
|
|
435
|
+
dspy.OutputField(desc="Improved instruction for extraction", default=None),
|
|
436
|
+
)
|
|
437
|
+
kwargs["current_extract_instruction"] = current_module_config[extract_predictor_key]
|
|
438
|
+
|
|
439
|
+
propose_descriptions = dspy.Predict(signature)
|
|
440
|
+
result = propose_descriptions(**kwargs)
|
|
441
|
+
|
|
442
|
+
# Build improved config (reflection LM returns None to keep original, or new text)
|
|
443
|
+
improved_module_config = {}
|
|
444
|
+
|
|
445
|
+
if result.improved_predictor_instruction is not None:
|
|
446
|
+
improved_module_config[primary_predictor_key] = result.improved_predictor_instruction
|
|
447
|
+
|
|
448
|
+
if extract_predictor_key is not None and result.improved_extract_instruction is not None:
|
|
449
|
+
improved_module_config[extract_predictor_key] = result.improved_extract_instruction
|
|
450
|
+
|
|
451
|
+
improved_module_config["tools"] = {}
|
|
452
|
+
for tool_name, tool_info in current_tools_dict.items():
|
|
453
|
+
# Update tool description if LM proposed a change
|
|
454
|
+
improved_tool_desc = getattr(result, f"improved_tool_{tool_name}_desc", None)
|
|
455
|
+
if improved_tool_desc is not None:
|
|
456
|
+
tool_info["desc"] = improved_tool_desc
|
|
457
|
+
|
|
458
|
+
# Update arg descriptions if LM proposed changes
|
|
459
|
+
for arg_name in tool_info["args"].keys():
|
|
460
|
+
improved_tool_arg_desc = getattr(result, f"improved_tool_{tool_name}_arg_{arg_name}_desc", None)
|
|
461
|
+
if improved_tool_arg_desc is not None:
|
|
462
|
+
tool_info["args"][arg_name]["description"] = improved_tool_arg_desc
|
|
463
|
+
|
|
464
|
+
improved_module_config["tools"][tool_name] = tool_info
|
|
465
|
+
|
|
466
|
+
updated_components[module_key] = json.dumps(improved_module_config, indent=2)
|
|
467
|
+
|
|
468
|
+
return updated_components
|
|
469
|
+
|
|
470
|
+
def _format_examples(self, reflective_dataset: list[ReflectiveExample]) -> str:
|
|
471
|
+
"""Format reflective examples using GEPA's markdown structure."""
|
|
472
|
+
|
|
473
|
+
def render_value(value, level=3):
|
|
474
|
+
if isinstance(value, dict):
|
|
475
|
+
s = ""
|
|
476
|
+
for key, val in value.items():
|
|
477
|
+
s += f"{'#' * level} {key}\n"
|
|
478
|
+
s += render_value(val, min(level + 1, 6))
|
|
479
|
+
if not value:
|
|
480
|
+
s += "\n"
|
|
481
|
+
return s
|
|
482
|
+
if isinstance(value, list | tuple):
|
|
483
|
+
s = ""
|
|
484
|
+
for index, item in enumerate(value):
|
|
485
|
+
s += f"{'#' * level} Item {index + 1}\n"
|
|
486
|
+
s += render_value(item, min(level + 1, 6))
|
|
487
|
+
if not value:
|
|
488
|
+
s += "\n"
|
|
489
|
+
return s
|
|
490
|
+
return f"{str(value).strip()}\n\n"
|
|
491
|
+
|
|
492
|
+
def convert_sample_to_markdown(sample, example_num):
|
|
493
|
+
s = f"# Example {example_num}\n"
|
|
494
|
+
for key, val in sample.items():
|
|
495
|
+
s += f"## {key}\n"
|
|
496
|
+
s += render_value(val, level=3)
|
|
497
|
+
return s
|
|
498
|
+
|
|
499
|
+
formatted_parts = [convert_sample_to_markdown(example, i + 1) for i, example in enumerate(reflective_dataset)]
|
|
500
|
+
return "\n\n".join(formatted_parts)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Copyright (c) 2025 Lakshya A Agrawal and the GEPA contributors
|
|
2
|
+
# https://github.com/gepa-ai/gepa
|
|
3
|
+
|
|
4
|
+
from typing import Any, ClassVar
|
|
5
|
+
|
|
6
|
+
import yaml
|
|
7
|
+
|
|
8
|
+
from gepa.proposer.reflective_mutation.base import Signature
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DSPyProgramProposalSignature(Signature):
|
|
12
|
+
prompt_template = """I am trying to solve a task using the DSPy framework. Here's a comprehensive overview of DSPy concepts to guide your improvements:
|
|
13
|
+
|
|
14
|
+
Signatures:
|
|
15
|
+
- Signatures define tasks declaratively through input/output fields and explicit instructions.
|
|
16
|
+
- They serve as blueprints for what the LM needs to accomplish.
|
|
17
|
+
|
|
18
|
+
Signature Types:
|
|
19
|
+
- Simple signatures: Specified as strings like "input1, ..., inputN -> output1, ..., outputM" (e.g., "topic -> tweet").
|
|
20
|
+
- Typed signatures: Create a subclass of dspy.Signature with a detailed docstring that includes task instructions, common pitfalls, edge cases, and successful strategies. Define fields using dspy.InputField(desc="...", type=...) and dspy.OutputField(desc="...", type=...) with pydantic types such as str, List[str], Literal["option1", "option2"], or custom classes.
|
|
21
|
+
|
|
22
|
+
Modules:
|
|
23
|
+
- Modules specify __how__ to solve the task defined by a signature.
|
|
24
|
+
- They are composable units inspired by PyTorch layers, using language models to process inputs and produce outputs.
|
|
25
|
+
- Inputs are provided as keyword arguments matching the signature's input fields.
|
|
26
|
+
- Outputs are returned as dspy.Prediction objects containing the signature's output fields.
|
|
27
|
+
- Key built-in modules:
|
|
28
|
+
- dspy.Predict(signature): Performs a single LM call to directly generate the outputs from the inputs.
|
|
29
|
+
- dspy.ChainOfThought(signature): Performs a single LM call that first generates a reasoning chain, then the outputs (adds a 'reasoning' field to the prediction).
|
|
30
|
+
- Other options: dspy.ReAct(signature) for reasoning and acting, or custom chains.
|
|
31
|
+
- Custom modules: Subclass dspy.Module. In __init__, compose sub-modules (e.g., other Predict or ChainOfThought instances). In forward(self, **kwargs), define the data flow: call sub-modules, execute Python logic if needed, and return dspy.Prediction with the output fields.
|
|
32
|
+
|
|
33
|
+
Example Usage:
|
|
34
|
+
```
|
|
35
|
+
# Simple signature
|
|
36
|
+
simple_signature = "question -> answer"
|
|
37
|
+
|
|
38
|
+
# Typed signature
|
|
39
|
+
class ComplexSignature(dspy.Signature):
|
|
40
|
+
\"\"\"
|
|
41
|
+
<Detailed instructions for completing the task: Include steps, common pitfalls, edge cases, successful strategies. Include domain knowledge...>
|
|
42
|
+
\"\"\"
|
|
43
|
+
question: str = dspy.InputField(desc="The question to answer")
|
|
44
|
+
answer: str = dspy.OutputField(desc="Concise and accurate answer")
|
|
45
|
+
|
|
46
|
+
# Built-in module
|
|
47
|
+
simple_program = dspy.Predict(simple_signature) # or dspy.ChainOfThought(ComplexSignature)
|
|
48
|
+
|
|
49
|
+
# Custom module
|
|
50
|
+
class ComplexModule(dspy.Module):
|
|
51
|
+
def __init__(self):
|
|
52
|
+
self.reasoner = dspy.ChainOfThought("question -> intermediate_answer")
|
|
53
|
+
self.finalizer = dspy.Predict("intermediate_answer -> answer")
|
|
54
|
+
|
|
55
|
+
def forward(self, question: str):
|
|
56
|
+
intermediate = self.reasoner(question=question)
|
|
57
|
+
final = self.finalizer(intermediate_answer=intermediate.intermediate_answer)
|
|
58
|
+
return dspy.Prediction(answer=final.answer, reasoning=intermediate.reasoning) # dspy.ChainOfThought returns 'reasoning' in addition to the signature outputs.
|
|
59
|
+
|
|
60
|
+
complex_program = ComplexModule()
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
DSPy Improvement Strategies:
|
|
64
|
+
1. Analyze traces for LM overload: If a single call struggles (e.g., skips steps or hallucinates), decompose into multi-step modules with ChainOfThought or custom logic for stepwise reasoning.
|
|
65
|
+
2. Avoid over-decomposition: If the program is too fragmented, consolidate related steps into fewer modules for efficiency and coherence.
|
|
66
|
+
3. Refine signatures: Enhance docstrings with actionable guidance from traces—address specific errors, incorporate domain knowledge, document edge cases, and suggest reasoning patterns. Ensure docstrings are self-contained, as the LM won't have access external traces during runtime.
|
|
67
|
+
4. Balance LM and Python: Use Python for symbolic/logical operations (e.g., loops, conditionals); delegate complex reasoning or generation to LM calls.
|
|
68
|
+
5. Incorporate control flow: Add loops, conditionals, sub-modules in custom modules if the task requires iteration (e.g., multi-turn reasoning, selection, voting, etc.).
|
|
69
|
+
6. Leverage LM strengths: For code-heavy tasks, define signatures with 'code' outputs, extract and execute the generated code in the module's forward pass.
|
|
70
|
+
|
|
71
|
+
Here's my current code:
|
|
72
|
+
```
|
|
73
|
+
<curr_program>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Here is the execution trace of the current code on example inputs, their outputs, and detailed feedback on improvements:
|
|
77
|
+
```
|
|
78
|
+
<dataset_with_feedback>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Assignment:
|
|
82
|
+
- Think step-by-step: First, deeply analyze the current code, traces, and feedback to identify failure modes, strengths, and opportunities.
|
|
83
|
+
- Create a concise checklist (3-7 bullets) outlining your high-level improvement plan, focusing on conceptual changes (e.g., "Decompose step X into a multi-stage module").
|
|
84
|
+
- Then, propose a drop-in replacement code that instantiates an improved 'program' object.
|
|
85
|
+
- Ensure the code is modular, efficient, and directly addresses feedback.
|
|
86
|
+
- Output everything in a single code block using triple backticks—no additional explanations, comments, or language markers outside the block.
|
|
87
|
+
- The code must be a valid, self-contained Python script with all necessary imports, definitions, and assignment to 'program'.
|
|
88
|
+
|
|
89
|
+
Output Format:
|
|
90
|
+
- Start with the checklist in plain text (3-7 short bullets).
|
|
91
|
+
- Follow immediately with one code block in triple backticks containing the complete Python code, including assigning a `program` object."""
|
|
92
|
+
input_keys: ClassVar[list[str]] = ["curr_program", "dataset_with_feedback"]
|
|
93
|
+
output_keys: ClassVar[list[str]] = ["new_program"]
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def prompt_renderer(cls, input_dict: dict[str, Any]) -> str:
|
|
97
|
+
curr_program = input_dict["curr_program"]
|
|
98
|
+
if not isinstance(curr_program, str):
|
|
99
|
+
raise TypeError("curr_program must be a string")
|
|
100
|
+
|
|
101
|
+
dataset = input_dict["dataset_with_feedback"]
|
|
102
|
+
if not isinstance(dataset, list):
|
|
103
|
+
raise TypeError("dataset_with_feedback must be a list")
|
|
104
|
+
|
|
105
|
+
def format_samples(samples):
|
|
106
|
+
# Serialize the samples list to YAML for concise, structured representation
|
|
107
|
+
yaml_str = yaml.dump(samples, sort_keys=False, default_flow_style=False, indent=2)
|
|
108
|
+
# Optionally, wrap or label it for clarity in the prompt
|
|
109
|
+
return yaml_str
|
|
110
|
+
|
|
111
|
+
prompt = cls.prompt_template
|
|
112
|
+
prompt = prompt.replace("<curr_program>", curr_program)
|
|
113
|
+
prompt = prompt.replace("<dataset_with_feedback>", format_samples(dataset))
|
|
114
|
+
return prompt
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def output_extractor(lm_out: str) -> dict[str, str]:
|
|
118
|
+
# Extract ``` blocks
|
|
119
|
+
new_instruction = None
|
|
120
|
+
if lm_out.count("```") >= 2:
|
|
121
|
+
start = lm_out.find("```")
|
|
122
|
+
end = lm_out.rfind("```")
|
|
123
|
+
if start >= end:
|
|
124
|
+
new_instruction = lm_out
|
|
125
|
+
if start == -1 or end == -1:
|
|
126
|
+
new_instruction = lm_out
|
|
127
|
+
else:
|
|
128
|
+
new_instruction = lm_out[start + 3 : end].strip()
|
|
129
|
+
else:
|
|
130
|
+
lm_out = lm_out.strip()
|
|
131
|
+
if lm_out.startswith("```"):
|
|
132
|
+
lm_out = lm_out[3:]
|
|
133
|
+
if lm_out.endswith("```"):
|
|
134
|
+
lm_out = lm_out[:-3]
|
|
135
|
+
new_instruction = lm_out
|
|
136
|
+
|
|
137
|
+
return {"new_program": new_instruction}
|