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,34 @@
|
|
|
1
|
+
"""Explicit hosted-dispatch identity. No identity is inferred from process state."""
|
|
2
|
+
from typing import TypedDict
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DispatchShard(TypedDict):
|
|
7
|
+
protocol: int
|
|
8
|
+
dispatchId: str
|
|
9
|
+
slotId: str
|
|
10
|
+
index: int
|
|
11
|
+
total: int
|
|
12
|
+
jobId: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def validate_dispatch_shard(value: object) -> DispatchShard:
|
|
16
|
+
keys = {"protocol", "dispatchId", "slotId", "index", "total", "jobId"}
|
|
17
|
+
if not isinstance(value, dict) or set(value) != keys:
|
|
18
|
+
raise ValueError("dispatchShard must contain exactly the protocol and dispatch slot identity fields")
|
|
19
|
+
if type(value["protocol"]) is not int or value["protocol"] != 1:
|
|
20
|
+
raise ValueError("dispatchShard protocol must be 1")
|
|
21
|
+
if (type(value["index"]) is not int or type(value["total"]) is not int
|
|
22
|
+
or not 1 <= value["total"] <= 16 or not 0 <= value["index"] < value["total"]):
|
|
23
|
+
raise ValueError("dispatchShard must have 0 <= index < total <= 16")
|
|
24
|
+
for key in ("dispatchId", "slotId", "jobId"):
|
|
25
|
+
item = value[key]
|
|
26
|
+
if not isinstance(item, str) or not item or item != item.strip():
|
|
27
|
+
raise ValueError(f"dispatchShard {key} must be a nonblank identifier without boundary whitespace")
|
|
28
|
+
try:
|
|
29
|
+
parsed = UUID(value["slotId"])
|
|
30
|
+
if str(parsed) != value["slotId"].lower():
|
|
31
|
+
raise ValueError("noncanonical UUID")
|
|
32
|
+
except (ValueError, AttributeError):
|
|
33
|
+
raise ValueError("dispatchShard slotId must be a hyphenated UUID") from None
|
|
34
|
+
return dict(value)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Config for a local ``bench eval`` run (the in-scope subset of verifiers'
|
|
2
|
+
EvalConfig). Drives the resumable results artifact + the Gateway harvest."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class EvalConfig:
|
|
12
|
+
env_id: str # container slug/name (the verifiers env id)
|
|
13
|
+
model: str # model id for the OpenAI-compatible client
|
|
14
|
+
num_examples: int = -1
|
|
15
|
+
rollouts_per_example: int = 1
|
|
16
|
+
shuffle: bool = False
|
|
17
|
+
shuffle_seed: Optional[int] = None
|
|
18
|
+
output_dir: str = "./outputs"
|
|
19
|
+
save_results: bool = False
|
|
20
|
+
resume_path: Optional[str] = None
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"""Gateway eval-harvest client.
|
|
2
|
+
|
|
3
|
+
Mirrors the prime-evals ``EvalsClient`` shape (create_evaluation ->
|
|
4
|
+
push_samples[batched] -> finalize_evaluation) but harvests INTO Gateway — pointed
|
|
5
|
+
at our version-pinned eval routes, never at Prime's platform. An evaluation is
|
|
6
|
+
anchored to an immutable container version, so scores stay reproducible across
|
|
7
|
+
re-pushes; each sample carries the multi-component reward breakdown.
|
|
8
|
+
|
|
9
|
+
Stdlib only. Writes require a secret key (Basic auth).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import base64
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import urllib.error
|
|
20
|
+
import urllib.request
|
|
21
|
+
import uuid
|
|
22
|
+
from collections import OrderedDict
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
|
+
from typing import Any, Dict, List, Optional
|
|
25
|
+
|
|
26
|
+
from .dispatch_shard import DispatchShard, validate_dispatch_shard
|
|
27
|
+
|
|
28
|
+
_BASE = "/api/public/benchmark-containers/evaluations"
|
|
29
|
+
|
|
30
|
+
_log = logging.getLogger("gatewaysdk.benchmark_hub.evals")
|
|
31
|
+
|
|
32
|
+
# Each rollout is emitted as a Gateway SESSION (a session-tagged trace) so it
|
|
33
|
+
# opens in the platform's session view. Set GATEWAY_EMIT_ROLLOUT_SESSIONS=0 to
|
|
34
|
+
# disable. The resulting {sessionId, traceId} are stamped into sample.info so
|
|
35
|
+
# the RolloutViewer links straight to the session/trace.
|
|
36
|
+
|
|
37
|
+
#: The single environment every rollout trace is stamped with. Rollouts land
|
|
38
|
+
#: in the SAME project as the agent's live traffic (agent projects own their
|
|
39
|
+
#: environment containers), and this well-known name is what lets the
|
|
40
|
+
#: platform hide them by default while keeping them selectable. Keep in sync
|
|
41
|
+
#: with GATEWAY_ROLLOUTS_ENVIRONMENT in gateway/packages/shared/src/constants.ts
|
|
42
|
+
#: and ROLLOUTS_ENVIRONMENT in deploy/benchmark-runner/engines/.
|
|
43
|
+
ROLLOUTS_ENVIRONMENT = "rollouts"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _emit_rollout_sessions_enabled() -> bool:
|
|
47
|
+
return os.environ.get("GATEWAY_EMIT_ROLLOUT_SESSIONS", "1") not in (
|
|
48
|
+
"0",
|
|
49
|
+
"false",
|
|
50
|
+
"no",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class EvalHarvestError(RuntimeError):
|
|
55
|
+
"""Raised when a harvest call fails."""
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _chunk(items: List[Any], size: int) -> List[List[Any]]:
|
|
59
|
+
if size <= 0:
|
|
60
|
+
raise ValueError("size must be > 0")
|
|
61
|
+
return [items[i : i + size] for i in range(0, len(items), size)]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def normalize_sample(sample: Dict[str, Any]) -> Dict[str, Any]:
|
|
65
|
+
"""Map a sample (snake_case prime-evals style OR camelCase) to our API shape.
|
|
66
|
+
Named sub-rewards belong in `rewards`; the caller (e.g. the verifiers worker)
|
|
67
|
+
builds that dict from the rubric's components."""
|
|
68
|
+
|
|
69
|
+
def pick(*keys: str) -> Any:
|
|
70
|
+
for k in keys:
|
|
71
|
+
if k in sample and sample[k] is not None:
|
|
72
|
+
return sample[k]
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
mapping = [
|
|
76
|
+
("exampleId", ("exampleId", "example_id")),
|
|
77
|
+
("task", ("task",)),
|
|
78
|
+
("rolloutIndex", ("rolloutIndex", "rollout_index")),
|
|
79
|
+
("prompt", ("prompt",)),
|
|
80
|
+
("completion", ("completion",)),
|
|
81
|
+
("answer", ("answer",)),
|
|
82
|
+
("reward", ("reward",)),
|
|
83
|
+
("score", ("score",)),
|
|
84
|
+
("correct", ("correct",)),
|
|
85
|
+
("rewards", ("rewards",)),
|
|
86
|
+
("info", ("info",)),
|
|
87
|
+
]
|
|
88
|
+
out: Dict[str, Any] = {}
|
|
89
|
+
for our_key, in_keys in mapping:
|
|
90
|
+
v = pick(*in_keys)
|
|
91
|
+
if v is not None:
|
|
92
|
+
out[our_key] = v
|
|
93
|
+
return out
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class GatewayEvalsClient:
|
|
97
|
+
"""Create/push/finalize evaluations against a Gateway host."""
|
|
98
|
+
|
|
99
|
+
def __init__(self, host: str, public_key: str, secret_key: str) -> None:
|
|
100
|
+
if not host:
|
|
101
|
+
raise ValueError("host is required (e.g. https://withgateway.ai)")
|
|
102
|
+
if not public_key or not secret_key:
|
|
103
|
+
raise ValueError("both public_key and secret_key are required")
|
|
104
|
+
self.host = host.rstrip("/")
|
|
105
|
+
self._auth = base64.b64encode(
|
|
106
|
+
f"{public_key}:{secret_key}".encode("utf-8")
|
|
107
|
+
).decode("ascii")
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def from_env(cls, host: Optional[str] = None) -> "GatewayEvalsClient":
|
|
111
|
+
return cls(
|
|
112
|
+
host=host or os.environ.get("GATEWAY_HOST", ""),
|
|
113
|
+
public_key=os.environ.get("GATEWAY_PUBLIC_KEY", ""),
|
|
114
|
+
secret_key=os.environ.get("GATEWAY_SECRET_KEY", ""),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def _post(self, path: str, body: Dict[str, Any]) -> Dict[str, Any]:
|
|
118
|
+
req = urllib.request.Request(
|
|
119
|
+
f"{self.host}{path}",
|
|
120
|
+
data=json.dumps(body).encode("utf-8"),
|
|
121
|
+
method="POST",
|
|
122
|
+
headers={
|
|
123
|
+
"Authorization": f"Basic {self._auth}",
|
|
124
|
+
"Content-Type": "application/json",
|
|
125
|
+
},
|
|
126
|
+
)
|
|
127
|
+
try:
|
|
128
|
+
with urllib.request.urlopen(req, timeout=180) as resp:
|
|
129
|
+
return json.loads(resp.read().decode("utf-8"))
|
|
130
|
+
except urllib.error.HTTPError as e:
|
|
131
|
+
detail = e.read().decode("utf-8", "replace")[:500]
|
|
132
|
+
raise EvalHarvestError(f"POST {path} -> {e.code}: {detail}") from None
|
|
133
|
+
|
|
134
|
+
def create_evaluation(
|
|
135
|
+
self,
|
|
136
|
+
version_id: str,
|
|
137
|
+
*,
|
|
138
|
+
model: Optional[str] = None,
|
|
139
|
+
run_id: Optional[str] = None,
|
|
140
|
+
dispatch_shard: Optional[DispatchShard] = None,
|
|
141
|
+
# The world condition this evaluation executed under (identity only —
|
|
142
|
+
# the bindings that changed behavior travel in `metadata`). Recorded so
|
|
143
|
+
# results can be compared BY condition instead of by whichever label
|
|
144
|
+
# someone remembers attaching to the run.
|
|
145
|
+
condition_id: Optional[str] = None,
|
|
146
|
+
# The agent build this evaluation tested. Identity only, like
|
|
147
|
+
# condition_id: nothing in the run branches on it, but without it a run
|
|
148
|
+
# records only which MODEL answered, and a release citing that run
|
|
149
|
+
# cannot show the thing shipped is the thing tested.
|
|
150
|
+
agent_build_id: Optional[str] = None,
|
|
151
|
+
# WHAT THE RUN ACTUALLY DID with the agent variation it was sent —
|
|
152
|
+
# `AppliedAgentVariation` from
|
|
153
|
+
# packages/shared/src/agent-variation/schemas.ts.
|
|
154
|
+
#
|
|
155
|
+
# Unlike agent_build_id this is NOT identity: it is the only thing that
|
|
156
|
+
# ever writes `benchmark_container_evaluations
|
|
157
|
+
# .agent_variation_revision_id`. The platform can dispatch a variation
|
|
158
|
+
# and cannot observe that the engine honoured it — a stale image, a
|
|
159
|
+
# dropped env var, or an engine that never learnt to read the variable
|
|
160
|
+
# each produce a run that used the world bundle's own prompt. So the
|
|
161
|
+
# pin comes from the runner's echo and from nothing else. Omitted = not
|
|
162
|
+
# recorded, which is the honest state for every runner that predates
|
|
163
|
+
# this field.
|
|
164
|
+
applied_agent_variation: Optional[Dict[str, Any]] = None,
|
|
165
|
+
num_examples: Optional[int] = None,
|
|
166
|
+
rollouts_per_example: Optional[int] = None,
|
|
167
|
+
environment_ids: Optional[List[str]] = None,
|
|
168
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
169
|
+
) -> str:
|
|
170
|
+
body: Dict[str, Any] = {"versionId": version_id}
|
|
171
|
+
if dispatch_shard is not None:
|
|
172
|
+
if not isinstance(run_id, str) or not run_id or run_id != run_id.strip():
|
|
173
|
+
raise ValueError("dispatchShard requires a nonblank run_id without boundary whitespace")
|
|
174
|
+
body["dispatchShard"] = validate_dispatch_shard(dispatch_shard)
|
|
175
|
+
if model is not None:
|
|
176
|
+
body["model"] = model
|
|
177
|
+
if run_id is not None:
|
|
178
|
+
body["runId"] = run_id
|
|
179
|
+
if condition_id is not None:
|
|
180
|
+
body["conditionId"] = condition_id
|
|
181
|
+
if agent_build_id is not None:
|
|
182
|
+
body["agentBuildId"] = agent_build_id
|
|
183
|
+
if applied_agent_variation is not None:
|
|
184
|
+
body["appliedAgentVariation"] = applied_agent_variation
|
|
185
|
+
if num_examples is not None:
|
|
186
|
+
body["numExamples"] = num_examples
|
|
187
|
+
if rollouts_per_example is not None:
|
|
188
|
+
body["rolloutsPerExample"] = rollouts_per_example
|
|
189
|
+
if environment_ids is not None:
|
|
190
|
+
body["environmentIds"] = environment_ids
|
|
191
|
+
if metadata is not None:
|
|
192
|
+
body["metadata"] = metadata
|
|
193
|
+
evaluation_id = self._post(_BASE, body)["evaluationId"]
|
|
194
|
+
_OPEN_EVALUATIONS[evaluation_id] = self
|
|
195
|
+
return evaluation_id
|
|
196
|
+
|
|
197
|
+
def _stringify(self, value: Any) -> str:
|
|
198
|
+
if value is None:
|
|
199
|
+
return ""
|
|
200
|
+
if isinstance(value, str):
|
|
201
|
+
return value
|
|
202
|
+
try:
|
|
203
|
+
return json.dumps(value, ensure_ascii=False)
|
|
204
|
+
except (TypeError, ValueError):
|
|
205
|
+
return str(value)
|
|
206
|
+
|
|
207
|
+
def _emit_rollout_session(
|
|
208
|
+
self,
|
|
209
|
+
session_id: str,
|
|
210
|
+
*,
|
|
211
|
+
name: str,
|
|
212
|
+
prompt: Any,
|
|
213
|
+
completion: Any,
|
|
214
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
215
|
+
) -> Dict[str, str]:
|
|
216
|
+
"""Emit one rollout as a session-tagged trace via the ingestion API.
|
|
217
|
+
|
|
218
|
+
Mirrors the runner's emit_rollout_session (and voice sessions): a single
|
|
219
|
+
`trace-create` event whose `sessionId` ties the trace into a session,
|
|
220
|
+
with input=prompt / output=completion. Fail-soft — returns {} on any
|
|
221
|
+
error and never raises (harvest must not break on tracing).
|
|
222
|
+
"""
|
|
223
|
+
trace_id = uuid.uuid4().hex
|
|
224
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
225
|
+
try:
|
|
226
|
+
self._post(
|
|
227
|
+
"/api/public/ingestion",
|
|
228
|
+
{
|
|
229
|
+
"batch": [
|
|
230
|
+
{
|
|
231
|
+
"id": uuid.uuid4().hex,
|
|
232
|
+
"type": "trace-create",
|
|
233
|
+
"timestamp": now,
|
|
234
|
+
"body": {
|
|
235
|
+
"id": trace_id,
|
|
236
|
+
"sessionId": session_id,
|
|
237
|
+
"name": name or "rollout",
|
|
238
|
+
"environment": ROLLOUTS_ENVIRONMENT,
|
|
239
|
+
"input": self._stringify(prompt),
|
|
240
|
+
"output": self._stringify(completion),
|
|
241
|
+
"metadata": metadata or {},
|
|
242
|
+
"timestamp": now,
|
|
243
|
+
},
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
)
|
|
248
|
+
return {"sessionId": session_id, "traceId": trace_id}
|
|
249
|
+
except Exception as exc: # noqa: BLE001 — tracing is best-effort
|
|
250
|
+
_log.warning("rollout session emit failed for %s: %s", session_id, exc)
|
|
251
|
+
return {}
|
|
252
|
+
|
|
253
|
+
def _tag_sample_session(self, evaluation_id: str, sample: Dict[str, Any]) -> None:
|
|
254
|
+
"""Emit a session for `sample` and stamp {sessionId, traceId} into info."""
|
|
255
|
+
info = sample.get("info")
|
|
256
|
+
if not isinstance(info, dict):
|
|
257
|
+
info = {}
|
|
258
|
+
sample["info"] = info
|
|
259
|
+
# Respect an id the caller already set (e.g. a live-traced rollout).
|
|
260
|
+
if info.get("sessionId") or info.get("session_id"):
|
|
261
|
+
return
|
|
262
|
+
example_id = sample.get("exampleId") or sample.get("example_id") or "ex"
|
|
263
|
+
rollout_index = sample.get("rolloutIndex") or sample.get("rollout_index") or 0
|
|
264
|
+
session_id = f"{evaluation_id}:{example_id}:{rollout_index}"
|
|
265
|
+
ids = self._emit_rollout_session(
|
|
266
|
+
session_id,
|
|
267
|
+
name=str(sample.get("task") or example_id),
|
|
268
|
+
prompt=sample.get("prompt"),
|
|
269
|
+
completion=sample.get("completion") or sample.get("answer"),
|
|
270
|
+
metadata={
|
|
271
|
+
"evaluationId": evaluation_id,
|
|
272
|
+
"task": sample.get("task"),
|
|
273
|
+
"reward": sample.get("reward"),
|
|
274
|
+
},
|
|
275
|
+
)
|
|
276
|
+
info.update(ids)
|
|
277
|
+
|
|
278
|
+
def push_samples(
|
|
279
|
+
self,
|
|
280
|
+
evaluation_id: str,
|
|
281
|
+
samples: List[Dict[str, Any]],
|
|
282
|
+
*,
|
|
283
|
+
batch_size: int = 100,
|
|
284
|
+
) -> int:
|
|
285
|
+
emit_sessions = _emit_rollout_sessions_enabled()
|
|
286
|
+
total = 0
|
|
287
|
+
for batch in _chunk(samples, batch_size):
|
|
288
|
+
if emit_sessions:
|
|
289
|
+
# Each rollout becomes a session-tagged trace; sample.info then
|
|
290
|
+
# carries {sessionId, traceId} for the RolloutViewer links.
|
|
291
|
+
for s in batch:
|
|
292
|
+
self._tag_sample_session(evaluation_id, s)
|
|
293
|
+
resp = self._post(
|
|
294
|
+
f"{_BASE}/{evaluation_id}/samples",
|
|
295
|
+
{"samples": [normalize_sample(s) for s in batch]},
|
|
296
|
+
)
|
|
297
|
+
total += int(resp.get("inserted", len(batch)))
|
|
298
|
+
return total
|
|
299
|
+
|
|
300
|
+
def finalize_evaluation(
|
|
301
|
+
self,
|
|
302
|
+
evaluation_id: str,
|
|
303
|
+
*,
|
|
304
|
+
status: str = "COMPLETED",
|
|
305
|
+
metrics: Optional[Dict[str, Any]] = None,
|
|
306
|
+
cost: Optional[Dict[str, Any]] = None,
|
|
307
|
+
) -> str:
|
|
308
|
+
body: Dict[str, Any] = {"status": status}
|
|
309
|
+
if metrics is not None:
|
|
310
|
+
body["metrics"] = metrics
|
|
311
|
+
if cost is not None:
|
|
312
|
+
body["cost"] = cost
|
|
313
|
+
result = self._post(f"{_BASE}/{evaluation_id}/finalize", body)["status"]
|
|
314
|
+
_OPEN_EVALUATIONS.pop(evaluation_id, None)
|
|
315
|
+
return result
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
# Evaluations created but not yet finalized. A runner that dies mid-rollout
|
|
319
|
+
# would otherwise leave its evaluation RUNNING forever, so the process-level
|
|
320
|
+
# error handler finalizes whatever is still open as FAILED.
|
|
321
|
+
_OPEN_EVALUATIONS: "OrderedDict[str, GatewayEvalsClient]" = OrderedDict()
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def open_evaluations() -> List[str]:
|
|
325
|
+
"""Ids of evaluations created in this process that were never finalized."""
|
|
326
|
+
return list(_OPEN_EVALUATIONS)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def fail_open_evaluations(reason: str) -> List[str]:
|
|
330
|
+
"""Mark every still-open evaluation FAILED, recording `reason`.
|
|
331
|
+
|
|
332
|
+
Best-effort by design: it runs on a path where something has ALREADY gone
|
|
333
|
+
wrong, so a failure to report the failure must not mask the original error.
|
|
334
|
+
Returns the ids it managed to finalize.
|
|
335
|
+
"""
|
|
336
|
+
failed: List[str] = []
|
|
337
|
+
for evaluation_id, client in list(_OPEN_EVALUATIONS.items()):
|
|
338
|
+
# Deregister FIRST: whatever happens next, this evaluation has had its
|
|
339
|
+
# one attempt. Leaving it registered risks reporting it twice or looping.
|
|
340
|
+
_OPEN_EVALUATIONS.pop(evaluation_id, None)
|
|
341
|
+
try:
|
|
342
|
+
client.finalize_evaluation(
|
|
343
|
+
evaluation_id, status="FAILED", metrics={"error": reason[:2000]}
|
|
344
|
+
)
|
|
345
|
+
failed.append(evaluation_id)
|
|
346
|
+
except Exception as exc: # noqa: BLE001 - never mask the original error
|
|
347
|
+
print(
|
|
348
|
+
f"[evals] could not mark evaluation {evaluation_id} FAILED: {exc}",
|
|
349
|
+
file=sys.stderr,
|
|
350
|
+
)
|
|
351
|
+
return failed
|