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,300 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Instrumentation module for gatewaysdk.
|
|
5
|
+
|
|
6
|
+
Provides automatic metric collection and tracing for various libraries.
|
|
7
|
+
Uses a plugin architecture with an InstrumentorRegistry.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
# Enable specific instrumentors
|
|
11
|
+
gatewaysdk.instrument("openai")
|
|
12
|
+
gatewaysdk.instrument("openai", "anthropic", "langchain")
|
|
13
|
+
|
|
14
|
+
# Enable all available instrumentors
|
|
15
|
+
gatewaysdk.instrument_all()
|
|
16
|
+
|
|
17
|
+
# Disable instrumentors
|
|
18
|
+
gatewaysdk.uninstrument("openai")
|
|
19
|
+
gatewaysdk.uninstrument_all()
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import warnings
|
|
23
|
+
from typing import List, Optional
|
|
24
|
+
|
|
25
|
+
# Export base classes and registry
|
|
26
|
+
from .base import Instrumentor, MetricSchema
|
|
27
|
+
from .registry import (
|
|
28
|
+
InstrumentorRegistry,
|
|
29
|
+
)
|
|
30
|
+
from .registry import instrument as registry_instrument
|
|
31
|
+
from .registry import uninstrument as registry_uninstrument
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"Instrumentor",
|
|
35
|
+
"MetricSchema",
|
|
36
|
+
"InstrumentorRegistry",
|
|
37
|
+
"instrument",
|
|
38
|
+
"uninstrument",
|
|
39
|
+
"instrument_all",
|
|
40
|
+
"uninstrument_all",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# Legacy instrumentor availability flags
|
|
44
|
+
AGENTOPS_INSTALLED: bool = False
|
|
45
|
+
AGENTOPS_LANGCHAIN_INSTALLED: bool = False
|
|
46
|
+
LITELLM_INSTALLED: bool = False
|
|
47
|
+
VLLM_INSTALLED: bool = False
|
|
48
|
+
WEAVE_INSTALLED: bool = False
|
|
49
|
+
OPENAI_OTEL_INSTALLED: bool = False
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
from . import agentops # type: ignore
|
|
53
|
+
|
|
54
|
+
AGENTOPS_INSTALLED = True # type: ignore
|
|
55
|
+
except ImportError:
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
from . import litellm # type: ignore
|
|
60
|
+
|
|
61
|
+
LITELLM_INSTALLED = True # type: ignore
|
|
62
|
+
except ImportError:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
from opentelemetry.instrumentation.openai import OpenAIInstrumentor # type: ignore
|
|
67
|
+
|
|
68
|
+
OPENAI_OTEL_INSTALLED = True
|
|
69
|
+
except ImportError:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def instrument(*names: str, **kwargs) -> List[Optional[Instrumentor]]:
|
|
74
|
+
"""
|
|
75
|
+
Activate one or more instrumentors by name.
|
|
76
|
+
|
|
77
|
+
Uses the InstrumentorRegistry to activate instrumentors.
|
|
78
|
+
For legacy instrumentors not yet migrated to the registry,
|
|
79
|
+
falls back to direct activation.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
*names: Instrumentor names to activate
|
|
83
|
+
**kwargs: Additional arguments passed to instrumentor constructors
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
List of activated instrumentor instances (None for failed activations)
|
|
87
|
+
|
|
88
|
+
Examples:
|
|
89
|
+
# Enable OpenAI instrumentation
|
|
90
|
+
gatewaysdk.instrument("openai")
|
|
91
|
+
|
|
92
|
+
# Enable multiple instrumentors
|
|
93
|
+
gatewaysdk.instrument("openai", "anthropic", "langchain")
|
|
94
|
+
|
|
95
|
+
# Enable all available instrumentors
|
|
96
|
+
gatewaysdk.instrument_all()
|
|
97
|
+
"""
|
|
98
|
+
results = []
|
|
99
|
+
for name in names:
|
|
100
|
+
# Try registry first
|
|
101
|
+
try:
|
|
102
|
+
result = InstrumentorRegistry.instrument(name, **kwargs)
|
|
103
|
+
results.append(result)
|
|
104
|
+
except ValueError:
|
|
105
|
+
# Fall back to legacy instrumentors
|
|
106
|
+
result = _instrument_legacy(name)
|
|
107
|
+
results.append(result)
|
|
108
|
+
return results
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def uninstrument(*names: str) -> None:
|
|
112
|
+
"""
|
|
113
|
+
Deactivate one or more instrumentors by name.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
*names: Instrumentor names to deactivate
|
|
117
|
+
"""
|
|
118
|
+
for name in names:
|
|
119
|
+
# Try registry first
|
|
120
|
+
if InstrumentorRegistry.is_active(name):
|
|
121
|
+
InstrumentorRegistry.uninstrument(name)
|
|
122
|
+
else:
|
|
123
|
+
# Fall back to legacy uninstrument
|
|
124
|
+
_uninstrument_legacy(name)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _instrument_legacy(name: str) -> Optional[Instrumentor]:
|
|
128
|
+
"""Activate a legacy instrumentor by name."""
|
|
129
|
+
name_lower = name.lower()
|
|
130
|
+
|
|
131
|
+
if name_lower == "agentops" and AGENTOPS_INSTALLED:
|
|
132
|
+
from .agentops import instrument_agentops
|
|
133
|
+
|
|
134
|
+
instrument_agentops()
|
|
135
|
+
return None # Legacy doesn't return instance
|
|
136
|
+
|
|
137
|
+
if name_lower == "litellm" and LITELLM_INSTALLED:
|
|
138
|
+
from .litellm import instrument_litellm
|
|
139
|
+
|
|
140
|
+
instrument_litellm()
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
if name_lower == "vllm" and VLLM_INSTALLED:
|
|
144
|
+
from .vllm import instrument_vllm
|
|
145
|
+
|
|
146
|
+
instrument_vllm()
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
if name_lower in ("openai", "openai-otel") and OPENAI_OTEL_INSTALLED:
|
|
150
|
+
try:
|
|
151
|
+
OpenAIInstrumentor().instrument() # type: ignore
|
|
152
|
+
except Exception as e:
|
|
153
|
+
warnings.warn(f"Failed to instrument OpenAI SDK: {e}")
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
warnings.warn(f"Unknown or unavailable instrumentor: {name}")
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _uninstrument_legacy(name: str) -> None:
|
|
161
|
+
"""Deactivate a legacy instrumentor by name."""
|
|
162
|
+
name_lower = name.lower()
|
|
163
|
+
|
|
164
|
+
if name_lower == "agentops" and AGENTOPS_INSTALLED:
|
|
165
|
+
try:
|
|
166
|
+
from .agentops import uninstrument_agentops
|
|
167
|
+
|
|
168
|
+
uninstrument_agentops()
|
|
169
|
+
except ImportError:
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
elif name_lower == "litellm" and LITELLM_INSTALLED:
|
|
173
|
+
try:
|
|
174
|
+
from .litellm import uninstrument_litellm
|
|
175
|
+
|
|
176
|
+
uninstrument_litellm()
|
|
177
|
+
except ImportError:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
elif name_lower == "vllm" and VLLM_INSTALLED:
|
|
181
|
+
try:
|
|
182
|
+
from .vllm import uninstrument_vllm
|
|
183
|
+
|
|
184
|
+
uninstrument_vllm()
|
|
185
|
+
except ImportError:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
elif name_lower in ("openai", "openai-otel") and OPENAI_OTEL_INSTALLED:
|
|
189
|
+
try:
|
|
190
|
+
OpenAIInstrumentor().uninstrument() # type: ignore
|
|
191
|
+
except Exception:
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def instrument_all():
|
|
196
|
+
"""
|
|
197
|
+
Instrument all available instrumentation libraries.
|
|
198
|
+
|
|
199
|
+
This includes both registry-based instrumentors and legacy instrumentors.
|
|
200
|
+
"""
|
|
201
|
+
# First, activate all registry-based instrumentors
|
|
202
|
+
for name in InstrumentorRegistry.list_available():
|
|
203
|
+
try:
|
|
204
|
+
InstrumentorRegistry.instrument(name)
|
|
205
|
+
except Exception as e:
|
|
206
|
+
warnings.warn(f"Failed to instrument {name}: {e}")
|
|
207
|
+
|
|
208
|
+
# Then activate legacy instrumentors
|
|
209
|
+
if AGENTOPS_INSTALLED:
|
|
210
|
+
from .agentops import instrument_agentops
|
|
211
|
+
|
|
212
|
+
instrument_agentops()
|
|
213
|
+
else:
|
|
214
|
+
warnings.warn("agentops is not installed. It's therefore not instrumented.")
|
|
215
|
+
|
|
216
|
+
if LITELLM_INSTALLED:
|
|
217
|
+
from .litellm import instrument_litellm
|
|
218
|
+
|
|
219
|
+
instrument_litellm()
|
|
220
|
+
else:
|
|
221
|
+
warnings.warn("litellm is not installed. It's therefore not instrumented.")
|
|
222
|
+
|
|
223
|
+
if VLLM_INSTALLED:
|
|
224
|
+
from .vllm import instrument_vllm
|
|
225
|
+
|
|
226
|
+
instrument_vllm()
|
|
227
|
+
else:
|
|
228
|
+
warnings.warn("vllm is not installed. It's therefore not instrumented.")
|
|
229
|
+
|
|
230
|
+
if AGENTOPS_LANGCHAIN_INSTALLED:
|
|
231
|
+
from .agentops_langchain import instrument_agentops_langchain
|
|
232
|
+
|
|
233
|
+
instrument_agentops_langchain()
|
|
234
|
+
else:
|
|
235
|
+
warnings.warn("Agentops-langchain integration is not installed. It's therefore not instrumented.")
|
|
236
|
+
|
|
237
|
+
# Enable standard OpenAI instrumentation if available
|
|
238
|
+
# This allows client-side spans to be generated for OpenAI SDK calls
|
|
239
|
+
if OPENAI_OTEL_INSTALLED:
|
|
240
|
+
try:
|
|
241
|
+
OpenAIInstrumentor().instrument() # type: ignore
|
|
242
|
+
except Exception as e:
|
|
243
|
+
warnings.warn(f"Failed to instrument OpenAI SDK: {e}")
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def uninstrument_all():
|
|
247
|
+
"""
|
|
248
|
+
Uninstrument all active instrumentation libraries.
|
|
249
|
+
|
|
250
|
+
This includes both registry-based instrumentors and legacy instrumentors.
|
|
251
|
+
"""
|
|
252
|
+
# First, deactivate all registry-based instrumentors
|
|
253
|
+
InstrumentorRegistry.uninstrument_all()
|
|
254
|
+
|
|
255
|
+
# Then deactivate legacy instrumentors
|
|
256
|
+
if AGENTOPS_INSTALLED:
|
|
257
|
+
try:
|
|
258
|
+
from .agentops import uninstrument_agentops
|
|
259
|
+
|
|
260
|
+
uninstrument_agentops()
|
|
261
|
+
except ImportError:
|
|
262
|
+
warnings.warn("agentops is installed but uninstrument_agentops could not be imported.")
|
|
263
|
+
else:
|
|
264
|
+
warnings.warn("agentops is not installed. It's therefore not uninstrumented.")
|
|
265
|
+
|
|
266
|
+
if LITELLM_INSTALLED:
|
|
267
|
+
try:
|
|
268
|
+
from .litellm import uninstrument_litellm
|
|
269
|
+
|
|
270
|
+
uninstrument_litellm()
|
|
271
|
+
except ImportError:
|
|
272
|
+
warnings.warn("litellm is installed but uninstrument_litellm could not be imported.")
|
|
273
|
+
else:
|
|
274
|
+
warnings.warn("litellm is not installed. It's therefore not uninstrumented.")
|
|
275
|
+
|
|
276
|
+
if VLLM_INSTALLED:
|
|
277
|
+
try:
|
|
278
|
+
from .vllm import uninstrument_vllm
|
|
279
|
+
|
|
280
|
+
uninstrument_vllm()
|
|
281
|
+
except ImportError:
|
|
282
|
+
warnings.warn("vllm is installed but uninstrument_vllm could not be imported.")
|
|
283
|
+
else:
|
|
284
|
+
warnings.warn("vllm is not installed. It's therefore not uninstrumented.")
|
|
285
|
+
|
|
286
|
+
if AGENTOPS_LANGCHAIN_INSTALLED:
|
|
287
|
+
try:
|
|
288
|
+
from .agentops_langchain import uninstrument_agentops_langchain
|
|
289
|
+
|
|
290
|
+
uninstrument_agentops_langchain()
|
|
291
|
+
except ImportError:
|
|
292
|
+
warnings.warn("agentops_langchain is installed but uninstrument_agentops_langchain could not be imported.")
|
|
293
|
+
else:
|
|
294
|
+
warnings.warn("Agentops-langchain integration is not installed. It's therefore not uninstrumented.")
|
|
295
|
+
|
|
296
|
+
if OPENAI_OTEL_INSTALLED:
|
|
297
|
+
try:
|
|
298
|
+
OpenAIInstrumentor().uninstrument() # type: ignore
|
|
299
|
+
except Exception:
|
|
300
|
+
pass
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Any, Callable, no_type_check
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
from agentops.client.api import V3Client, V4Client
|
|
11
|
+
from agentops.client.api.types import AuthTokenResponse
|
|
12
|
+
from agentops.sdk.exporters import AuthenticatedOTLPExporter
|
|
13
|
+
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
|
|
14
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
15
|
+
from opentelemetry.sdk.metrics.export import MetricExportResult
|
|
16
|
+
|
|
17
|
+
from gatewaysdk.utils.otlp import LightningStoreOTLPExporter
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"instrument_agentops",
|
|
23
|
+
"uninstrument_agentops",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
# Module-level storage for originals
|
|
27
|
+
_original_handle_chat_attributes: Callable[..., Any] | None = None
|
|
28
|
+
_original_handle_response: Callable[..., Any] | None = None
|
|
29
|
+
_agentops_service_enabled = False
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def enable_agentops_service(enabled: bool = True) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Enable or disable communication with the AgentOps service.
|
|
35
|
+
|
|
36
|
+
By default, AgentOps exporters and clients will run in local mode
|
|
37
|
+
and will NOT attempt to communicate with the remote AgentOps service.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
enabled: If True, enable all AgentOps exporters and clients.
|
|
41
|
+
All exporters and clients will operate in normal mode and send data
|
|
42
|
+
to the [AgentOps service](https://www.agentops.ai).
|
|
43
|
+
"""
|
|
44
|
+
global _agentops_service_enabled
|
|
45
|
+
_agentops_service_enabled = enabled
|
|
46
|
+
logger.info(f"AgentOps service enabled is set to {enabled}.")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _patch_exporters():
|
|
50
|
+
import agentops.client.api
|
|
51
|
+
import agentops.sdk.core
|
|
52
|
+
|
|
53
|
+
agentops.sdk.core.AuthenticatedOTLPExporter = BypassableAuthenticatedOTLPExporter # type: ignore
|
|
54
|
+
agentops.sdk.core.OTLPMetricExporter = BypassableOTLPMetricExporter
|
|
55
|
+
if hasattr(agentops.sdk.core, "OTLPSpanExporter"):
|
|
56
|
+
agentops.sdk.core.OTLPSpanExporter = BypassableOTLPSpanExporter # type: ignore
|
|
57
|
+
agentops.client.api.V3Client = BypassableV3Client
|
|
58
|
+
agentops.client.api.V4Client = BypassableV4Client
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _unpatch_exporters():
|
|
62
|
+
import agentops.client.api
|
|
63
|
+
import agentops.sdk.core
|
|
64
|
+
|
|
65
|
+
agentops.sdk.core.AuthenticatedOTLPExporter = AuthenticatedOTLPExporter # type: ignore
|
|
66
|
+
agentops.sdk.core.OTLPMetricExporter = OTLPMetricExporter
|
|
67
|
+
if hasattr(agentops.sdk.core, "OTLPSpanExporter"):
|
|
68
|
+
agentops.sdk.core.OTLPSpanExporter = OTLPSpanExporter # type: ignore
|
|
69
|
+
agentops.client.api.V3Client = V3Client
|
|
70
|
+
agentops.client.api.V4Client = V4Client
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _unwrap_legacy_response(response: Any) -> Any:
|
|
74
|
+
if hasattr(response, "parse") and callable(response.parse):
|
|
75
|
+
return response.parse()
|
|
76
|
+
return response
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _patch_new_agentops():
|
|
80
|
+
import agentops.instrumentation.providers.openai.stream_wrapper
|
|
81
|
+
import agentops.instrumentation.providers.openai.wrappers.chat
|
|
82
|
+
from agentops.instrumentation.providers.openai.wrappers.chat import handle_chat_attributes # type: ignore
|
|
83
|
+
|
|
84
|
+
global _original_handle_chat_attributes
|
|
85
|
+
|
|
86
|
+
if _original_handle_chat_attributes is not None:
|
|
87
|
+
logger.warning("AgentOps already patched. Skipping.")
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
_original_handle_chat_attributes = handle_chat_attributes # type: ignore
|
|
91
|
+
|
|
92
|
+
@no_type_check
|
|
93
|
+
def _handle_chat_attributes_with_tokens(args=None, kwargs=None, return_value=None, **kws): # type: ignore
|
|
94
|
+
attributes = _original_handle_chat_attributes(args=args, kwargs=kwargs, return_value=return_value, **kws)
|
|
95
|
+
|
|
96
|
+
# In some cases, response is a openai._legacy_response.LegacyAPIResponse (e.g., LiteLLM, or LangChain),
|
|
97
|
+
# This is created by client.with_raw_response.create()
|
|
98
|
+
return_value = _unwrap_legacy_response(return_value)
|
|
99
|
+
|
|
100
|
+
if (
|
|
101
|
+
return_value is not None
|
|
102
|
+
and hasattr(return_value, "prompt_token_ids")
|
|
103
|
+
and return_value.prompt_token_ids is not None
|
|
104
|
+
):
|
|
105
|
+
attributes["prompt_token_ids"] = list(return_value.prompt_token_ids)
|
|
106
|
+
if (
|
|
107
|
+
return_value is not None
|
|
108
|
+
and hasattr(return_value, "response_token_ids")
|
|
109
|
+
and return_value.response_token_ids is not None
|
|
110
|
+
):
|
|
111
|
+
attributes["response_token_ids"] = list(return_value.response_token_ids[0])
|
|
112
|
+
|
|
113
|
+
# For LiteLLM Proxy (v0.2) with vLLM return_token_ids, response_token_ids now lives in choices
|
|
114
|
+
if (
|
|
115
|
+
return_value is not None
|
|
116
|
+
and hasattr(return_value, "choices")
|
|
117
|
+
and return_value.choices
|
|
118
|
+
and isinstance(return_value.choices, list)
|
|
119
|
+
and len(return_value.choices) > 0
|
|
120
|
+
):
|
|
121
|
+
first_choice = return_value.choices[0]
|
|
122
|
+
# Token IDs from "choices[0].token_ids"
|
|
123
|
+
if "response_token_ids" not in attributes:
|
|
124
|
+
if hasattr(first_choice, "token_ids") and first_choice.token_ids is not None:
|
|
125
|
+
attributes["response_token_ids"] = list(first_choice.token_ids)
|
|
126
|
+
# newer versions of OpenAI client SDK
|
|
127
|
+
elif (
|
|
128
|
+
hasattr(first_choice, "provider_specific_fields")
|
|
129
|
+
and first_choice.provider_specific_fields.get("token_ids") is not None
|
|
130
|
+
):
|
|
131
|
+
attributes["response_token_ids"] = list(first_choice.provider_specific_fields["token_ids"])
|
|
132
|
+
|
|
133
|
+
# log probability
|
|
134
|
+
# This is temporary. We need a unified convention for classifying and naming logprobs.
|
|
135
|
+
if hasattr(first_choice, "logprobs") and first_choice.logprobs is not None:
|
|
136
|
+
if hasattr(first_choice.logprobs, "content") and first_choice.logprobs.content is not None:
|
|
137
|
+
attributes["logprobs.content"] = json.dumps(
|
|
138
|
+
[logprob.model_dump() for logprob in first_choice.logprobs.content]
|
|
139
|
+
)
|
|
140
|
+
if hasattr(first_choice.logprobs, "refusal") and first_choice.logprobs.refusal is not None:
|
|
141
|
+
attributes["logprobs.refusal"] = json.dumps(
|
|
142
|
+
[logprob.model_dump() for logprob in first_choice.logprobs.refusal]
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return attributes
|
|
146
|
+
|
|
147
|
+
agentops.instrumentation.providers.openai.wrappers.chat.handle_chat_attributes = _handle_chat_attributes_with_tokens
|
|
148
|
+
agentops.instrumentation.providers.openai.stream_wrapper.handle_chat_attributes = (
|
|
149
|
+
_handle_chat_attributes_with_tokens
|
|
150
|
+
)
|
|
151
|
+
logger.info("Patched newer version of agentops using handle_chat_attributes")
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _unpatch_new_agentops():
|
|
156
|
+
import agentops.instrumentation.providers.openai.stream_wrapper
|
|
157
|
+
import agentops.instrumentation.providers.openai.wrappers.chat
|
|
158
|
+
|
|
159
|
+
global _original_handle_chat_attributes
|
|
160
|
+
if _original_handle_chat_attributes is not None:
|
|
161
|
+
agentops.instrumentation.providers.openai.wrappers.chat.handle_chat_attributes = (
|
|
162
|
+
_original_handle_chat_attributes
|
|
163
|
+
)
|
|
164
|
+
agentops.instrumentation.providers.openai.stream_wrapper.handle_chat_attributes = (
|
|
165
|
+
_original_handle_chat_attributes
|
|
166
|
+
)
|
|
167
|
+
_original_handle_chat_attributes = None
|
|
168
|
+
logger.info("Unpatched newer version of agentops using handle_chat_attributes")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _patch_old_agentops():
|
|
172
|
+
import opentelemetry.instrumentation.openai.shared.chat_wrappers # type: ignore
|
|
173
|
+
from opentelemetry.instrumentation.openai.shared.chat_wrappers import _handle_response, dont_throw # type: ignore
|
|
174
|
+
|
|
175
|
+
global _original_handle_response
|
|
176
|
+
_original_handle_response = _handle_response # type: ignore
|
|
177
|
+
|
|
178
|
+
@dont_throw # type: ignore
|
|
179
|
+
def _handle_response_with_tokens(response, span, *args, **kwargs): # type: ignore
|
|
180
|
+
_original_handle_response(response, span, *args, **kwargs) # type: ignore
|
|
181
|
+
if hasattr(response, "prompt_token_ids"): # type: ignore
|
|
182
|
+
span.set_attribute("prompt_token_ids", list(response.prompt_token_ids)) # type: ignore
|
|
183
|
+
if hasattr(response, "response_token_ids"): # type: ignore
|
|
184
|
+
span.set_attribute("response_token_ids", list(response.response_token_ids[0])) # type: ignore
|
|
185
|
+
|
|
186
|
+
# For LiteLLM, response is a openai._legacy_response.LegacyAPIResponse
|
|
187
|
+
if hasattr(response, "http_response") and hasattr(response.http_response, "json"): # type: ignore
|
|
188
|
+
json_data = response.http_response.json() # type: ignore
|
|
189
|
+
if isinstance(json_data, dict):
|
|
190
|
+
if "prompt_token_ids" in json_data:
|
|
191
|
+
span.set_attribute("prompt_token_ids", list(json_data["prompt_token_ids"])) # type: ignore
|
|
192
|
+
if "response_token_ids" in json_data:
|
|
193
|
+
span.set_attribute("response_token_ids", list(json_data["response_token_ids"][0])) # type: ignore
|
|
194
|
+
|
|
195
|
+
opentelemetry.instrumentation.openai.shared.chat_wrappers._handle_response = _handle_response_with_tokens # type: ignore
|
|
196
|
+
logger.info("Patched earlier version of agentops using _handle_response")
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _unpatch_old_agentops():
|
|
201
|
+
import opentelemetry.instrumentation.openai.shared.chat_wrappers # type: ignore
|
|
202
|
+
|
|
203
|
+
global _original_handle_response
|
|
204
|
+
if _original_handle_response is not None:
|
|
205
|
+
opentelemetry.instrumentation.openai.shared.chat_wrappers._handle_response = _original_handle_response # type: ignore
|
|
206
|
+
_original_handle_response = None
|
|
207
|
+
logger.info("Unpatched earlier version of agentops using _handle_response")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def instrument_agentops():
|
|
211
|
+
"""
|
|
212
|
+
Instrument agentops to capture token IDs.
|
|
213
|
+
Automatically detects and uses the appropriate patching method based on the installed agentops version.
|
|
214
|
+
"""
|
|
215
|
+
_patch_exporters()
|
|
216
|
+
|
|
217
|
+
# Try newest version first (tested for 0.4.16)
|
|
218
|
+
try:
|
|
219
|
+
return _patch_new_agentops()
|
|
220
|
+
except ImportError as e:
|
|
221
|
+
logger.debug(f"Couldn't patch newer version of agentops: {str(e)}")
|
|
222
|
+
|
|
223
|
+
# Note: 0.4.15 needs another patching method, but it's too shortlived to be worth handling separately.
|
|
224
|
+
|
|
225
|
+
# Try older version (tested for 0.4.13)
|
|
226
|
+
try:
|
|
227
|
+
return _patch_old_agentops()
|
|
228
|
+
except ImportError as e:
|
|
229
|
+
logger.warning(f"Couldn't patch older version of agentops: {str(e)}")
|
|
230
|
+
logger.error("Failed to instrument agentops - neither patching method was successful")
|
|
231
|
+
return False
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def uninstrument_agentops():
|
|
235
|
+
"""Uninstrument agentops to stop capturing token IDs."""
|
|
236
|
+
_unpatch_exporters()
|
|
237
|
+
|
|
238
|
+
try:
|
|
239
|
+
_unpatch_new_agentops()
|
|
240
|
+
except Exception:
|
|
241
|
+
pass
|
|
242
|
+
try:
|
|
243
|
+
_unpatch_old_agentops()
|
|
244
|
+
except Exception:
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class BypassableAuthenticatedOTLPExporter(LightningStoreOTLPExporter, AuthenticatedOTLPExporter):
|
|
249
|
+
"""
|
|
250
|
+
AuthenticatedOTLPExporter with switchable service control.
|
|
251
|
+
|
|
252
|
+
When `_agentops_service_enabled` is False, skip export and return success.
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
def should_bypass(self) -> bool:
|
|
256
|
+
return not _agentops_service_enabled
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class BypassableOTLPMetricExporter(OTLPMetricExporter):
|
|
260
|
+
"""
|
|
261
|
+
OTLPMetricExporter with switchable service control.
|
|
262
|
+
When `_agentops_service_enabled` is False, skip export and return success.
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
def export(self, *args: Any, **kwargs: Any) -> MetricExportResult:
|
|
266
|
+
if _agentops_service_enabled:
|
|
267
|
+
return super().export(*args, **kwargs) # type: ignore[reportUnknownMemberType]
|
|
268
|
+
else:
|
|
269
|
+
logger.debug("SwitchableOTLPMetricExporter is switched off, skipping export.")
|
|
270
|
+
return MetricExportResult.SUCCESS
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class BypassableOTLPSpanExporter(LightningStoreOTLPExporter):
|
|
274
|
+
"""
|
|
275
|
+
OTLPSpanExporter with switchable service control.
|
|
276
|
+
When `_agentops_service_enabled` is False, skip export and return success.
|
|
277
|
+
|
|
278
|
+
This is used instead of BypassableAuthenticatedOTLPExporter on legacy AgentOps versions.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
def should_bypass(self) -> bool:
|
|
282
|
+
return not _agentops_service_enabled
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class BypassableV3Client(V3Client):
|
|
286
|
+
"""
|
|
287
|
+
V3Client with toggleable authentication calls.
|
|
288
|
+
Returns dummy auth response when `_agentops_service_enabled` is False.
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
# Temporary synchronous override of fetch_auth_token for mock purposes.
|
|
292
|
+
def fetch_auth_token(self, *args: Any, **kwargs: Any) -> AuthTokenResponse: # type: ignore[override]
|
|
293
|
+
if _agentops_service_enabled:
|
|
294
|
+
return super().fetch_auth_token(*args, **kwargs) # type: ignore[override]
|
|
295
|
+
else:
|
|
296
|
+
logger.debug("SwitchableV3Client is switched off, skipping fetch_auth_token request.")
|
|
297
|
+
return AuthTokenResponse(token="dummy", project_id="dummy")
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class BypassableV4Client(V4Client):
|
|
301
|
+
"""
|
|
302
|
+
V4Client with toggleable post requests.
|
|
303
|
+
Returns dummy response when `_agentops_service_enabled` is False.
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
def post(self, *args: Any, **kwargs: Any) -> requests.Response:
|
|
307
|
+
if _agentops_service_enabled:
|
|
308
|
+
return super().post(*args, **kwargs)
|
|
309
|
+
else:
|
|
310
|
+
logger.debug("SwitchableV4Client is switched off, skipping post request.")
|
|
311
|
+
response = requests.Response()
|
|
312
|
+
response.status_code = 200
|
|
313
|
+
response._content = b"{}"
|
|
314
|
+
return response
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
|
|
5
|
+
from agentops import instrumentation
|
|
6
|
+
from agentops.integration.callbacks.langchain import LangchainCallbackHandler
|
|
7
|
+
|
|
8
|
+
original_on_chain_start = LangchainCallbackHandler.on_chain_start
|
|
9
|
+
langgraph_entry = None
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"instrument_agentops_langchain",
|
|
13
|
+
"uninstrument_agentops_langchain",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def on_chain_start(self: Any, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any) -> None:
|
|
18
|
+
if "name" in kwargs:
|
|
19
|
+
if serialized is None: # type: ignore
|
|
20
|
+
serialized = {}
|
|
21
|
+
serialized = serialized.copy()
|
|
22
|
+
serialized["name"] = kwargs["name"]
|
|
23
|
+
if "run_id" in kwargs:
|
|
24
|
+
if serialized is None: # type: ignore
|
|
25
|
+
serialized = {}
|
|
26
|
+
serialized = serialized.copy()
|
|
27
|
+
if "id" not in serialized:
|
|
28
|
+
serialized["id"] = kwargs["run_id"]
|
|
29
|
+
return original_on_chain_start(self, serialized, inputs, **kwargs)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def instrument_agentops_langchain():
|
|
33
|
+
"""Bypass AgentOp's native support for Langchain."""
|
|
34
|
+
global langgraph_entry
|
|
35
|
+
langgraph_entry = instrumentation.AGENTIC_LIBRARIES.pop("langgraph", None)
|
|
36
|
+
LangchainCallbackHandler.on_chain_start = on_chain_start
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def uninstrument_agentops_langchain():
|
|
40
|
+
"""Restore AgentOp's native support for Langchain."""
|
|
41
|
+
global langgraph_entry
|
|
42
|
+
if langgraph_entry is not None:
|
|
43
|
+
instrumentation.AGENTIC_LIBRARIES["langgraph"] = langgraph_entry
|
|
44
|
+
langgraph_entry = None
|
|
45
|
+
LangchainCallbackHandler.on_chain_start = original_on_chain_start
|