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,356 @@
|
|
|
1
|
+
# Copyright (c) Gateway. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""OTel span builder for JSON push-to-trace.
|
|
4
|
+
|
|
5
|
+
Creates OpenTelemetry spans from resolved mapping data. Isolated from
|
|
6
|
+
the mapping engine -- takes already-validated, already-resolved field
|
|
7
|
+
dicts and produces real spans with proper parent-child linking.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import time
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
|
+
|
|
17
|
+
from opentelemetry import context as otel_context
|
|
18
|
+
from opentelemetry import trace as otel_trace
|
|
19
|
+
|
|
20
|
+
from . import semconv
|
|
21
|
+
from .mapping import ChildMapping, coerce_timestamp, resolve_path
|
|
22
|
+
from .push_models import SpanPreview, ValidationIssue
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
# Default timestamp: "now" in nanoseconds
|
|
27
|
+
_NANOS_PER_SECOND = 1_000_000_000
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _now_ns() -> int:
|
|
31
|
+
return int(time.time() * _NANOS_PER_SECOND)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _safe_json(value: Any) -> str:
|
|
35
|
+
"""Serialize a value to JSON string for span attributes."""
|
|
36
|
+
if isinstance(value, str):
|
|
37
|
+
return value
|
|
38
|
+
try:
|
|
39
|
+
return json.dumps(value)
|
|
40
|
+
except (TypeError, ValueError):
|
|
41
|
+
logger.warning(
|
|
42
|
+
"Value of type %s is not JSON-serializable, using str() fallback: %s",
|
|
43
|
+
type(value).__name__,
|
|
44
|
+
repr(value)[:100],
|
|
45
|
+
)
|
|
46
|
+
return str(value)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# =============================================================================
|
|
50
|
+
# Span Building
|
|
51
|
+
# =============================================================================
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def build_trace_spans(
|
|
55
|
+
data: dict,
|
|
56
|
+
fields: Dict[str, Any],
|
|
57
|
+
child_mapping: Optional[ChildMapping],
|
|
58
|
+
tracer: Optional[otel_trace.Tracer] = None,
|
|
59
|
+
extra_attributes: Optional[Dict[str, Any]] = None,
|
|
60
|
+
timestamp_unit: str = "auto",
|
|
61
|
+
) -> tuple[str, int, List[ValidationIssue]]:
|
|
62
|
+
"""Create OTel spans for a trace and its children.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
data: The original JSON data dict (for resolving child fields).
|
|
66
|
+
fields: Merged trace-level fields (name, input, output, etc.).
|
|
67
|
+
child_mapping: Optional mapping for children observations.
|
|
68
|
+
tracer: OTel tracer to use. Defaults to the global gatewaysdk tracer.
|
|
69
|
+
extra_attributes: Additional OTel span attributes to set on the root span.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
(trace_id, observation_count, warnings) -- the hex trace ID, number of
|
|
73
|
+
child observations created, and any runtime warnings.
|
|
74
|
+
"""
|
|
75
|
+
if tracer is None:
|
|
76
|
+
tracer = otel_trace.get_tracer("gatewaysdk.tracing.push")
|
|
77
|
+
|
|
78
|
+
start_ns = coerce_timestamp(fields.get("timestamp"), unit=timestamp_unit) or _now_ns()
|
|
79
|
+
|
|
80
|
+
# Build root span attributes
|
|
81
|
+
root_attrs = _build_trace_attributes(fields)
|
|
82
|
+
if extra_attributes:
|
|
83
|
+
root_attrs.update(extra_attributes)
|
|
84
|
+
|
|
85
|
+
root_span = tracer.start_span(
|
|
86
|
+
name=fields.get("name") or "push",
|
|
87
|
+
start_time=start_ns,
|
|
88
|
+
attributes=root_attrs,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
observation_count = 0
|
|
92
|
+
runtime_warnings: List[ValidationIssue] = []
|
|
93
|
+
|
|
94
|
+
# Build children
|
|
95
|
+
if child_mapping is not None:
|
|
96
|
+
found, children_data = resolve_path(data, child_mapping.path)
|
|
97
|
+
if found and isinstance(children_data, list):
|
|
98
|
+
root_ctx = otel_trace.set_span_in_context(root_span)
|
|
99
|
+
observation_count, child_warnings = _build_children(
|
|
100
|
+
children_data,
|
|
101
|
+
child_mapping,
|
|
102
|
+
tracer,
|
|
103
|
+
root_ctx,
|
|
104
|
+
start_ns,
|
|
105
|
+
timestamp_unit=timestamp_unit,
|
|
106
|
+
)
|
|
107
|
+
runtime_warnings.extend(child_warnings)
|
|
108
|
+
|
|
109
|
+
# End root span
|
|
110
|
+
end_ns = _now_ns()
|
|
111
|
+
root_span.end(end_time=end_ns)
|
|
112
|
+
|
|
113
|
+
# Extract trace ID
|
|
114
|
+
span_context = root_span.get_span_context()
|
|
115
|
+
trace_id = format(span_context.trace_id, "032x")
|
|
116
|
+
|
|
117
|
+
return trace_id, observation_count, runtime_warnings
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _build_trace_attributes(fields: Dict[str, Any]) -> Dict[str, Any]:
|
|
121
|
+
"""Build OTel span attributes for the root trace span."""
|
|
122
|
+
attrs: Dict[str, Any] = {}
|
|
123
|
+
|
|
124
|
+
if fields.get("name"):
|
|
125
|
+
attrs[semconv.TRACE_NAME] = fields["name"]
|
|
126
|
+
if fields.get("input") is not None:
|
|
127
|
+
attrs[semconv.TRACE_INPUT] = _safe_json(fields["input"])
|
|
128
|
+
if fields.get("output") is not None:
|
|
129
|
+
attrs[semconv.TRACE_OUTPUT] = _safe_json(fields["output"])
|
|
130
|
+
if fields.get("metadata") is not None:
|
|
131
|
+
attrs[semconv.TRACE_METADATA] = _safe_json(fields["metadata"])
|
|
132
|
+
if fields.get("tags"):
|
|
133
|
+
attrs[semconv.TRACE_TAGS] = _safe_json(fields["tags"])
|
|
134
|
+
if fields.get("user_id"):
|
|
135
|
+
attrs[semconv.USER_ID] = fields["user_id"]
|
|
136
|
+
if fields.get("session_id"):
|
|
137
|
+
attrs[semconv.SESSION_ID] = fields["session_id"]
|
|
138
|
+
if fields.get("run_id"):
|
|
139
|
+
attrs[semconv.RUN_ID] = fields["run_id"]
|
|
140
|
+
if fields.get("environment"):
|
|
141
|
+
attrs[semconv.ENVIRONMENT] = fields["environment"]
|
|
142
|
+
|
|
143
|
+
return attrs
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _build_children(
|
|
147
|
+
children_data: List[dict],
|
|
148
|
+
child_mapping: ChildMapping,
|
|
149
|
+
tracer: otel_trace.Tracer,
|
|
150
|
+
parent_ctx: otel_context.Context,
|
|
151
|
+
parent_start_ns: int,
|
|
152
|
+
timestamp_unit: str = "auto",
|
|
153
|
+
) -> tuple[int, List[ValidationIssue]]:
|
|
154
|
+
"""Create child observation spans under the parent context.
|
|
155
|
+
|
|
156
|
+
Returns (observation_count, warnings).
|
|
157
|
+
"""
|
|
158
|
+
count = 0
|
|
159
|
+
warnings: List[ValidationIssue] = []
|
|
160
|
+
|
|
161
|
+
for i, child_dict in enumerate(children_data):
|
|
162
|
+
if not isinstance(child_dict, dict):
|
|
163
|
+
warnings.append(
|
|
164
|
+
ValidationIssue(
|
|
165
|
+
field="children",
|
|
166
|
+
path=f"{child_mapping.path}[{i}]",
|
|
167
|
+
issue="invalid_child",
|
|
168
|
+
message=f"Children item at index {i} is {type(child_dict).__name__}, expected dict. Skipped.",
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
child_fields, field_warnings = _extract_child_fields(child_dict, child_mapping, timestamp_unit=timestamp_unit)
|
|
174
|
+
warnings.extend(field_warnings)
|
|
175
|
+
|
|
176
|
+
child_start = child_fields.get("start_time_ns") or (parent_start_ns + i)
|
|
177
|
+
child_end = child_fields.get("end_time_ns")
|
|
178
|
+
|
|
179
|
+
child_attrs = _build_observation_attributes(child_fields)
|
|
180
|
+
|
|
181
|
+
child_span = tracer.start_span(
|
|
182
|
+
name=child_fields.get("name") or f"observation-{i}",
|
|
183
|
+
context=parent_ctx,
|
|
184
|
+
start_time=child_start,
|
|
185
|
+
attributes=child_attrs,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Recurse into nested children if the mapping defines them
|
|
189
|
+
nested_count = 0
|
|
190
|
+
if child_mapping.children is not None:
|
|
191
|
+
found, nested_data = resolve_path(child_dict, child_mapping.children.path)
|
|
192
|
+
if found and isinstance(nested_data, list):
|
|
193
|
+
child_ctx = otel_trace.set_span_in_context(child_span)
|
|
194
|
+
nested_count, nested_warnings = _build_children(
|
|
195
|
+
nested_data,
|
|
196
|
+
child_mapping.children,
|
|
197
|
+
tracer,
|
|
198
|
+
child_ctx,
|
|
199
|
+
child_start,
|
|
200
|
+
timestamp_unit=timestamp_unit,
|
|
201
|
+
)
|
|
202
|
+
warnings.extend(nested_warnings)
|
|
203
|
+
|
|
204
|
+
child_span.end(end_time=child_end or _now_ns())
|
|
205
|
+
count += 1 + nested_count
|
|
206
|
+
|
|
207
|
+
return count, warnings
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _extract_child_fields(
|
|
211
|
+
child_dict: dict,
|
|
212
|
+
mapping: ChildMapping,
|
|
213
|
+
timestamp_unit: str = "auto",
|
|
214
|
+
) -> tuple[Dict[str, Any], List[ValidationIssue]]:
|
|
215
|
+
"""Extract mapped fields from a single child dict.
|
|
216
|
+
|
|
217
|
+
Returns (fields, warnings).
|
|
218
|
+
"""
|
|
219
|
+
fields: Dict[str, Any] = {}
|
|
220
|
+
warnings: List[ValidationIssue] = []
|
|
221
|
+
|
|
222
|
+
simple_fields = [
|
|
223
|
+
"name",
|
|
224
|
+
"input",
|
|
225
|
+
"output",
|
|
226
|
+
"type",
|
|
227
|
+
"model",
|
|
228
|
+
"metadata",
|
|
229
|
+
"level",
|
|
230
|
+
"usage",
|
|
231
|
+
"cost",
|
|
232
|
+
"model_parameters",
|
|
233
|
+
"status_message",
|
|
234
|
+
"prompt_name",
|
|
235
|
+
"prompt_version",
|
|
236
|
+
"attributes",
|
|
237
|
+
]
|
|
238
|
+
for field in simple_fields:
|
|
239
|
+
dot_path = getattr(mapping, field, None)
|
|
240
|
+
if dot_path is not None:
|
|
241
|
+
found, value = resolve_path(child_dict, dot_path)
|
|
242
|
+
if found:
|
|
243
|
+
fields[field] = value
|
|
244
|
+
|
|
245
|
+
# Timestamps need coercion
|
|
246
|
+
for ts_field in ("start_time", "end_time"):
|
|
247
|
+
dot_path = getattr(mapping, ts_field, None)
|
|
248
|
+
if dot_path is not None:
|
|
249
|
+
found, value = resolve_path(child_dict, dot_path)
|
|
250
|
+
if found:
|
|
251
|
+
coerced = coerce_timestamp(value, unit=timestamp_unit)
|
|
252
|
+
if coerced is None and value is not None:
|
|
253
|
+
warnings.append(
|
|
254
|
+
ValidationIssue(
|
|
255
|
+
field=f"children.{ts_field}",
|
|
256
|
+
path=dot_path,
|
|
257
|
+
issue="timestamp_coercion_failed",
|
|
258
|
+
message=f"Could not parse timestamp value: {value!r}. Using fallback.",
|
|
259
|
+
)
|
|
260
|
+
)
|
|
261
|
+
fields[f"{ts_field}_ns"] = coerced
|
|
262
|
+
|
|
263
|
+
return fields, warnings
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _build_observation_attributes(fields: Dict[str, Any]) -> Dict[str, Any]:
|
|
267
|
+
"""Build OTel span attributes for an observation span."""
|
|
268
|
+
attrs: Dict[str, Any] = {}
|
|
269
|
+
|
|
270
|
+
if fields.get("input") is not None:
|
|
271
|
+
attrs[semconv.OBSERVATION_INPUT] = _safe_json(fields["input"])
|
|
272
|
+
if fields.get("output") is not None:
|
|
273
|
+
attrs[semconv.OBSERVATION_OUTPUT] = _safe_json(fields["output"])
|
|
274
|
+
if fields.get("type"):
|
|
275
|
+
attrs[semconv.OBSERVATION_TYPE] = fields["type"].upper()
|
|
276
|
+
if fields.get("model"):
|
|
277
|
+
attrs[semconv.MODEL_NAME] = fields["model"]
|
|
278
|
+
# Presence of model implies GENERATION type (unless explicitly set)
|
|
279
|
+
if not fields.get("type"):
|
|
280
|
+
attrs[semconv.OBSERVATION_TYPE] = "GENERATION"
|
|
281
|
+
if fields.get("metadata") is not None:
|
|
282
|
+
attrs[semconv.OBSERVATION_METADATA] = _safe_json(fields["metadata"])
|
|
283
|
+
if fields.get("level"):
|
|
284
|
+
attrs[semconv.OBSERVATION_LEVEL] = fields["level"].upper()
|
|
285
|
+
if fields.get("status_message"):
|
|
286
|
+
attrs[semconv.OBSERVATION_STATUS_MESSAGE] = fields["status_message"]
|
|
287
|
+
if fields.get("model_parameters") is not None:
|
|
288
|
+
attrs[semconv.MODEL_PARAMETERS] = _safe_json(fields["model_parameters"])
|
|
289
|
+
|
|
290
|
+
# Usage and cost use the langfuse-compatible attributes
|
|
291
|
+
if fields.get("usage") is not None:
|
|
292
|
+
attrs["gateway.observation.usage_details"] = _safe_json(fields["usage"])
|
|
293
|
+
if fields.get("cost") is not None:
|
|
294
|
+
attrs["gateway.observation.cost_details"] = _safe_json(fields["cost"])
|
|
295
|
+
|
|
296
|
+
# Prompt reference
|
|
297
|
+
if fields.get("prompt_name"):
|
|
298
|
+
attrs["gateway.observation.prompt.name"] = fields["prompt_name"]
|
|
299
|
+
if fields.get("prompt_version") is not None:
|
|
300
|
+
attrs["gateway.observation.prompt.version"] = fields["prompt_version"]
|
|
301
|
+
|
|
302
|
+
# Extra attributes escape hatch
|
|
303
|
+
extra = fields.get("attributes")
|
|
304
|
+
if isinstance(extra, dict):
|
|
305
|
+
attrs.update(extra)
|
|
306
|
+
|
|
307
|
+
return attrs
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
# =============================================================================
|
|
311
|
+
# Preview Building (no OTel dependency)
|
|
312
|
+
# =============================================================================
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def build_trace_preview(
|
|
316
|
+
data: dict,
|
|
317
|
+
fields: Dict[str, Any],
|
|
318
|
+
child_mapping: Optional[ChildMapping],
|
|
319
|
+
) -> List[SpanPreview]:
|
|
320
|
+
"""Build SpanPreview objects for children (no OTel spans created).
|
|
321
|
+
|
|
322
|
+
Returns list of SpanPreview for the children.
|
|
323
|
+
"""
|
|
324
|
+
if child_mapping is None:
|
|
325
|
+
return []
|
|
326
|
+
|
|
327
|
+
found, children_data = resolve_path(data, child_mapping.path)
|
|
328
|
+
if not found or not isinstance(children_data, list):
|
|
329
|
+
return []
|
|
330
|
+
|
|
331
|
+
previews = []
|
|
332
|
+
for i, child_dict in enumerate(children_data):
|
|
333
|
+
if not isinstance(child_dict, dict):
|
|
334
|
+
continue
|
|
335
|
+
|
|
336
|
+
child_fields, _ = _extract_child_fields(child_dict, child_mapping)
|
|
337
|
+
|
|
338
|
+
nested = []
|
|
339
|
+
if child_mapping.children is not None:
|
|
340
|
+
nested = build_trace_preview(child_dict, child_fields, child_mapping.children)
|
|
341
|
+
|
|
342
|
+
previews.append(
|
|
343
|
+
SpanPreview(
|
|
344
|
+
name=child_fields.get("name") or f"observation-{i}",
|
|
345
|
+
type=child_fields.get("type"),
|
|
346
|
+
input=child_fields.get("input"),
|
|
347
|
+
output=child_fields.get("output"),
|
|
348
|
+
model=child_fields.get("model"),
|
|
349
|
+
metadata=child_fields.get("metadata"),
|
|
350
|
+
start_time=str(child_fields.get("start_time_ns")) if child_fields.get("start_time_ns") else None,
|
|
351
|
+
end_time=str(child_fields.get("end_time_ns")) if child_fields.get("end_time_ns") else None,
|
|
352
|
+
children=nested,
|
|
353
|
+
)
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
return previews
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Utility helpers for dynamic component initialization within the trainer."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import importlib
|
|
8
|
+
import inspect
|
|
9
|
+
from typing import Any, Callable, Dict, Optional, TypeVar, Union, cast, overload
|
|
10
|
+
|
|
11
|
+
OptionalDefaults = Dict[str, Callable[[], Any] | Any]
|
|
12
|
+
T = TypeVar("T")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_class(path: str) -> type[Any]:
|
|
16
|
+
"""Load a class from its fully qualified import path."""
|
|
17
|
+
module_name, class_name = path.rsplit(".", 1)
|
|
18
|
+
module = importlib.import_module(module_name)
|
|
19
|
+
return getattr(module, class_name)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def instantiate_component(
|
|
23
|
+
cls: type[Any],
|
|
24
|
+
provided_kwargs: Optional[Dict[str, Any]] = None,
|
|
25
|
+
optional_defaults: Optional[OptionalDefaults] = None,
|
|
26
|
+
) -> Any:
|
|
27
|
+
"""Instantiate `cls`, filling optional kwargs when the constructor accepts them."""
|
|
28
|
+
kwargs = dict(provided_kwargs or {})
|
|
29
|
+
if optional_defaults:
|
|
30
|
+
signature = inspect.signature(cls.__init__)
|
|
31
|
+
for name, value in optional_defaults.items():
|
|
32
|
+
if name in kwargs or name not in signature.parameters:
|
|
33
|
+
continue
|
|
34
|
+
kwargs[name] = value() if callable(value) else value
|
|
35
|
+
return cls(**kwargs)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def instantiate_from_spec(
|
|
39
|
+
spec: Union[str, Dict[str, Any]],
|
|
40
|
+
*,
|
|
41
|
+
spec_name: str,
|
|
42
|
+
optional_defaults: Optional[OptionalDefaults] = None,
|
|
43
|
+
dict_requires_type: bool = True,
|
|
44
|
+
dict_default_cls: type[Any] | None = None,
|
|
45
|
+
registry: Optional[Dict[str, str]] = None,
|
|
46
|
+
) -> Any:
|
|
47
|
+
"""Instantiate a component from a string or dict spec."""
|
|
48
|
+
if isinstance(spec, str):
|
|
49
|
+
type_path = registry.get(spec, spec) if registry else spec
|
|
50
|
+
cls = load_class(type_path)
|
|
51
|
+
return instantiate_component(cls, optional_defaults=optional_defaults)
|
|
52
|
+
|
|
53
|
+
if isinstance(spec, dict): # pyright: ignore[reportUnnecessaryIsInstance]
|
|
54
|
+
spec_conf = dict(spec)
|
|
55
|
+
type_path = spec_conf.pop("type", None)
|
|
56
|
+
if type_path is None and registry and "name" in spec_conf:
|
|
57
|
+
type_path = registry.get(spec_conf.pop("name"))
|
|
58
|
+
elif registry and type_path is not None:
|
|
59
|
+
type_path = registry.get(type_path, type_path)
|
|
60
|
+
if type_path is None:
|
|
61
|
+
if dict_requires_type:
|
|
62
|
+
raise ValueError(f"{spec_name} dict must have a 'type' key with the class full name")
|
|
63
|
+
if dict_default_cls is None:
|
|
64
|
+
raise ValueError(f"{spec_name} dict missing 'type' and no default class provided")
|
|
65
|
+
cls = dict_default_cls
|
|
66
|
+
else:
|
|
67
|
+
cls = load_class(type_path)
|
|
68
|
+
return instantiate_component(cls, spec_conf, optional_defaults)
|
|
69
|
+
|
|
70
|
+
raise TypeError(f"{spec_name} spec must be a string or dict (got {type(spec)}).")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _ensure_expected_type(
|
|
74
|
+
instance: Any,
|
|
75
|
+
expected_type: type[T],
|
|
76
|
+
spec_name: str,
|
|
77
|
+
type_error_fmt: str | None,
|
|
78
|
+
) -> T:
|
|
79
|
+
if not isinstance(instance, expected_type):
|
|
80
|
+
type_name = str(type(instance)) # type: ignore
|
|
81
|
+
if type_error_fmt:
|
|
82
|
+
raise TypeError(type_error_fmt.format(type_name=type_name, expected_type=expected_type.__name__))
|
|
83
|
+
raise TypeError(f"{spec_name} factory returned {type_name}, which is not a {expected_type.__name__} subclass.")
|
|
84
|
+
return instance
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@overload
|
|
88
|
+
def build_component(
|
|
89
|
+
spec: Union[T, str, Dict[str, Any], type[T], Callable[[], T], None],
|
|
90
|
+
*,
|
|
91
|
+
expected_type: type[T],
|
|
92
|
+
spec_name: str,
|
|
93
|
+
default_factory: Callable[[], T],
|
|
94
|
+
allow_none: bool = ...,
|
|
95
|
+
optional_defaults: Optional[OptionalDefaults] = ...,
|
|
96
|
+
dict_requires_type: bool = ...,
|
|
97
|
+
dict_default_cls: type[T] | None = ...,
|
|
98
|
+
type_error_fmt: str | None = ...,
|
|
99
|
+
invalid_spec_error_fmt: str | None = ...,
|
|
100
|
+
registry: Optional[Dict[str, str]] = ...,
|
|
101
|
+
) -> T: ...
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@overload
|
|
105
|
+
def build_component(
|
|
106
|
+
spec: Union[T, str, Dict[str, Any], type[T], Callable[[], T], None],
|
|
107
|
+
*,
|
|
108
|
+
expected_type: type[T],
|
|
109
|
+
spec_name: str,
|
|
110
|
+
default_factory: None = ...,
|
|
111
|
+
allow_none: bool,
|
|
112
|
+
optional_defaults: Optional[OptionalDefaults] = ...,
|
|
113
|
+
dict_requires_type: bool = ...,
|
|
114
|
+
dict_default_cls: type[T] | None = ...,
|
|
115
|
+
type_error_fmt: str | None = ...,
|
|
116
|
+
invalid_spec_error_fmt: str | None = ...,
|
|
117
|
+
registry: Optional[Dict[str, str]] = ...,
|
|
118
|
+
) -> T | None: ...
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@overload
|
|
122
|
+
def build_component(
|
|
123
|
+
spec: Union[T, str, Dict[str, Any], type[T], Callable[[], T], None],
|
|
124
|
+
*,
|
|
125
|
+
expected_type: type[T],
|
|
126
|
+
spec_name: str,
|
|
127
|
+
default_factory: None = ...,
|
|
128
|
+
allow_none: bool = ...,
|
|
129
|
+
optional_defaults: Optional[OptionalDefaults] = ...,
|
|
130
|
+
dict_requires_type: bool = ...,
|
|
131
|
+
dict_default_cls: type[T] | None = ...,
|
|
132
|
+
type_error_fmt: str | None = ...,
|
|
133
|
+
invalid_spec_error_fmt: str | None = ...,
|
|
134
|
+
registry: Optional[Dict[str, str]] = ...,
|
|
135
|
+
) -> T | None: ...
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def build_component(
|
|
139
|
+
spec: Union[T, str, Dict[str, Any], type[T], Callable[[], T], None],
|
|
140
|
+
*,
|
|
141
|
+
expected_type: type[T],
|
|
142
|
+
spec_name: str,
|
|
143
|
+
default_factory: Callable[[], T] | None = None,
|
|
144
|
+
allow_none: bool = False,
|
|
145
|
+
optional_defaults: Optional[OptionalDefaults] = None,
|
|
146
|
+
dict_requires_type: bool = True,
|
|
147
|
+
dict_default_cls: type[T] | None = None,
|
|
148
|
+
type_error_fmt: str | None = None,
|
|
149
|
+
invalid_spec_error_fmt: str | None = None,
|
|
150
|
+
registry: Optional[Dict[str, str]] = None,
|
|
151
|
+
) -> T | None:
|
|
152
|
+
"""Build and return a component instance from a flexible specification.
|
|
153
|
+
|
|
154
|
+
This function provides a flexible way to create component instances from various
|
|
155
|
+
input formats including direct instances, class types, factory functions, import
|
|
156
|
+
paths, or configuration dictionaries.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
spec: The component specification. Can be:
|
|
160
|
+
- An instance of expected_type (returned as-is)
|
|
161
|
+
- A string import path (e.g., 'module.Class') or registry key
|
|
162
|
+
- A dict with 'type' key (import path or registry key) and constructor kwargs
|
|
163
|
+
- A class type (will be instantiated)
|
|
164
|
+
- A factory function (will be called)
|
|
165
|
+
- None (uses default_factory or returns None if allow_none=True)
|
|
166
|
+
expected_type: The type that the resulting instance must be or inherit from.
|
|
167
|
+
spec_name: Descriptive name for the spec, used in error messages.
|
|
168
|
+
default_factory: Optional factory function called when spec is None.
|
|
169
|
+
allow_none: If True, allows None to be returned when spec is None and
|
|
170
|
+
no default_factory is provided.
|
|
171
|
+
optional_defaults: Dict mapping parameter names to default values or factory
|
|
172
|
+
functions that will be injected if the constructor accepts them.
|
|
173
|
+
dict_requires_type: If True, dict specs must include a 'type' key.
|
|
174
|
+
dict_default_cls: Default class to use for dict specs without a 'type' key
|
|
175
|
+
(only used when dict_requires_type=False).
|
|
176
|
+
type_error_fmt: Custom format string for type validation errors. Should include
|
|
177
|
+
{type_name} and {expected_type} placeholders.
|
|
178
|
+
invalid_spec_error_fmt: Custom format string for invalid spec type errors.
|
|
179
|
+
Should include {actual_type} and {expected_type} placeholders.
|
|
180
|
+
registry: Optional mapping of short names to fully qualified import paths.
|
|
181
|
+
When provided, string specs or dict 'type'/'name' entries are first
|
|
182
|
+
resolved through this registry before attempting to import.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
An instance of expected_type, or None if allow_none=True and spec is None
|
|
186
|
+
without a default_factory.
|
|
187
|
+
|
|
188
|
+
Raises:
|
|
189
|
+
TypeError: If the instantiated object is not an instance of expected_type.
|
|
190
|
+
ValueError: If spec is None and neither default_factory nor allow_none is set,
|
|
191
|
+
or if spec type is invalid, or if dict spec is invalid.
|
|
192
|
+
|
|
193
|
+
Examples:
|
|
194
|
+
>>> # Direct instance
|
|
195
|
+
>>> optimizer = build_component(AdamW(), expected_type=Optimizer, spec_name='optimizer')
|
|
196
|
+
>>>
|
|
197
|
+
>>> # String import path
|
|
198
|
+
>>> optimizer = build_component('torch.optim.AdamW', expected_type=Optimizer, spec_name='optimizer')
|
|
199
|
+
>>>
|
|
200
|
+
>>> # Dict with type and kwargs
|
|
201
|
+
>>> spec = {'type': 'torch.optim.AdamW', 'lr': 0.001}
|
|
202
|
+
>>> optimizer = build_component(spec, expected_type=Optimizer, spec_name='optimizer')
|
|
203
|
+
>>>
|
|
204
|
+
>>> # Class type
|
|
205
|
+
>>> optimizer = build_component(AdamW, expected_type=Optimizer, spec_name='optimizer')
|
|
206
|
+
>>>
|
|
207
|
+
>>> # Factory function
|
|
208
|
+
>>> optimizer = build_component(lambda: AdamW(lr=0.001), expected_type=Optimizer,
|
|
209
|
+
... spec_name='optimizer')
|
|
210
|
+
"""
|
|
211
|
+
if isinstance(spec, expected_type):
|
|
212
|
+
return cast(T, spec)
|
|
213
|
+
|
|
214
|
+
if spec is None:
|
|
215
|
+
if default_factory is not None:
|
|
216
|
+
instance = default_factory()
|
|
217
|
+
return _ensure_expected_type(instance, expected_type, spec_name, type_error_fmt)
|
|
218
|
+
if allow_none:
|
|
219
|
+
return None
|
|
220
|
+
raise ValueError(
|
|
221
|
+
invalid_spec_error_fmt.format(actual_type=type(spec), expected_type=expected_type.__name__)
|
|
222
|
+
if invalid_spec_error_fmt
|
|
223
|
+
else f"{spec_name} cannot be None."
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
if isinstance(spec, type) and issubclass(spec, expected_type):
|
|
227
|
+
instance = instantiate_component(spec, optional_defaults=optional_defaults)
|
|
228
|
+
return _ensure_expected_type(instance, expected_type, spec_name, type_error_fmt)
|
|
229
|
+
|
|
230
|
+
if callable(spec) and not isinstance(spec, type): # type: ignore
|
|
231
|
+
instance = spec()
|
|
232
|
+
return _ensure_expected_type(instance, expected_type, spec_name, type_error_fmt)
|
|
233
|
+
|
|
234
|
+
if isinstance(spec, str):
|
|
235
|
+
instance = instantiate_from_spec(
|
|
236
|
+
spec,
|
|
237
|
+
spec_name=spec_name,
|
|
238
|
+
optional_defaults=optional_defaults,
|
|
239
|
+
dict_requires_type=dict_requires_type,
|
|
240
|
+
dict_default_cls=dict_default_cls,
|
|
241
|
+
registry=registry,
|
|
242
|
+
)
|
|
243
|
+
return _ensure_expected_type(instance, expected_type, spec_name, type_error_fmt)
|
|
244
|
+
|
|
245
|
+
if isinstance(spec, dict):
|
|
246
|
+
instance = instantiate_from_spec(
|
|
247
|
+
spec, # type: ignore
|
|
248
|
+
spec_name=spec_name,
|
|
249
|
+
optional_defaults=optional_defaults,
|
|
250
|
+
dict_requires_type=dict_requires_type,
|
|
251
|
+
dict_default_cls=dict_default_cls,
|
|
252
|
+
registry=registry,
|
|
253
|
+
)
|
|
254
|
+
return _ensure_expected_type(instance, expected_type, spec_name, type_error_fmt)
|
|
255
|
+
|
|
256
|
+
if invalid_spec_error_fmt:
|
|
257
|
+
raise ValueError(invalid_spec_error_fmt.format(actual_type=type(spec), expected_type=expected_type.__name__)) # type: ignore
|
|
258
|
+
|
|
259
|
+
type_name = str(type(spec)) # type: ignore
|
|
260
|
+
raise ValueError(f"Invalid {spec_name} type: {type_name}. Expected {expected_type.__name__}, str, dict, or None.")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
__all__ = ["OptionalDefaults", "build_component", "instantiate_component", "instantiate_from_spec", "load_class"]
|