gatewaysdk 0.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gatewaysdk/__init__.py +540 -0
- gatewaysdk/adapter/__init__.py +15 -0
- gatewaysdk/adapter/base.py +94 -0
- gatewaysdk/adapter/messages.py +270 -0
- gatewaysdk/adapter/triplet.py +1026 -0
- gatewaysdk/algorithm/__init__.py +39 -0
- gatewaysdk/algorithm/apo/__init__.py +5 -0
- gatewaysdk/algorithm/apo/apo.py +898 -0
- gatewaysdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
- gatewaysdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
- gatewaysdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
- gatewaysdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
- gatewaysdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
- gatewaysdk/algorithm/base.py +262 -0
- gatewaysdk/algorithm/decorator.py +264 -0
- gatewaysdk/algorithm/evals/__init__.py +7 -0
- gatewaysdk/algorithm/evals/evals.py +217 -0
- gatewaysdk/algorithm/fast.py +250 -0
- gatewaysdk/algorithm/gepa/__init__.py +61 -0
- gatewaysdk/algorithm/gepa/adapter.py +495 -0
- gatewaysdk/algorithm/gepa/gepa.py +570 -0
- gatewaysdk/algorithm/gepa/lib/__init__.py +18 -0
- gatewaysdk/algorithm/gepa/lib/adapters/README.md +12 -0
- gatewaysdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
- gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +268 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +699 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
- gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
- gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- gatewaysdk/algorithm/gepa/lib/api.py +382 -0
- gatewaysdk/algorithm/gepa/lib/core/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/core/adapter.py +180 -0
- gatewaysdk/algorithm/gepa/lib/core/data_loader.py +74 -0
- gatewaysdk/algorithm/gepa/lib/core/engine.py +379 -0
- gatewaysdk/algorithm/gepa/lib/core/result.py +233 -0
- gatewaysdk/algorithm/gepa/lib/core/state.py +636 -0
- gatewaysdk/algorithm/gepa/lib/examples/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/examples/aime.py +24 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
- gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
- gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
- gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
- gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +456 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +820 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
- gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
- gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
- gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
- gatewaysdk/algorithm/gepa/lib/gepa_utils.py +117 -0
- gatewaysdk/algorithm/gepa/lib/logging/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
- gatewaysdk/algorithm/gepa/lib/logging/logger.py +75 -0
- gatewaysdk/algorithm/gepa/lib/logging/utils.py +103 -0
- gatewaysdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/proposer/base.py +31 -0
- gatewaysdk/algorithm/gepa/lib/proposer/merge.py +357 -0
- gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
- gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
- gatewaysdk/algorithm/gepa/lib/py.typed +0 -0
- gatewaysdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
- gatewaysdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
- gatewaysdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
- gatewaysdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
- gatewaysdk/algorithm/gepa/lib/strategies/instruction_proposal.py +126 -0
- gatewaysdk/algorithm/gepa/lib/utils/__init__.py +10 -0
- gatewaysdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
- gatewaysdk/algorithm/gepa/tracing.py +105 -0
- gatewaysdk/algorithm/utils.py +177 -0
- gatewaysdk/algorithm/verl/__init__.py +5 -0
- gatewaysdk/algorithm/verl/interface.py +202 -0
- gatewaysdk/automations.py +111 -0
- gatewaysdk/benchmark_hub/README.md +88 -0
- gatewaysdk/benchmark_hub/__init__.py +119 -0
- gatewaysdk/benchmark_hub/_archive.py +189 -0
- gatewaysdk/benchmark_hub/_tar.py +6 -0
- gatewaysdk/benchmark_hub/client.py +992 -0
- gatewaysdk/benchmark_hub/dispatch_shard.py +34 -0
- gatewaysdk/benchmark_hub/eval_config.py +20 -0
- gatewaysdk/benchmark_hub/evals.py +351 -0
- gatewaysdk/benchmark_hub/harbor_adapter.py +673 -0
- gatewaysdk/benchmark_hub/path_utils.py +81 -0
- gatewaysdk/benchmark_hub/save_utils.py +101 -0
- gatewaysdk/benchmark_hub/verifiers_adapter.py +327 -0
- gatewaysdk/benchmark_hub/versioning.py +72 -0
- gatewaysdk/build.py +515 -0
- gatewaysdk/cli/__init__.py +58 -0
- gatewaysdk/cli/agent_runner.py +132 -0
- gatewaysdk/cli/http_client.py +115 -0
- gatewaysdk/cli/platform.py +4086 -0
- gatewaysdk/cli/prometheus.py +115 -0
- gatewaysdk/cli/release_gate.py +215 -0
- gatewaysdk/cli/store.py +131 -0
- gatewaysdk/cli/vllm.py +29 -0
- gatewaysdk/client.py +406 -0
- gatewaysdk/config.py +348 -0
- gatewaysdk/connectors/__init__.py +25 -0
- gatewaysdk/connectors/client.py +203 -0
- gatewaysdk/connectors/skill.py +25 -0
- gatewaysdk/connectors/template.py +106 -0
- gatewaysdk/context.py +606 -0
- gatewaysdk/emitter/__init__.py +43 -0
- gatewaysdk/emitter/annotation.py +370 -0
- gatewaysdk/emitter/exception.py +54 -0
- gatewaysdk/emitter/message.py +61 -0
- gatewaysdk/emitter/object.py +117 -0
- gatewaysdk/emitter/reward.py +320 -0
- gatewaysdk/env_var.py +156 -0
- gatewaysdk/environment/__init__.py +108 -0
- gatewaysdk/environment/_bundle.py +281 -0
- gatewaysdk/environment/_harbor.py +276 -0
- gatewaysdk/environment/_materialize.py +97 -0
- gatewaysdk/environment/_tar.py +33 -0
- gatewaysdk/environment/_world.py +346 -0
- gatewaysdk/environment/core.py +527 -0
- gatewaysdk/environment/errors.py +58 -0
- gatewaysdk/environment/runtime.py +150 -0
- gatewaysdk/environment/schema/__init__.py +35 -0
- gatewaysdk/environment/schema/__main__.py +225 -0
- gatewaysdk/environment/schema/_slack_fidelity.py +116 -0
- gatewaysdk/environment/schema/_slack_scenario.py +183 -0
- gatewaysdk/environment/schema/api.py +1628 -0
- gatewaysdk/environment/schema/batch.py +755 -0
- gatewaysdk/environment/schema/compiler.py +615 -0
- gatewaysdk/environment/schema/conform.py +428 -0
- gatewaysdk/environment/schema/connector.py +777 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/handlers.py +17 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/parity.json +28 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/provenance.json +233 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/scope.toml +112 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/world.json +1380 -0
- gatewaysdk/environment/schema/connectors/base.json +28 -0
- gatewaysdk/environment/schema/connectors/custom/handlers.py +18 -0
- gatewaysdk/environment/schema/connectors/custom/world.json +123 -0
- gatewaysdk/environment/schema/connectors/github/handlers.py +81 -0
- gatewaysdk/environment/schema/connectors/github/parity.json +37 -0
- gatewaysdk/environment/schema/connectors/github/provenance.json +134 -0
- gatewaysdk/environment/schema/connectors/github/scope.toml +158 -0
- gatewaysdk/environment/schema/connectors/github/world.json +5869 -0
- gatewaysdk/environment/schema/connectors/google-calendar/handlers.py +23 -0
- gatewaysdk/environment/schema/connectors/google-calendar/world.json +209 -0
- gatewaysdk/environment/schema/connectors/google-drive/handlers.py +18 -0
- gatewaysdk/environment/schema/connectors/google-drive/world.json +286 -0
- gatewaysdk/environment/schema/connectors/jamf/handlers.py +34 -0
- gatewaysdk/environment/schema/connectors/jamf/parity.json +49 -0
- gatewaysdk/environment/schema/connectors/jamf/provenance.json +181 -0
- gatewaysdk/environment/schema/connectors/jamf/scope.toml +128 -0
- gatewaysdk/environment/schema/connectors/jamf/world.json +2218 -0
- gatewaysdk/environment/schema/connectors/jira/handlers.py +28 -0
- gatewaysdk/environment/schema/connectors/jira/world.json +389 -0
- gatewaysdk/environment/schema/connectors/kandji/handlers.py +38 -0
- gatewaysdk/environment/schema/connectors/kandji/parity.json +29 -0
- gatewaysdk/environment/schema/connectors/kandji/provenance.json +152 -0
- gatewaysdk/environment/schema/connectors/kandji/scope.toml +120 -0
- gatewaysdk/environment/schema/connectors/kandji/world.json +765 -0
- gatewaysdk/environment/schema/connectors/linear/handlers.py +20 -0
- gatewaysdk/environment/schema/connectors/linear/world.json +363 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/fidelity.json +45 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/handlers.py +1 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/provenance.json +851 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/scope.md +231 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/teams-types.json +1710 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/world.json +858 -0
- gatewaysdk/environment/schema/connectors/netsuite/handlers.py +32 -0
- gatewaysdk/environment/schema/connectors/netsuite/parity.json +50 -0
- gatewaysdk/environment/schema/connectors/netsuite/provenance.json +137 -0
- gatewaysdk/environment/schema/connectors/netsuite/scope.toml +78 -0
- gatewaysdk/environment/schema/connectors/netsuite/world.json +16243 -0
- gatewaysdk/environment/schema/connectors/salesforce/handlers.py +806 -0
- gatewaysdk/environment/schema/connectors/salesforce/parity.json +46 -0
- gatewaysdk/environment/schema/connectors/salesforce/provenance.json +143 -0
- gatewaysdk/environment/schema/connectors/salesforce/scope.toml +174 -0
- gatewaysdk/environment/schema/connectors/salesforce/world.json +4695 -0
- gatewaysdk/environment/schema/connectors/slack/MODEL.md +236 -0
- gatewaysdk/environment/schema/connectors/slack/capabilities.json +1039 -0
- gatewaysdk/environment/schema/connectors/slack/handlers.py +762 -0
- gatewaysdk/environment/schema/connectors/slack/parity.json +65 -0
- gatewaysdk/environment/schema/connectors/slack/provenance.json +294 -0
- gatewaysdk/environment/schema/connectors/slack/scope.toml +44 -0
- gatewaysdk/environment/schema/connectors/slack/world.json +4993 -0
- gatewaysdk/environment/schema/connectors/workday/handlers.py +75 -0
- gatewaysdk/environment/schema/connectors/workday/parity.json +36 -0
- gatewaysdk/environment/schema/connectors/workday/provenance.json +179 -0
- gatewaysdk/environment/schema/connectors/workday/scope.toml +180 -0
- gatewaysdk/environment/schema/connectors/workday/world.json +806 -0
- gatewaysdk/environment/schema/data.py +593 -0
- gatewaysdk/environment/schema/extract.py +263 -0
- gatewaysdk/environment/schema/host.py +2437 -0
- gatewaysdk/environment/schema/host_surfaces.py +275 -0
- gatewaysdk/environment/schema/platform.py +1272 -0
- gatewaysdk/environment/schema/scaffold.py +250 -0
- gatewaysdk/environment/schema/skill.py +118 -0
- gatewaysdk/environment/schema/skills/agents/connector-template-author.md +202 -0
- gatewaysdk/environment/schema/skills/connector-schema-authoring/CONNECTORS.md +331 -0
- gatewaysdk/environment/schema/skills/connector-schema-authoring/CONVENTIONS.md +100 -0
- gatewaysdk/environment/schema/skills/connector-schema-authoring/SKILL.md +313 -0
- gatewaysdk/environment/schema/skills/world-data-ingestion/ROWS.md +223 -0
- gatewaysdk/environment/schema/skills/world-data-ingestion/SKILL.md +293 -0
- gatewaysdk/environment/schema/skills/worlds-getting-started/SKILL.md +390 -0
- gatewaysdk/environment/schema/slack.py +757 -0
- gatewaysdk/environment/schema/snapshot.py +479 -0
- gatewaysdk/environment/schema/store.py +904 -0
- gatewaysdk/environment/schema/tasks.py +525 -0
- gatewaysdk/environment/schema/tools_world.py +322 -0
- gatewaysdk/environment/schema/validation.py +577 -0
- gatewaysdk/environment/schema/worker.py +78 -0
- gatewaysdk/environment/schema/workers.py +500 -0
- gatewaysdk/environment/schema/world_tests.py +336 -0
- gatewaysdk/environments/__init__.py +24 -0
- gatewaysdk/environments/client.py +486 -0
- gatewaysdk/environments/types.py +318 -0
- gatewaysdk/execution/__init__.py +15 -0
- gatewaysdk/execution/base.py +64 -0
- gatewaysdk/execution/client_server.py +443 -0
- gatewaysdk/execution/events.py +69 -0
- gatewaysdk/execution/inter_process.py +16 -0
- gatewaysdk/execution/shared_memory.py +282 -0
- gatewaysdk/experiments/__init__.py +90 -0
- gatewaysdk/experiments/assignment.py +177 -0
- gatewaysdk/experiments/client.py +877 -0
- gatewaysdk/experiments/exposure.py +222 -0
- gatewaysdk/experiments/types.py +81 -0
- gatewaysdk/importers/__init__.py +49 -0
- gatewaysdk/importers/_normalize.py +91 -0
- gatewaysdk/importers/builder.py +173 -0
- gatewaysdk/importers/client.py +95 -0
- gatewaysdk/importers/langsmith.py +196 -0
- gatewaysdk/importers/recipes.py +249 -0
- gatewaysdk/instrumentation/__init__.py +300 -0
- gatewaysdk/instrumentation/agentops.py +314 -0
- gatewaysdk/instrumentation/agentops_langchain.py +45 -0
- gatewaysdk/instrumentation/base.py +119 -0
- gatewaysdk/instrumentation/litellm.py +83 -0
- gatewaysdk/instrumentation/registry.py +273 -0
- gatewaysdk/instrumentation/vllm.py +81 -0
- gatewaysdk/instrumentation/weave.py +500 -0
- gatewaysdk/integrations/__init__.py +15 -0
- gatewaysdk/integrations/gateway/__init__.py +11 -0
- gatewaysdk/integrations/gateway/client.py +171 -0
- gatewaysdk/integrations/tool_access.py +549 -0
- gatewaysdk/litagent/__init__.py +11 -0
- gatewaysdk/litagent/decorator.py +536 -0
- gatewaysdk/litagent/litagent.py +252 -0
- gatewaysdk/llm_proxy.py +1742 -0
- gatewaysdk/logging.py +370 -0
- gatewaysdk/memory.py +278 -0
- gatewaysdk/personas.py +186 -0
- gatewaysdk/platform/__init__.py +17 -0
- gatewaysdk/platform/builder.py +221 -0
- gatewaysdk/platform/compatibility.py +67 -0
- gatewaysdk/platform/manifest.py +185 -0
- gatewaysdk/platform/orchestrator.py +901 -0
- gatewaysdk/platform/registry.py +122 -0
- gatewaysdk/platform/worker.py +864 -0
- gatewaysdk/replay/__init__.py +1032 -0
- gatewaysdk/replay/pytest.py +56 -0
- gatewaysdk/reward.py +7 -0
- gatewaysdk/run.py +1781 -0
- gatewaysdk/runner/__init__.py +11 -0
- gatewaysdk/runner/agent.py +878 -0
- gatewaysdk/runner/base.py +182 -0
- gatewaysdk/runner/legacy.py +309 -0
- gatewaysdk/security.py +700 -0
- gatewaysdk/semconv.py +170 -0
- gatewaysdk/server.py +399 -0
- gatewaysdk/sessions.py +282 -0
- gatewaysdk/store/__init__.py +45 -0
- gatewaysdk/store/base.py +908 -0
- gatewaysdk/store/client_server.py +2093 -0
- gatewaysdk/store/collection/__init__.py +30 -0
- gatewaysdk/store/collection/base.py +587 -0
- gatewaysdk/store/collection/memory.py +970 -0
- gatewaysdk/store/collection/mongo.py +1412 -0
- gatewaysdk/store/collection_based.py +1823 -0
- gatewaysdk/store/gateway.py +983 -0
- gatewaysdk/store/gateway_listener.py +465 -0
- gatewaysdk/store/listener.py +58 -0
- gatewaysdk/store/memory.py +396 -0
- gatewaysdk/store/mongo.py +165 -0
- gatewaysdk/store/redis_stream.py +517 -0
- gatewaysdk/store/sqlite.py +3 -0
- gatewaysdk/store/threading.py +370 -0
- gatewaysdk/store/utils.py +142 -0
- gatewaysdk/tracer/__init__.py +14 -0
- gatewaysdk/tracer/base.py +286 -0
- gatewaysdk/tracer/dummy.py +106 -0
- gatewaysdk/tracer/otel.py +559 -0
- gatewaysdk/tracing/__init__.py +110 -0
- gatewaysdk/tracing/api.py +808 -0
- gatewaysdk/tracing/attributes.py +9 -0
- gatewaysdk/tracing/context.py +272 -0
- gatewaysdk/tracing/exporters/__init__.py +10 -0
- gatewaysdk/tracing/exporters/gateway.py +228 -0
- gatewaysdk/tracing/identity.py +288 -0
- gatewaysdk/tracing/init.py +620 -0
- gatewaysdk/tracing/instrumentors/__init__.py +15 -0
- gatewaysdk/tracing/instrumentors/claude_agent_sdk.py +766 -0
- gatewaysdk/tracing/instrumentors/instrumentation_principles.md +294 -0
- gatewaysdk/tracing/instrumentors/registry.py +352 -0
- gatewaysdk/tracing/mapping.py +729 -0
- gatewaysdk/tracing/processors.py +393 -0
- gatewaysdk/tracing/push.py +617 -0
- gatewaysdk/tracing/push_models.py +247 -0
- gatewaysdk/tracing/semconv.py +294 -0
- gatewaysdk/tracing/span_builder.py +356 -0
- gatewaysdk/trainer/__init__.py +6 -0
- gatewaysdk/trainer/init_utils.py +263 -0
- gatewaysdk/trainer/legacy.py +359 -0
- gatewaysdk/trainer/registry.py +12 -0
- gatewaysdk/trainer/trainer.py +638 -0
- gatewaysdk/types/__init__.py +63 -0
- gatewaysdk/types/core.py +556 -0
- gatewaysdk/types/resources.py +204 -0
- gatewaysdk/types/tracer.py +515 -0
- gatewaysdk/types/tracing.py +162 -0
- gatewaysdk/users.py +251 -0
- gatewaysdk/utils/__init__.py +1 -0
- gatewaysdk/utils/id.py +18 -0
- gatewaysdk/utils/metrics.py +1025 -0
- gatewaysdk/utils/otel.py +550 -0
- gatewaysdk/utils/otlp.py +556 -0
- gatewaysdk/utils/redact.py +22 -0
- gatewaysdk/utils/server_launcher.py +1045 -0
- gatewaysdk/utils/system_snapshot.py +90 -0
- gatewaysdk/verl/__init__.py +8 -0
- gatewaysdk/verl/__main__.py +6 -0
- gatewaysdk/verl/async_server.py +46 -0
- gatewaysdk/verl/config.yaml +27 -0
- gatewaysdk/verl/daemon.py +1154 -0
- gatewaysdk/verl/dataset.py +44 -0
- gatewaysdk/verl/entrypoint.py +248 -0
- gatewaysdk/verl/trainer.py +549 -0
- gatewaysdk/world_browser.py +748 -0
- gatewaysdk/world_data.py +453 -0
- gatewaysdk/world_sessions.py +978 -0
- gatewaysdk/world_tasks.py +285 -0
- gatewaysdk/world_tools.py +115 -0
- gatewaysdk/worlds.py +639 -0
- gatewaysdk-0.3.2.dist-info/METADATA +236 -0
- gatewaysdk-0.3.2.dist-info/RECORD +376 -0
- gatewaysdk-0.3.2.dist-info/WHEEL +4 -0
- gatewaysdk-0.3.2.dist-info/entry_points.txt +5 -0
- gatewaysdk-0.3.2.dist-info/licenses/LICENSE +19 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Eval-results dir layout + resume matching.
|
|
2
|
+
|
|
3
|
+
Ported (stdlib-only) from Prime Intellect's ``verifiers`` (MIT). A run's results
|
|
4
|
+
live at ``<output_dir>/evals/<env_id>--<model>/<run_id>/`` holding
|
|
5
|
+
``results.jsonl`` + ``metadata.json``. Resume finds the newest *incomplete* run
|
|
6
|
+
whose saved config matches, counting completed rollouts per example (clamped to
|
|
7
|
+
``rollouts_per_example``) — so a crashed run continues instead of restarting.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import uuid
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any, Dict, Optional, Union
|
|
15
|
+
|
|
16
|
+
from .save_utils import (
|
|
17
|
+
METADATA_FILE,
|
|
18
|
+
RESULTS_FILE,
|
|
19
|
+
load_metadata,
|
|
20
|
+
load_outputs,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _model_slug(model: str) -> str:
|
|
25
|
+
return model.replace("/", "--")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_results_path(output_dir: Union[str, Path], env_id: str, model: str) -> Path:
|
|
29
|
+
"""A fresh results dir for a run: ``<output_dir>/evals/<env>--<model>/<uuid8>``."""
|
|
30
|
+
run_id = uuid.uuid4().hex[:8]
|
|
31
|
+
return Path(output_dir) / "evals" / f"{env_id}--{_model_slug(model)}" / run_id
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_valid_eval_results_path(path: Union[str, Path]) -> bool:
|
|
35
|
+
"""A results dir is valid iff it has BOTH results.jsonl and metadata.json."""
|
|
36
|
+
p = Path(path)
|
|
37
|
+
return (p / RESULTS_FILE).exists() and (p / METADATA_FILE).exists()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def count_saved_rollouts(results_path: Union[str, Path], rollouts_per_example: int) -> Dict[Any, int]:
|
|
41
|
+
"""Completed rollouts per ``example_id``, clamped to ``rollouts_per_example``."""
|
|
42
|
+
counts: Dict[Any, int] = {}
|
|
43
|
+
rpe = rollouts_per_example if rollouts_per_example > 0 else 1
|
|
44
|
+
for row in load_outputs(results_path):
|
|
45
|
+
eid = row.get("example_id")
|
|
46
|
+
if eid is None:
|
|
47
|
+
continue
|
|
48
|
+
counts[eid] = min(counts.get(eid, 0) + 1, rpe)
|
|
49
|
+
return counts
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def find_latest_incomplete_eval_results_path(
|
|
53
|
+
output_dir: Union[str, Path],
|
|
54
|
+
env_id: str,
|
|
55
|
+
model: str,
|
|
56
|
+
num_examples: int,
|
|
57
|
+
rollouts_per_example: int,
|
|
58
|
+
shuffle: bool = False,
|
|
59
|
+
shuffle_seed: Optional[int] = None,
|
|
60
|
+
) -> Optional[Path]:
|
|
61
|
+
"""Newest results dir (by mtime) whose saved metadata matches this config AND
|
|
62
|
+
that still has fewer saved rollouts than requested — or None."""
|
|
63
|
+
root = Path(output_dir) / "evals" / f"{env_id}--{_model_slug(model)}"
|
|
64
|
+
if not root.exists():
|
|
65
|
+
return None
|
|
66
|
+
candidates = [d for d in root.iterdir() if d.is_dir() and is_valid_eval_results_path(d)]
|
|
67
|
+
candidates.sort(key=lambda d: d.stat().st_mtime, reverse=True)
|
|
68
|
+
|
|
69
|
+
total = num_examples * rollouts_per_example if num_examples > 0 else None
|
|
70
|
+
for c in candidates:
|
|
71
|
+
meta = load_metadata(c)
|
|
72
|
+
if meta.get("env_id") != env_id or meta.get("model") != model:
|
|
73
|
+
continue
|
|
74
|
+
if meta.get("rollouts_per_example") != rollouts_per_example:
|
|
75
|
+
continue
|
|
76
|
+
if meta.get("shuffle") != shuffle or meta.get("shuffle_seed") != (shuffle_seed):
|
|
77
|
+
continue
|
|
78
|
+
saved = sum(count_saved_rollouts(c, rollouts_per_example).values())
|
|
79
|
+
if total is None or saved < total:
|
|
80
|
+
return c
|
|
81
|
+
return None
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Local eval-results persistence: ``results.jsonl`` + ``metadata.json``.
|
|
2
|
+
|
|
3
|
+
Ported (stdlib-only) from Prime Intellect's ``verifiers`` (MIT) save layer so a
|
|
4
|
+
``bench eval`` run writes the same on-disk contract that powers resume + upload.
|
|
5
|
+
``save_metadata`` is atomic (temp file in the same dir + ``os.replace``) and drops
|
|
6
|
+
the non-serializable ``path_to_save``/``date`` keys, matching verifiers.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import tempfile
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, Dict, List, Union
|
|
16
|
+
|
|
17
|
+
RESULTS_FILE = "results.jsonl"
|
|
18
|
+
METADATA_FILE = "metadata.json"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def make_serializable(obj: Any) -> Any:
|
|
22
|
+
"""Best-effort JSON-serializable copy: recurse dict/list, stringify the rest."""
|
|
23
|
+
try:
|
|
24
|
+
json.dumps(obj)
|
|
25
|
+
return obj
|
|
26
|
+
except (TypeError, ValueError):
|
|
27
|
+
if isinstance(obj, dict):
|
|
28
|
+
return {k: make_serializable(v) for k, v in obj.items()}
|
|
29
|
+
if isinstance(obj, (list, tuple)):
|
|
30
|
+
return [make_serializable(v) for v in obj]
|
|
31
|
+
return str(obj)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def save_outputs(
|
|
35
|
+
results_path: Union[str, Path],
|
|
36
|
+
rows: List[Dict[str, Any]],
|
|
37
|
+
mode: str = "a",
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Append (or overwrite) rollout rows to ``results.jsonl``, one per line."""
|
|
40
|
+
f = Path(results_path) / RESULTS_FILE
|
|
41
|
+
f.parent.mkdir(parents=True, exist_ok=True)
|
|
42
|
+
with open(f, mode) as fh:
|
|
43
|
+
for row in rows:
|
|
44
|
+
fh.write(json.dumps(make_serializable(row)) + "\n")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def load_outputs(results_path: Union[str, Path]) -> List[Dict[str, Any]]:
|
|
48
|
+
"""Read ``results.jsonl``, skipping blank/malformed/non-dict lines (a torn last
|
|
49
|
+
line from a crash is silently ignored — resume-safe)."""
|
|
50
|
+
f = Path(results_path) / RESULTS_FILE
|
|
51
|
+
if not f.exists():
|
|
52
|
+
return []
|
|
53
|
+
out: List[Dict[str, Any]] = []
|
|
54
|
+
for line in f.read_text().splitlines():
|
|
55
|
+
line = line.strip()
|
|
56
|
+
if not line:
|
|
57
|
+
continue
|
|
58
|
+
try:
|
|
59
|
+
row = json.loads(line)
|
|
60
|
+
except Exception:
|
|
61
|
+
continue
|
|
62
|
+
if isinstance(row, dict):
|
|
63
|
+
out.append(row)
|
|
64
|
+
return out
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def save_metadata(results_path: Union[str, Path], metadata: Dict[str, Any]) -> None:
|
|
68
|
+
"""Atomically write ``metadata.json`` (temp in same dir + ``os.replace``),
|
|
69
|
+
dropping ``path_to_save``/``date`` (non-serializable, per verifiers)."""
|
|
70
|
+
p = Path(results_path)
|
|
71
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
72
|
+
meta = dict(metadata)
|
|
73
|
+
meta.pop("path_to_save", None)
|
|
74
|
+
meta.pop("date", None)
|
|
75
|
+
fd, tmp = tempfile.mkstemp(dir=str(p), suffix=".tmp")
|
|
76
|
+
try:
|
|
77
|
+
with os.fdopen(fd, "w") as fh:
|
|
78
|
+
json.dump(make_serializable(meta), fh, indent=2)
|
|
79
|
+
os.replace(tmp, str(p / METADATA_FILE))
|
|
80
|
+
finally:
|
|
81
|
+
if os.path.exists(tmp):
|
|
82
|
+
os.unlink(tmp)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def load_metadata(results_path: Union[str, Path]) -> Dict[str, Any]:
|
|
86
|
+
"""Read ``metadata.json`` ({} if absent/malformed)."""
|
|
87
|
+
f = Path(results_path) / METADATA_FILE
|
|
88
|
+
if not f.exists():
|
|
89
|
+
return {}
|
|
90
|
+
try:
|
|
91
|
+
data = json.loads(f.read_text())
|
|
92
|
+
return data if isinstance(data, dict) else {}
|
|
93
|
+
except Exception:
|
|
94
|
+
return {}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def validate_resume_metadata(saved_metadata: Dict[str, Any], requested_num_examples: int) -> None:
|
|
98
|
+
"""On resume, ``num_examples`` may only grow — a smaller request is an error."""
|
|
99
|
+
saved_n = saved_metadata.get("num_examples")
|
|
100
|
+
if isinstance(saved_n, int) and saved_n > 0 and requested_num_examples > 0 and requested_num_examples < saved_n:
|
|
101
|
+
raise ValueError(f"cannot resume: requested num_examples {requested_num_examples} " f"< saved {saved_n}")
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"""Score a verifiers-format container and harvest into Gateway.
|
|
2
|
+
|
|
3
|
+
`verifiers` (MIT) is the one genuinely open, self-hostable piece of Prime's eval
|
|
4
|
+
stack: ``Environment.evaluate_sync()`` runs the rollout loop against ANY
|
|
5
|
+
OpenAI-compatible client (ours) and scores via the rubric — so we don't reimplement
|
|
6
|
+
rollouts/parsers/scoring. This adapter maps its ``GenerateOutputs`` into our
|
|
7
|
+
version-pinned eval sample shape and pushes it through ``GatewayEvalsClient``.
|
|
8
|
+
|
|
9
|
+
Verified against verifiers ``Environment.evaluate`` →
|
|
10
|
+
``GenerateOutputs{outputs: list[RolloutOutput], metadata}``; each ``RolloutOutput``
|
|
11
|
+
carries ``prompt / completion / answer / reward`` and the named sub-rewards in
|
|
12
|
+
``metrics: dict[str, float]``. ``example_id`` is declared on ``RolloutOutput`` but
|
|
13
|
+
may be absent on rows produced by ``evaluate_sync``; the mapper falls back to a
|
|
14
|
+
positional example index derived from ``metadata.rollouts_per_example``.
|
|
15
|
+
|
|
16
|
+
The verifiers import is lazy (optional dependency); the mappers are pure + tested.
|
|
17
|
+
|
|
18
|
+
NOTE (verifiers v1): this adapter drives the LEGACY v0 API (`load_environment` +
|
|
19
|
+
`Environment.evaluate_sync`), which the v1 release froze — it only keeps working
|
|
20
|
+
with `verifiers<1.0.0` installed. v1 Taskset packages (`verifiers.v1` namespace,
|
|
21
|
+
detected as kind "verifiers-v1" by `detect_env_kind`) are run by the platform
|
|
22
|
+
benchmark runner's verifiers-v1 engine (deploy/benchmark-runner/engines/
|
|
23
|
+
verifiers_v1.py); a v1 in-process path here is a deliberate non-goal until the
|
|
24
|
+
v1 API settles.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import json
|
|
30
|
+
from typing import Any, Dict, List, Optional
|
|
31
|
+
|
|
32
|
+
from .evals import EvalHarvestError, GatewayEvalsClient
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get(obj: Any, key: str, default: Any = None) -> Any:
|
|
36
|
+
"""Read a field from a dict (TypedDict) or an attribute object."""
|
|
37
|
+
if isinstance(obj, dict):
|
|
38
|
+
return obj.get(key, default)
|
|
39
|
+
return getattr(obj, key, default)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _as_text(value: Any) -> Optional[str]:
|
|
43
|
+
if value is None:
|
|
44
|
+
return None
|
|
45
|
+
if isinstance(value, str):
|
|
46
|
+
return value
|
|
47
|
+
try:
|
|
48
|
+
return json.dumps(value, default=str)
|
|
49
|
+
except Exception:
|
|
50
|
+
return str(value)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _rollouts(outputs: Any) -> List[Any]:
|
|
54
|
+
return _get(outputs, "outputs", []) or []
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def samples_from_generate_outputs(outputs: Any) -> List[Dict[str, Any]]:
|
|
58
|
+
"""Map verifiers ``GenerateOutputs`` → our eval-sample dicts. The per-rollout
|
|
59
|
+
``metrics`` (named rubric components) become the multi-reward ``rewards`` map.
|
|
60
|
+
|
|
61
|
+
``rolloutIndex`` is the occurrence of a rollout *within its example*. verifiers'
|
|
62
|
+
``RolloutOutput`` lists ``example_id`` as a field, but rows produced by
|
|
63
|
+
``evaluate_sync`` are not guaranteed to carry it as a top-level key — so when it
|
|
64
|
+
is missing we fall back to the positional example index
|
|
65
|
+
(``i // rollouts_per_example``) instead of letting every id collapse to the string
|
|
66
|
+
``"None"``, which would flatten all rollout indices into one monotonic run across
|
|
67
|
+
the whole batch."""
|
|
68
|
+
rollouts = _rollouts(outputs)
|
|
69
|
+
rpe = int(_get(_get(outputs, "metadata", {}) or {}, "rollouts_per_example", 1) or 1)
|
|
70
|
+
if rpe <= 0:
|
|
71
|
+
rpe = 1
|
|
72
|
+
seen: Dict[str, int] = {}
|
|
73
|
+
samples: List[Dict[str, Any]] = []
|
|
74
|
+
for i, r in enumerate(rollouts):
|
|
75
|
+
raw_example_id = _get(r, "example_id")
|
|
76
|
+
example_id = str(raw_example_id if raw_example_id is not None else i // rpe)
|
|
77
|
+
idx = seen.get(example_id, 0)
|
|
78
|
+
seen[example_id] = idx + 1
|
|
79
|
+
|
|
80
|
+
reward = _get(r, "reward")
|
|
81
|
+
answer = _get(r, "answer")
|
|
82
|
+
sample: Dict[str, Any] = {
|
|
83
|
+
"exampleId": example_id,
|
|
84
|
+
"rolloutIndex": idx,
|
|
85
|
+
"prompt": _as_text(_get(r, "prompt")),
|
|
86
|
+
"completion": _as_text(_get(r, "completion")),
|
|
87
|
+
"answer": answer if isinstance(answer, str) else _as_text(answer),
|
|
88
|
+
"reward": float(reward) if reward is not None else None,
|
|
89
|
+
"score": float(reward) if reward is not None else None,
|
|
90
|
+
"rewards": _get(r, "metrics") or {}, # named sub-rewards
|
|
91
|
+
"info": _get(r, "info") or {},
|
|
92
|
+
}
|
|
93
|
+
samples.append({k: v for k, v in sample.items() if v is not None})
|
|
94
|
+
return samples
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def metrics_from_generate_outputs(outputs: Any) -> Dict[str, Any]:
|
|
98
|
+
"""Aggregate metrics: average reward + average of each named sub-reward."""
|
|
99
|
+
rollouts = _rollouts(outputs)
|
|
100
|
+
rewards = [float(_get(r, "reward")) for r in rollouts if _get(r, "reward") is not None]
|
|
101
|
+
by_metric: Dict[str, List[float]] = {}
|
|
102
|
+
for r in rollouts:
|
|
103
|
+
for name, value in (_get(r, "metrics") or {}).items():
|
|
104
|
+
if isinstance(value, (int, float)):
|
|
105
|
+
by_metric.setdefault(name, []).append(float(value))
|
|
106
|
+
|
|
107
|
+
def _mean(xs: List[float]) -> Optional[float]:
|
|
108
|
+
return sum(xs) / len(xs) if xs else None
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
"n": len(rollouts),
|
|
112
|
+
"avg_reward": _mean(rewards),
|
|
113
|
+
"metrics": {name: _mean(vals) for name, vals in by_metric.items()},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def write_results_artifact(outputs: Any, config: Any, results_path: Any) -> Dict[str, Any]:
|
|
118
|
+
"""Write the verifiers-compatible on-disk artifact for a completed run —
|
|
119
|
+
``results.jsonl`` (raw rollout rows, keyed on ``example_id`` for resume) +
|
|
120
|
+
``metadata.json`` (config + aggregates). ``config`` is an ``EvalConfig``.
|
|
121
|
+
Returns the metadata dict."""
|
|
122
|
+
from .save_utils import save_metadata, save_outputs
|
|
123
|
+
|
|
124
|
+
save_outputs(results_path, _rollouts(outputs), mode="w")
|
|
125
|
+
agg = metrics_from_generate_outputs(outputs)
|
|
126
|
+
metadata: Dict[str, Any] = {
|
|
127
|
+
"env_id": config.env_id,
|
|
128
|
+
"model": config.model,
|
|
129
|
+
"num_examples": config.num_examples,
|
|
130
|
+
"rollouts_per_example": config.rollouts_per_example,
|
|
131
|
+
"shuffle": config.shuffle,
|
|
132
|
+
"shuffle_seed": config.shuffle_seed,
|
|
133
|
+
"n": agg.get("n"),
|
|
134
|
+
"avg_reward": agg.get("avg_reward"),
|
|
135
|
+
"avg_metrics": agg.get("metrics"),
|
|
136
|
+
}
|
|
137
|
+
save_metadata(results_path, metadata)
|
|
138
|
+
return metadata
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _adapt_client(client: Any) -> Any:
|
|
142
|
+
"""Bridge verifiers' client API drift. Older releases take a raw (Async)OpenAI
|
|
143
|
+
client; 0.1.14+ requires its own Client/ClientConfig ("Unsupported client
|
|
144
|
+
type"). Map a raw client's base_url onto a ClientConfig, keyed by the env
|
|
145
|
+
var that holds the matching API key (ClientConfig reads the key from the
|
|
146
|
+
environment by NAME)."""
|
|
147
|
+
try:
|
|
148
|
+
from verifiers.clients import Client # noqa: WPS433 — new-style verifiers only
|
|
149
|
+
from verifiers.types import ClientConfig # noqa: WPS433
|
|
150
|
+
except Exception: # noqa: BLE001 — old verifiers: raw clients accepted
|
|
151
|
+
return client
|
|
152
|
+
if isinstance(client, (Client, ClientConfig)):
|
|
153
|
+
return client
|
|
154
|
+
base_url = str(getattr(client, "base_url", "") or "")
|
|
155
|
+
api_key_var = (
|
|
156
|
+
"OPENAI_API_KEY" if "api.openai.com" in base_url else "OPENROUTER_API_KEY"
|
|
157
|
+
)
|
|
158
|
+
return ClientConfig(
|
|
159
|
+
client_type="openai_chat_completions",
|
|
160
|
+
api_base_url=base_url or "https://openrouter.ai/api/v1",
|
|
161
|
+
api_key_var=api_key_var,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def score_environment(
|
|
166
|
+
env: Any,
|
|
167
|
+
*,
|
|
168
|
+
client: Any,
|
|
169
|
+
model: str,
|
|
170
|
+
num_examples: int = -1,
|
|
171
|
+
rollouts_per_example: int = 1,
|
|
172
|
+
**kwargs: Any,
|
|
173
|
+
) -> Any:
|
|
174
|
+
"""Run a verifiers environment and return its ``GenerateOutputs``. `env` is an
|
|
175
|
+
already-loaded Environment, or an env id/name resolvable by
|
|
176
|
+
``verifiers.load_environment`` (a local container must be installed first)."""
|
|
177
|
+
if isinstance(env, str):
|
|
178
|
+
try:
|
|
179
|
+
import verifiers as vf
|
|
180
|
+
except ImportError as e: # pragma: no cover - optional dep
|
|
181
|
+
raise EvalHarvestError(
|
|
182
|
+
'verifiers is not installed — `pip install "verifiers<1.0.0"` to '
|
|
183
|
+
"score environments (this adapter drives the legacy v0 "
|
|
184
|
+
"Environment API, which v1 froze), or pass an already-loaded "
|
|
185
|
+
"Environment."
|
|
186
|
+
) from e
|
|
187
|
+
if not hasattr(vf, "load_environment"):
|
|
188
|
+
# verifiers v1 dropped the frozen v0 loader — this adapter is v0-only.
|
|
189
|
+
raise EvalHarvestError(
|
|
190
|
+
"the installed verifiers has no load_environment — it looks like "
|
|
191
|
+
"verifiers v1, whose Taskset API this v0 adapter does not drive. "
|
|
192
|
+
'Pin `verifiers<1.0.0` for v0 environments, or run v1 Taskset '
|
|
193
|
+
"packages through the platform runner's verifiers-v1 engine."
|
|
194
|
+
)
|
|
195
|
+
env = vf.load_environment(env)
|
|
196
|
+
if not hasattr(env, "evaluate_sync"):
|
|
197
|
+
if callable(getattr(env, "load", None)):
|
|
198
|
+
# v1 Tasksets expose load() -> list[Task] instead of evaluate_sync.
|
|
199
|
+
raise EvalHarvestError(
|
|
200
|
+
"env looks like a verifiers v1 Taskset (has load(), no "
|
|
201
|
+
"evaluate_sync). This adapter drives the legacy v0 Environment "
|
|
202
|
+
"API only — run v1 Taskset packages through the platform "
|
|
203
|
+
"runner's verifiers-v1 engine, or pin `verifiers<1.0.0` and "
|
|
204
|
+
"expose a v0 load_environment()."
|
|
205
|
+
)
|
|
206
|
+
raise EvalHarvestError("env is not a verifiers Environment (no evaluate_sync method).")
|
|
207
|
+
return env.evaluate_sync(
|
|
208
|
+
client=_adapt_client(client),
|
|
209
|
+
model=model,
|
|
210
|
+
num_examples=num_examples,
|
|
211
|
+
rollouts_per_example=rollouts_per_example,
|
|
212
|
+
**kwargs,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def run_and_harvest(
|
|
217
|
+
env: Any,
|
|
218
|
+
version_id: str,
|
|
219
|
+
evals_client: GatewayEvalsClient,
|
|
220
|
+
*,
|
|
221
|
+
client: Any,
|
|
222
|
+
model: str,
|
|
223
|
+
num_examples: int = -1,
|
|
224
|
+
rollouts_per_example: int = 1,
|
|
225
|
+
run_id: Optional[str] = None,
|
|
226
|
+
**kwargs: Any,
|
|
227
|
+
) -> Dict[str, Any]:
|
|
228
|
+
"""Score a verifiers container version and harvest a version-pinned evaluation
|
|
229
|
+
into Gateway: evaluate → create → push samples → finalize with metrics."""
|
|
230
|
+
outputs = score_environment(
|
|
231
|
+
env,
|
|
232
|
+
client=client,
|
|
233
|
+
model=model,
|
|
234
|
+
num_examples=num_examples,
|
|
235
|
+
rollouts_per_example=rollouts_per_example,
|
|
236
|
+
**kwargs,
|
|
237
|
+
)
|
|
238
|
+
samples = samples_from_generate_outputs(outputs)
|
|
239
|
+
metrics = metrics_from_generate_outputs(outputs)
|
|
240
|
+
|
|
241
|
+
evaluation_id = evals_client.create_evaluation(
|
|
242
|
+
version_id,
|
|
243
|
+
model=model,
|
|
244
|
+
run_id=run_id,
|
|
245
|
+
# Samples are one row PER ROLLOUT — count distinct examples, not rows,
|
|
246
|
+
# or the UI's "N examples × k rollouts" double-counts by k.
|
|
247
|
+
num_examples=(num_examples if num_examples > 0 else len({s.get("exampleId") for s in samples})),
|
|
248
|
+
rollouts_per_example=rollouts_per_example,
|
|
249
|
+
)
|
|
250
|
+
inserted = evals_client.push_samples(evaluation_id, samples)
|
|
251
|
+
evals_client.finalize_evaluation(evaluation_id, metrics=metrics)
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
"evaluationId": evaluation_id,
|
|
255
|
+
"samples": inserted,
|
|
256
|
+
"metrics": metrics,
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def run_local_eval(
|
|
261
|
+
env: Any,
|
|
262
|
+
version_id: str,
|
|
263
|
+
evals_client: GatewayEvalsClient,
|
|
264
|
+
*,
|
|
265
|
+
client: Any,
|
|
266
|
+
config: Any,
|
|
267
|
+
run_id: Optional[str] = None,
|
|
268
|
+
) -> Dict[str, Any]:
|
|
269
|
+
"""Run a local verifiers eval driven by an ``EvalConfig``, writing a resumable
|
|
270
|
+
on-disk artifact (``results.jsonl`` + ``metadata.json``) when
|
|
271
|
+
``config.save_results`` and harvesting a version-pinned evaluation into Gateway.
|
|
272
|
+
|
|
273
|
+
Resume: ``config.resume_path`` uses that dir; otherwise, when saving, it reuses
|
|
274
|
+
the newest matching incomplete run (or starts a fresh one). NOTE: v1 saves the
|
|
275
|
+
whole run at the end (resume across runs), not mid-``evaluate_sync``.
|
|
276
|
+
"""
|
|
277
|
+
from pathlib import Path
|
|
278
|
+
|
|
279
|
+
from .path_utils import (
|
|
280
|
+
find_latest_incomplete_eval_results_path,
|
|
281
|
+
get_results_path,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
results_path = None
|
|
285
|
+
if config.resume_path:
|
|
286
|
+
results_path = Path(config.resume_path)
|
|
287
|
+
elif config.save_results:
|
|
288
|
+
results_path = find_latest_incomplete_eval_results_path(
|
|
289
|
+
config.output_dir,
|
|
290
|
+
config.env_id,
|
|
291
|
+
config.model,
|
|
292
|
+
config.num_examples,
|
|
293
|
+
config.rollouts_per_example,
|
|
294
|
+
config.shuffle,
|
|
295
|
+
config.shuffle_seed,
|
|
296
|
+
) or get_results_path(config.output_dir, config.env_id, config.model)
|
|
297
|
+
|
|
298
|
+
outputs = score_environment(
|
|
299
|
+
env,
|
|
300
|
+
client=client,
|
|
301
|
+
model=config.model,
|
|
302
|
+
num_examples=config.num_examples,
|
|
303
|
+
rollouts_per_example=config.rollouts_per_example,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
if results_path is not None:
|
|
307
|
+
write_results_artifact(outputs, config, results_path)
|
|
308
|
+
|
|
309
|
+
samples = samples_from_generate_outputs(outputs)
|
|
310
|
+
metrics = metrics_from_generate_outputs(outputs)
|
|
311
|
+
evaluation_id = evals_client.create_evaluation(
|
|
312
|
+
version_id,
|
|
313
|
+
model=config.model,
|
|
314
|
+
run_id=run_id,
|
|
315
|
+
# Distinct examples, not rollout rows (see run_and_harvest).
|
|
316
|
+
num_examples=(config.num_examples if config.num_examples > 0 else len({s.get("exampleId") for s in samples})),
|
|
317
|
+
rollouts_per_example=config.rollouts_per_example,
|
|
318
|
+
)
|
|
319
|
+
inserted = evals_client.push_samples(evaluation_id, samples)
|
|
320
|
+
evals_client.finalize_evaluation(evaluation_id, metrics=metrics)
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
"evaluationId": evaluation_id,
|
|
324
|
+
"samples": inserted,
|
|
325
|
+
"metrics": metrics,
|
|
326
|
+
"resultsPath": str(results_path) if results_path else None,
|
|
327
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Semantic-version bump helpers for `bench push --auto-bump/--rc/--post`.
|
|
2
|
+
|
|
3
|
+
The bump functions and the pyproject rewrite are ported verbatim from Prime
|
|
4
|
+
Intellect's ``prime`` CLI (``packages/prime/src/prime_cli/commands/env.py``,
|
|
5
|
+
MIT (c) 2025 Prime Intellect) — see ``_archive.py`` for the same attribution. The
|
|
6
|
+
rewrite is a raw-text regex substitution (not a TOML re-dump) so comments and
|
|
7
|
+
formatting in ``pyproject.toml`` are preserved.
|
|
8
|
+
|
|
9
|
+
Stdlib only (``re``).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def bump_version(version: str) -> str:
|
|
19
|
+
"""Patch bump: ``1.2.3`` -> ``1.2.4``. Strips a ``-``/``+`` pre-release/build
|
|
20
|
+
suffix to find the numeric patch; a non-numeric patch appends ``.1``."""
|
|
21
|
+
parts = version.split(".")
|
|
22
|
+
if len(parts) >= 3:
|
|
23
|
+
patch_part = parts[2]
|
|
24
|
+
if "-" in patch_part:
|
|
25
|
+
patch_num = patch_part.split("-")[0]
|
|
26
|
+
elif "+" in patch_part:
|
|
27
|
+
patch_num = patch_part.split("+")[0]
|
|
28
|
+
else:
|
|
29
|
+
patch_num = patch_part
|
|
30
|
+
try:
|
|
31
|
+
parts[2] = str(int(patch_num) + 1)
|
|
32
|
+
return ".".join(parts)
|
|
33
|
+
except ValueError:
|
|
34
|
+
return f"{version}.1"
|
|
35
|
+
elif len(parts) == 2:
|
|
36
|
+
return f"{version}.1"
|
|
37
|
+
else:
|
|
38
|
+
return f"{version}.0.1"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def bump_rc_version(version: str) -> str:
|
|
42
|
+
"""Release-candidate bump: ``1.2.3`` -> ``1.2.3.rc0``, ``1.2.3.rc0`` ->
|
|
43
|
+
``1.2.3.rc1`` (Prime's docstring wrongly says ``.post``; the code does ``.rc``)."""
|
|
44
|
+
m = re.match(r"^(?P<base>.*?)(?:\.rc|rc)(?P<num>\d+)$", version)
|
|
45
|
+
if m:
|
|
46
|
+
return f"{m.group('base')}.rc{int(m.group('num')) + 1}"
|
|
47
|
+
return f'{re.sub(r"([+-].*)$", "", version)}.rc0'
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def bump_post_version(version: str) -> str:
|
|
51
|
+
"""Post-release bump: ``1.2.3`` -> ``1.2.3.post0``, ``1.2.3.post0`` ->
|
|
52
|
+
``1.2.3.post1``."""
|
|
53
|
+
m = re.match(r"^(?P<base>.*?)(?:\.post|post)(?P<num>\d+)$", version)
|
|
54
|
+
if m:
|
|
55
|
+
return f"{m.group('base')}.post{int(m.group('num')) + 1}"
|
|
56
|
+
return f'{re.sub(r"([+-].*)$", "", version)}.post0'
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def update_pyproject_version(pyproject_path: Path, new_version: str) -> None:
|
|
60
|
+
"""Rewrite the ``version = "..."`` line in pyproject.toml via regex (preserving
|
|
61
|
+
formatting/comments). Raises ``ValueError`` if no version line is present."""
|
|
62
|
+
pyproject_path = Path(pyproject_path)
|
|
63
|
+
content = pyproject_path.read_text()
|
|
64
|
+
updated = re.sub(
|
|
65
|
+
r'(\s*)version\s*=\s*["\'][^"\']*["\']',
|
|
66
|
+
rf'\1version = "{new_version}"',
|
|
67
|
+
content,
|
|
68
|
+
flags=re.MULTILINE,
|
|
69
|
+
)
|
|
70
|
+
if updated == content:
|
|
71
|
+
raise ValueError("version line not found or unchanged in pyproject.toml")
|
|
72
|
+
pyproject_path.write_text(updated)
|