agent-learning-kit 0.1.0__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.
- agent_learning_kit-0.1.0.dist-info/METADATA +381 -0
- agent_learning_kit-0.1.0.dist-info/RECORD +642 -0
- agent_learning_kit-0.1.0.dist-info/WHEEL +4 -0
- agent_learning_kit-0.1.0.dist-info/entry_points.txt +5 -0
- agent_learning_kit-0.1.0.dist-info/licenses/LICENSE +173 -0
- agent_learning_kit-0.1.0.dist-info/licenses/NOTICE +7 -0
- fi/__init__.py +5 -0
- fi/alk/__init__.py +57 -0
- fi/alk/_facade.py +31 -0
- fi/alk/_module_alias.py +68 -0
- fi/alk/_paths.py +14 -0
- fi/alk/_schema.py +522 -0
- fi/alk/actions.py +727 -0
- fi/alk/bench/__init__.py +517 -0
- fi/alk/bench/_codeexec.py +213 -0
- fi/alk/bench/_coding.py +215 -0
- fi/alk/bench/_docker.py +237 -0
- fi/alk/bench/_grader.py +286 -0
- fi/alk/bench/_pull.py +212 -0
- fi/alk/bench/_voice.py +147 -0
- fi/alk/capabilities.py +627 -0
- fi/alk/cli.py +6396 -0
- fi/alk/config.py +130 -0
- fi/alk/cua_loop.py +562 -0
- fi/alk/evals.py +2351 -0
- fi/alk/extensions.py +163 -0
- fi/alk/harness/ARCHITECTURE.md +231 -0
- fi/alk/harness/DESIGN.md +246 -0
- fi/alk/harness/ENVIRONMENT_CONFORMANCE.md +127 -0
- fi/alk/harness/HOW-IT-WORKS.md +297 -0
- fi/alk/harness/IMPLEMENTATION_AND_VALIDATION_STATUS.md +229 -0
- fi/alk/harness/README.md +417 -0
- fi/alk/harness/__init__.py +77 -0
- fi/alk/harness/__main__.py +3 -0
- fi/alk/harness/amend.py +312 -0
- fi/alk/harness/artifacts.py +319 -0
- fi/alk/harness/authoring_entrypoint.py +189 -0
- fi/alk/harness/authoring_runtime_validation.py +267 -0
- fi/alk/harness/backends/README.md +43 -0
- fi/alk/harness/backends/__init__.py +122 -0
- fi/alk/harness/backends/base.py +241 -0
- fi/alk/harness/backends/claude.py +211 -0
- fi/alk/harness/backends/files.py +182 -0
- fi/alk/harness/backends/vertex_gemini.py +457 -0
- fi/alk/harness/background_noise.py +95 -0
- fi/alk/harness/build.py +385 -0
- fi/alk/harness/bundle.py +593 -0
- fi/alk/harness/bundle_author_v2.py +1831 -0
- fi/alk/harness/bundle_v2.py +719 -0
- fi/alk/harness/call_runner.py +1440 -0
- fi/alk/harness/callback_http_adapter.py +111 -0
- fi/alk/harness/catalogue.py +287 -0
- fi/alk/harness/chat.py +428 -0
- fi/alk/harness/chat_call_runner.py +506 -0
- fi/alk/harness/checks.py +136 -0
- fi/alk/harness/cli.py +1354 -0
- fi/alk/harness/config.py +338 -0
- fi/alk/harness/contract.py +718 -0
- fi/alk/harness/credentials.py +674 -0
- fi/alk/harness/data/persona_vocabulary.json +111 -0
- fi/alk/harness/environment.py +99 -0
- fi/alk/harness/environment_plan.py +168 -0
- fi/alk/harness/events.py +125 -0
- fi/alk/harness/executor.py +304 -0
- fi/alk/harness/folder.py +234 -0
- fi/alk/harness/generated_runtime.py +815 -0
- fi/alk/harness/github.py +72 -0
- fi/alk/harness/hosted_authoring_entrypoint.py +183 -0
- fi/alk/harness/hosted_entrypoint.py +2402 -0
- fi/alk/harness/hosted_scheduler.py +2218 -0
- fi/alk/harness/job.py +426 -0
- fi/alk/harness/judge.py +184 -0
- fi/alk/harness/livekit_source.py +50 -0
- fi/alk/harness/livekit_tool_trace_bootstrap.py +71 -0
- fi/alk/harness/observability.py +208 -0
- fi/alk/harness/outbound.py +3252 -0
- fi/alk/harness/packaging.py +515 -0
- fi/alk/harness/persona_guides.py +157 -0
- fi/alk/harness/platform.py +692 -0
- fi/alk/harness/process_preflight.py +764 -0
- fi/alk/harness/process_runtime.py +5670 -0
- fi/alk/harness/prove.py +425 -0
- fi/alk/harness/provider_import.py +703 -0
- fi/alk/harness/provider_lifecycle.py +392 -0
- fi/alk/harness/provision.py +2896 -0
- fi/alk/harness/reception.py +147 -0
- fi/alk/harness/retell_chat_call_runner.py +373 -0
- fi/alk/harness/run/__init__.py +296 -0
- fi/alk/harness/run/alk.py +184 -0
- fi/alk/harness/run/call.py +162 -0
- fi/alk/harness/run/conversation.py +264 -0
- fi/alk/harness/run/data/voices_by_language_and_gender.json +693 -0
- fi/alk/harness/run/evidence.py +195 -0
- fi/alk/harness/run/grade.py +598 -0
- fi/alk/harness/run/live.py +297 -0
- fi/alk/harness/run/models.py +56 -0
- fi/alk/harness/run/platform_evals.py +227 -0
- fi/alk/harness/run/sdk_voice.py +130 -0
- fi/alk/harness/run/simulation.py +1209 -0
- fi/alk/harness/run/stage.py +91 -0
- fi/alk/harness/run/targets.py +508 -0
- fi/alk/harness/run/tools.py +601 -0
- fi/alk/harness/run/voice.py +340 -0
- fi/alk/harness/runtime.py +172 -0
- fi/alk/harness/sandbox_server.py +2011 -0
- fi/alk/harness/sandbox_worker.py +44 -0
- fi/alk/harness/scenario.py +1048 -0
- fi/alk/harness/scenario_source.py +879 -0
- fi/alk/harness/scenario_tools.py +1143 -0
- fi/alk/harness/scenarios.py +915 -0
- fi/alk/harness/secrets.py +168 -0
- fi/alk/harness/service_catalog.py +97 -0
- fi/alk/harness/session.py +391 -0
- fi/alk/harness/sessions.py +372 -0
- fi/alk/harness/simulator.py +76 -0
- fi/alk/harness/simulator_voice.py +928 -0
- fi/alk/harness/skills/build-environment/SKILL.md +538 -0
- fi/alk/harness/skills/harness.md +131 -0
- fi/alk/harness/skills/kinds/chat.md +48 -0
- fi/alk/harness/skills/kinds/voice-voicemail.md +63 -0
- fi/alk/harness/skills/kinds/voice.md +59 -0
- fi/alk/harness/skills/plan-suite/SKILL.md +103 -0
- fi/alk/harness/skills/provision-environment/SKILL.md +136 -0
- fi/alk/harness/skills/run-scenarios/SKILL.md +112 -0
- fi/alk/harness/skills/understand-agent/SKILL.md +251 -0
- fi/alk/harness/skills/write-scenarios/SKILL.md +606 -0
- fi/alk/harness/skills/write-scenarios/references/refusals.md +28 -0
- fi/alk/harness/skills/write-scenarios/references/world-api.md +92 -0
- fi/alk/harness/source_data_invariants.py +444 -0
- fi/alk/harness/source_tool_evidence.py +79 -0
- fi/alk/harness/sources.py +253 -0
- fi/alk/harness/spend.py +140 -0
- fi/alk/harness/tool_trace_proxy.py +104 -0
- fi/alk/harness/tools.py +1018 -0
- fi/alk/harness/understand.py +169 -0
- fi/alk/harness/voicemail_audio.py +74 -0
- fi/alk/harness/world/__init__.py +33 -0
- fi/alk/harness/world/errors.py +68 -0
- fi/alk/harness/world/expectations.py +91 -0
- fi/alk/harness/world/handle.py +538 -0
- fi/alk/harness/world/kinds.py +196 -0
- fi/alk/harness/world/mutate.py +186 -0
- fi/alk/harness/world/probe.py +413 -0
- fi/alk/harness/world/provision.py +511 -0
- fi/alk/harness/world/provisioned.py +191 -0
- fi/alk/harness/world/runtime.py +616 -0
- fi/alk/harness/world/snapshot.py +288 -0
- fi/alk/harness/world/stores/__init__.py +305 -0
- fi/alk/harness/world/stores/container.py +215 -0
- fi/alk/harness/world/stores/inprocess.py +346 -0
- fi/alk/harness/world/stores/postgres.py +481 -0
- fi/alk/harness/world/stores/prove.py +202 -0
- fi/alk/harness/world/stores/sqlite.py +245 -0
- fi/alk/harness/world/stores/written.py +182 -0
- fi/alk/harness/world/tools.py +1516 -0
- fi/alk/harness/world/workspace.py +144 -0
- fi/alk/image_loop.py +453 -0
- fi/alk/image_perturb.py +241 -0
- fi/alk/improve.py +274 -0
- fi/alk/live/__init__.py +154 -0
- fi/alk/live/_attribution.py +184 -0
- fi/alk/live/_capture.py +264 -0
- fi/alk/live/_codec.py +391 -0
- fi/alk/live/_contract.py +134 -0
- fi/alk/live/_loopback.py +316 -0
- fi/alk/live/_perturb.py +449 -0
- fi/alk/live/_runner.py +386 -0
- fi/alk/live/_stats.py +561 -0
- fi/alk/live/_transcript.py +240 -0
- fi/alk/live/_workers/__init__.py +9 -0
- fi/alk/live/_workers/a2a_worker.py +316 -0
- fi/alk/live/_workers/langgraph_worker.py +217 -0
- fi/alk/live/_workers/livekit_worker.py +207 -0
- fi/alk/live/_workers/mcp_loopback_server.py +46 -0
- fi/alk/live/_workers/mcp_worker.py +158 -0
- fi/alk/live/_workers/pipecat_worker.py +189 -0
- fi/alk/live/a2a_lane.py +138 -0
- fi/alk/live/langgraph_lane.py +339 -0
- fi/alk/live/livekit_lane.py +376 -0
- fi/alk/live/mcp_lane.py +172 -0
- fi/alk/live/pipecat_lane.py +341 -0
- fi/alk/live/voice_redteam.py +494 -0
- fi/alk/loss.py +306 -0
- fi/alk/optimize.py +36260 -0
- fi/alk/practice/__init__.py +51 -0
- fi/alk/practice/_assess.py +103 -0
- fi/alk/practice/_budget.py +81 -0
- fi/alk/practice/_calibrate.py +69 -0
- fi/alk/practice/_capstone.py +86 -0
- fi/alk/practice/_contract.py +91 -0
- fi/alk/practice/_diagnose.py +79 -0
- fi/alk/practice/_drill.py +196 -0
- fi/alk/practice/_experiment.py +720 -0
- fi/alk/practice/_schedule.py +102 -0
- fi/alk/practice/_store.py +194 -0
- fi/alk/practice/_trainer.py +245 -0
- fi/alk/practice/_update.py +125 -0
- fi/alk/redteam.py +2621 -0
- fi/alk/rewardhack.py +237 -0
- fi/alk/simulate.py +10351 -0
- fi/alk/studio/__init__.py +82 -0
- fi/alk/studio/_bias.py +314 -0
- fi/alk/studio/_calibration.py +522 -0
- fi/alk/studio/_coverage.py +262 -0
- fi/alk/studio/_download.py +665 -0
- fi/alk/studio/_fidelity_attack.py +114 -0
- fi/alk/studio/_generate.py +652 -0
- fi/alk/studio/_library.py +370 -0
- fi/alk/studio/_scan.py +134 -0
- fi/alk/studio/_upgrade.py +42 -0
- fi/alk/studio/_vendor.py +172 -0
- fi/alk/suite.py +4200 -0
- fi/alk/tasks.py +828 -0
- fi/alk/telemetry/__init__.py +149 -0
- fi/alk/telemetry/_contract.py +141 -0
- fi/alk/telemetry/_emit.py +182 -0
- fi/alk/telemetry/_ledger.py +296 -0
- fi/alk/telemetry/_queue.py +127 -0
- fi/alk/telemetry/_row.py +294 -0
- fi/alk/telemetry/_run.py +233 -0
- fi/alk/telemetry/_sync.py +193 -0
- fi/alk/telemetry/_url.py +119 -0
- fi/alk/trinity.py +49397 -0
- fi/alk/voice_loop.py +174 -0
- fi/api/__init__.py +1 -0
- fi/api/auth.py +137 -0
- fi/api/types.py +29 -0
- fi/cli/__init__.py +9 -0
- fi/cli/assertions/__init__.py +25 -0
- fi/cli/assertions/conditions.py +76 -0
- fi/cli/assertions/evaluator.py +286 -0
- fi/cli/assertions/exit_codes.py +20 -0
- fi/cli/assertions/parser.py +131 -0
- fi/cli/assertions/reporter.py +194 -0
- fi/cli/commands/__init__.py +9 -0
- fi/cli/commands/config.py +165 -0
- fi/cli/commands/export.py +208 -0
- fi/cli/commands/init.py +112 -0
- fi/cli/commands/list_cmd.py +213 -0
- fi/cli/commands/run.py +486 -0
- fi/cli/commands/validate.py +173 -0
- fi/cli/commands/view.py +424 -0
- fi/cli/config/__init__.py +6 -0
- fi/cli/config/defaults.py +206 -0
- fi/cli/config/loader.py +155 -0
- fi/cli/config/schema.py +174 -0
- fi/cli/main.py +78 -0
- fi/cli/output/__init__.py +6 -0
- fi/cli/output/formatters.py +106 -0
- fi/cli/output/reporters.py +46 -0
- fi/cli/storage/__init__.py +5 -0
- fi/cli/storage/run_history.py +249 -0
- fi/cli/utils/__init__.py +5 -0
- fi/cli/utils/console.py +44 -0
- fi/evals/__init__.py +131 -0
- fi/evals/autoeval/__init__.py +137 -0
- fi/evals/autoeval/analyzer.py +211 -0
- fi/evals/autoeval/config.py +244 -0
- fi/evals/autoeval/export.py +213 -0
- fi/evals/autoeval/interactive.py +283 -0
- fi/evals/autoeval/pipeline.py +625 -0
- fi/evals/autoeval/prompts.py +139 -0
- fi/evals/autoeval/recommender.py +242 -0
- fi/evals/autoeval/rules.py +589 -0
- fi/evals/autoeval/templates.py +299 -0
- fi/evals/autoeval/types.py +232 -0
- fi/evals/core/__init__.py +16 -0
- fi/evals/core/cloud_registry.py +184 -0
- fi/evals/core/engines.py +368 -0
- fi/evals/core/evaluate.py +319 -0
- fi/evals/core/judge_prompt.py +90 -0
- fi/evals/core/prompt_generator.py +83 -0
- fi/evals/core/registry.py +57 -0
- fi/evals/core/result.py +55 -0
- fi/evals/evaluator.py +721 -0
- fi/evals/execution.py +168 -0
- fi/evals/feedback/__init__.py +32 -0
- fi/evals/feedback/calibrator.py +160 -0
- fi/evals/feedback/collector.py +214 -0
- fi/evals/feedback/hooks.py +81 -0
- fi/evals/feedback/retriever.py +128 -0
- fi/evals/feedback/store.py +272 -0
- fi/evals/feedback/types.py +99 -0
- fi/evals/framework/README.md +79 -0
- fi/evals/framework/__init__.py +267 -0
- fi/evals/framework/backends/Dockerfile.eval-runner +33 -0
- fi/evals/framework/backends/__init__.py +99 -0
- fi/evals/framework/backends/_container.py +141 -0
- fi/evals/framework/backends/_utils.py +145 -0
- fi/evals/framework/backends/base.py +223 -0
- fi/evals/framework/backends/celery_backend.py +417 -0
- fi/evals/framework/backends/celery_worker.py +78 -0
- fi/evals/framework/backends/kubernetes_backend.py +665 -0
- fi/evals/framework/backends/ray_backend.py +521 -0
- fi/evals/framework/backends/temporal.py +350 -0
- fi/evals/framework/backends/temporal_worker.py +126 -0
- fi/evals/framework/backends/thread_pool.py +286 -0
- fi/evals/framework/context.py +258 -0
- fi/evals/framework/enrichment.py +306 -0
- fi/evals/framework/evals/__init__.py +68 -0
- fi/evals/framework/evals/agentic.py +399 -0
- fi/evals/framework/evals/builder.py +609 -0
- fi/evals/framework/evals/semantic.py +142 -0
- fi/evals/framework/evaluator.py +647 -0
- fi/evals/framework/evaluators/__init__.py +22 -0
- fi/evals/framework/evaluators/blocking.py +347 -0
- fi/evals/framework/evaluators/non_blocking.py +577 -0
- fi/evals/framework/propagation.py +421 -0
- fi/evals/framework/protocols.py +385 -0
- fi/evals/framework/registry.py +370 -0
- fi/evals/framework/resilience/__init__.py +150 -0
- fi/evals/framework/resilience/circuit_breaker.py +309 -0
- fi/evals/framework/resilience/degradation.py +355 -0
- fi/evals/framework/resilience/health.py +505 -0
- fi/evals/framework/resilience/rate_limiter.py +228 -0
- fi/evals/framework/resilience/retry.py +274 -0
- fi/evals/framework/resilience/types.py +288 -0
- fi/evals/framework/resilience/wrapper.py +433 -0
- fi/evals/framework/types.py +218 -0
- fi/evals/guardrails/README.md +915 -0
- fi/evals/guardrails/__init__.py +96 -0
- fi/evals/guardrails/backends/__init__.py +43 -0
- fi/evals/guardrails/backends/azure.py +361 -0
- fi/evals/guardrails/backends/base.py +88 -0
- fi/evals/guardrails/backends/generic_llm.py +163 -0
- fi/evals/guardrails/backends/granite.py +216 -0
- fi/evals/guardrails/backends/llamaguard.py +221 -0
- fi/evals/guardrails/backends/local_base.py +479 -0
- fi/evals/guardrails/backends/openai.py +365 -0
- fi/evals/guardrails/backends/qwen.py +170 -0
- fi/evals/guardrails/backends/shieldgemma.py +154 -0
- fi/evals/guardrails/backends/turing.py +235 -0
- fi/evals/guardrails/backends/vllm_client.py +321 -0
- fi/evals/guardrails/backends/wildguard.py +188 -0
- fi/evals/guardrails/base.py +888 -0
- fi/evals/guardrails/config.py +221 -0
- fi/evals/guardrails/discovery.py +243 -0
- fi/evals/guardrails/gateway.py +437 -0
- fi/evals/guardrails/registry.py +231 -0
- fi/evals/guardrails/scanners/__init__.py +127 -0
- fi/evals/guardrails/scanners/base.py +191 -0
- fi/evals/guardrails/scanners/code_injection.py +243 -0
- fi/evals/guardrails/scanners/eval_delegate.py +574 -0
- fi/evals/guardrails/scanners/invisible_chars.py +351 -0
- fi/evals/guardrails/scanners/jailbreak.py +412 -0
- fi/evals/guardrails/scanners/language.py +288 -0
- fi/evals/guardrails/scanners/pipeline.py +260 -0
- fi/evals/guardrails/scanners/regex.py +311 -0
- fi/evals/guardrails/scanners/secrets.py +274 -0
- fi/evals/guardrails/scanners/topics.py +649 -0
- fi/evals/guardrails/scanners/urls.py +341 -0
- fi/evals/guardrails/types.py +96 -0
- fi/evals/llm/__init__.py +3 -0
- fi/evals/llm/base_llm_provider.py +35 -0
- fi/evals/llm/providers/litellm.py +70 -0
- fi/evals/local/__init__.py +90 -0
- fi/evals/local/evaluator.py +690 -0
- fi/evals/local/execution_mode.py +121 -0
- fi/evals/local/llm.py +489 -0
- fi/evals/local/metrics/__init__.py +19 -0
- fi/evals/local/registry.py +360 -0
- fi/evals/manager.py +1018 -0
- fi/evals/manager_types.py +362 -0
- fi/evals/metrics/__init__.py +185 -0
- fi/evals/metrics/agents/__init__.py +74 -0
- fi/evals/metrics/agents/metrics.py +693 -0
- fi/evals/metrics/agents/report.py +36463 -0
- fi/evals/metrics/agents/types.py +160 -0
- fi/evals/metrics/base_llm_metric.py +111 -0
- fi/evals/metrics/base_metric.py +138 -0
- fi/evals/metrics/code_security/__init__.py +305 -0
- fi/evals/metrics/code_security/analyzer.py +985 -0
- fi/evals/metrics/code_security/benchmarks/__init__.py +73 -0
- fi/evals/metrics/code_security/benchmarks/builtin.py +750 -0
- fi/evals/metrics/code_security/benchmarks/loader.py +580 -0
- fi/evals/metrics/code_security/benchmarks/types.py +308 -0
- fi/evals/metrics/code_security/detectors/__init__.py +186 -0
- fi/evals/metrics/code_security/detectors/base.py +394 -0
- fi/evals/metrics/code_security/detectors/cryptography.py +345 -0
- fi/evals/metrics/code_security/detectors/injection.py +744 -0
- fi/evals/metrics/code_security/detectors/secrets.py +287 -0
- fi/evals/metrics/code_security/detectors/serialization.py +192 -0
- fi/evals/metrics/code_security/joint_metrics.py +588 -0
- fi/evals/metrics/code_security/judges/__init__.py +83 -0
- fi/evals/metrics/code_security/judges/base.py +238 -0
- fi/evals/metrics/code_security/judges/dual_judge.py +534 -0
- fi/evals/metrics/code_security/judges/llm_judge.py +301 -0
- fi/evals/metrics/code_security/judges/pattern_judge.py +515 -0
- fi/evals/metrics/code_security/metrics.py +388 -0
- fi/evals/metrics/code_security/modes/__init__.py +63 -0
- fi/evals/metrics/code_security/modes/adversarial.py +284 -0
- fi/evals/metrics/code_security/modes/autocomplete.py +198 -0
- fi/evals/metrics/code_security/modes/base.py +283 -0
- fi/evals/metrics/code_security/modes/instruct.py +253 -0
- fi/evals/metrics/code_security/modes/repair.py +230 -0
- fi/evals/metrics/code_security/reports/__init__.py +57 -0
- fi/evals/metrics/code_security/reports/generator.py +404 -0
- fi/evals/metrics/code_security/reports/leaderboard.py +509 -0
- fi/evals/metrics/code_security/types.py +534 -0
- fi/evals/metrics/function_calling/__init__.py +34 -0
- fi/evals/metrics/function_calling/metrics.py +573 -0
- fi/evals/metrics/function_calling/types.py +87 -0
- fi/evals/metrics/hallucination/__init__.py +54 -0
- fi/evals/metrics/hallucination/detector.py +149 -0
- fi/evals/metrics/hallucination/metrics.py +390 -0
- fi/evals/metrics/hallucination/nli.py +253 -0
- fi/evals/metrics/hallucination/sentinel.py +106 -0
- fi/evals/metrics/hallucination/types.py +132 -0
- fi/evals/metrics/heuristics/aggregation_metrics.py +85 -0
- fi/evals/metrics/heuristics/json_metrics.py +87 -0
- fi/evals/metrics/heuristics/similarity_metrics.py +375 -0
- fi/evals/metrics/heuristics/string_metrics.py +391 -0
- fi/evals/metrics/llm_as_judges/__init__.py +17 -0
- fi/evals/metrics/llm_as_judges/custom_judge/metric.py +112 -0
- fi/evals/metrics/llm_as_judges/custom_judge/prompts.py +26 -0
- fi/evals/metrics/llm_as_judges/types.py +48 -0
- fi/evals/metrics/rag/__init__.py +111 -0
- fi/evals/metrics/rag/advanced/__init__.py +14 -0
- fi/evals/metrics/rag/advanced/multi_hop.py +283 -0
- fi/evals/metrics/rag/advanced/source_attribution.py +344 -0
- fi/evals/metrics/rag/generation/__init__.py +17 -0
- fi/evals/metrics/rag/generation/answer_relevancy.py +176 -0
- fi/evals/metrics/rag/generation/context_utilization.py +245 -0
- fi/evals/metrics/rag/generation/faithfulness.py +241 -0
- fi/evals/metrics/rag/generation/groundedness.py +131 -0
- fi/evals/metrics/rag/rag_score.py +277 -0
- fi/evals/metrics/rag/retrieval/__init__.py +20 -0
- fi/evals/metrics/rag/retrieval/context_entity_recall.py +124 -0
- fi/evals/metrics/rag/retrieval/context_precision.py +158 -0
- fi/evals/metrics/rag/retrieval/context_recall.py +106 -0
- fi/evals/metrics/rag/retrieval/noise_sensitivity.py +163 -0
- fi/evals/metrics/rag/retrieval/ranking.py +261 -0
- fi/evals/metrics/rag/types.py +100 -0
- fi/evals/metrics/rag/utils/__init__.py +62 -0
- fi/evals/metrics/rag/utils/claims.py +189 -0
- fi/evals/metrics/rag/utils/entities.py +244 -0
- fi/evals/metrics/rag/utils/nli.py +92 -0
- fi/evals/metrics/rag/utils/similarity.py +345 -0
- fi/evals/metrics/structured/__init__.py +114 -0
- fi/evals/metrics/structured/field_completeness.py +313 -0
- fi/evals/metrics/structured/hierarchy_score.py +366 -0
- fi/evals/metrics/structured/json_validation.py +190 -0
- fi/evals/metrics/structured/schema_compliance.py +280 -0
- fi/evals/metrics/structured/structured_output_score.py +298 -0
- fi/evals/metrics/structured/types.py +108 -0
- fi/evals/metrics/structured/validators/__init__.py +30 -0
- fi/evals/metrics/structured/validators/base.py +189 -0
- fi/evals/metrics/structured/validators/json_validator.py +196 -0
- fi/evals/metrics/structured/validators/pydantic_validator.py +178 -0
- fi/evals/metrics/structured/validators/yaml_validator.py +248 -0
- fi/evals/otel/__init__.py +266 -0
- fi/evals/otel/config.py +400 -0
- fi/evals/otel/conventions.py +463 -0
- fi/evals/otel/enrichment.py +371 -0
- fi/evals/otel/instrumentors/__init__.py +140 -0
- fi/evals/otel/instrumentors/anthropic.py +517 -0
- fi/evals/otel/instrumentors/base.py +382 -0
- fi/evals/otel/instrumentors/openai.py +673 -0
- fi/evals/otel/processors/__init__.py +36 -0
- fi/evals/otel/processors/base.py +473 -0
- fi/evals/otel/processors/cost.py +445 -0
- fi/evals/otel/processors/evaluation.py +559 -0
- fi/evals/otel/processors/llm.py +462 -0
- fi/evals/otel/tracer.py +506 -0
- fi/evals/otel/types.py +232 -0
- fi/evals/otel_utils.py +23 -0
- fi/evals/protect.py +671 -0
- fi/evals/protect_input_adapter.py +154 -0
- fi/evals/streaming/__init__.py +88 -0
- fi/evals/streaming/buffer.py +213 -0
- fi/evals/streaming/evaluator.py +551 -0
- fi/evals/streaming/policy.py +307 -0
- fi/evals/streaming/scorers.py +368 -0
- fi/evals/streaming/types.py +238 -0
- fi/evals/templates.py +472 -0
- fi/evals/types.py +156 -0
- fi/opt/__init__.py +221 -0
- fi/opt/_objective_scoring.py +85 -0
- fi/opt/base/__init__.py +11 -0
- fi/opt/base/base_generator.py +33 -0
- fi/opt/base/base_mapper.py +26 -0
- fi/opt/base/base_optimizer.py +45 -0
- fi/opt/base/evaluator.py +211 -0
- fi/opt/components.py +3095 -0
- fi/opt/datamappers/__init__.py +3 -0
- fi/opt/datamappers/basic_mapper.py +40 -0
- fi/opt/deployment.py +1021 -0
- fi/opt/evidence.py +4332 -0
- fi/opt/generators/__init__.py +3 -0
- fi/opt/generators/litellm.py +66 -0
- fi/opt/integrations/__init__.py +23 -0
- fi/opt/integrations/generative_suite.py +410 -0
- fi/opt/integrations/simulate.py +1313 -0
- fi/opt/mutations.py +771 -0
- fi/opt/observability.py +4639 -0
- fi/opt/optimizer_trace.py +889 -0
- fi/opt/optimizers/__init__.py +80 -0
- fi/opt/optimizers/agent.py +331 -0
- fi/opt/optimizers/agent_bandit.py +392 -0
- fi/opt/optimizers/agent_curriculum.py +635 -0
- fi/opt/optimizers/agent_evolution.py +894 -0
- fi/opt/optimizers/agent_feedback.py +1863 -0
- fi/opt/optimizers/agent_pareto.py +547 -0
- fi/opt/optimizers/agent_social_memory.py +1113 -0
- fi/opt/optimizers/agent_tpe.py +321 -0
- fi/opt/optimizers/bayesian_search.py +449 -0
- fi/opt/optimizers/council.py +2075 -0
- fi/opt/optimizers/futureagi_replay.py +799 -0
- fi/opt/optimizers/gepa.py +322 -0
- fi/opt/optimizers/metaprompt.py +243 -0
- fi/opt/optimizers/promptwizard.py +417 -0
- fi/opt/optimizers/protegi.py +329 -0
- fi/opt/optimizers/random_search.py +224 -0
- fi/opt/research.py +518 -0
- fi/opt/simulation.py +260 -0
- fi/opt/targets.py +232 -0
- fi/opt/types.py +66 -0
- fi/opt/utils/__init__.py +4 -0
- fi/opt/utils/early_stopping.py +266 -0
- fi/opt/utils/setup_logging.py +82 -0
- fi/simulate/__init__.py +540 -0
- fi/simulate/_hashing.py +35 -0
- fi/simulate/_logging.py +10 -0
- fi/simulate/adapters.py +87 -0
- fi/simulate/agent/__init__.py +120 -0
- fi/simulate/agent/browser.py +658 -0
- fi/simulate/agent/definition.py +587 -0
- fi/simulate/agent/frameworks.py +3528 -0
- fi/simulate/agent/generic.py +8286 -0
- fi/simulate/agent/import_probe.py +227 -0
- fi/simulate/agent/memory.py +905 -0
- fi/simulate/agent/mocks.py +101 -0
- fi/simulate/agent/multi_agent.py +361 -0
- fi/simulate/agent/orchestration.py +903 -0
- fi/simulate/agent/realtime.py +665 -0
- fi/simulate/agent/wrapper.py +99 -0
- fi/simulate/agent/wrappers/__init__.py +18 -0
- fi/simulate/agent/wrappers/anthropic.py +62 -0
- fi/simulate/agent/wrappers/gemini.py +65 -0
- fi/simulate/agent/wrappers/http.py +404 -0
- fi/simulate/agent/wrappers/langchain.py +80 -0
- fi/simulate/agent/wrappers/openai.py +75 -0
- fi/simulate/agent/wrappers/websocket.py +326 -0
- fi/simulate/artifacts/__init__.py +11 -0
- fi/simulate/artifacts/manifest.py +62 -0
- fi/simulate/cli.py +20560 -0
- fi/simulate/endpoints/__init__.py +45 -0
- fi/simulate/endpoints/_http_actor.py +73 -0
- fi/simulate/endpoints/actor_sources.py +243 -0
- fi/simulate/endpoints/base.py +107 -0
- fi/simulate/endpoints/builtins.py +10 -0
- fi/simulate/endpoints/callable.py +95 -0
- fi/simulate/endpoints/http.py +76 -0
- fi/simulate/endpoints/livekit.py +138 -0
- fi/simulate/endpoints/originators.py +132 -0
- fi/simulate/endpoints/profiles.py +348 -0
- fi/simulate/endpoints/retell.py +633 -0
- fi/simulate/endpoints/vapi.py +205 -0
- fi/simulate/endpoints/websocket.py +76 -0
- fi/simulate/environment.py +33026 -0
- fi/simulate/environments/__init__.py +11 -0
- fi/simulate/environments/base.py +73 -0
- fi/simulate/environments/chat.py +697 -0
- fi/simulate/environments/voice.py +212 -0
- fi/simulate/evaluation/__init__.py +4 -0
- fi/simulate/evaluation/ai_eval.py +227 -0
- fi/simulate/evidence/__init__.py +35 -0
- fi/simulate/evidence/base.py +59 -0
- fi/simulate/evidence/caller_observed.py +50 -0
- fi/simulate/evidence/livekit_instrumentation.py +51 -0
- fi/simulate/evidence/livekit_room.py +50 -0
- fi/simulate/evidence/otel.py +49 -0
- fi/simulate/evidence/providers/__init__.py +24 -0
- fi/simulate/evidence/providers/base.py +61 -0
- fi/simulate/evidence/providers/retell.py +376 -0
- fi/simulate/evidence/providers/vapi.py +426 -0
- fi/simulate/hosted/__init__.py +32 -0
- fi/simulate/hosted/child_entrypoint.py +306 -0
- fi/simulate/hosted/job.py +150 -0
- fi/simulate/hosted/targets.py +53 -0
- fi/simulate/instrumentation/__init__.py +5 -0
- fi/simulate/instrumentation/livekit/__init__.py +122 -0
- fi/simulate/manifest.py +1033 -0
- fi/simulate/matrix_cli.py +165 -0
- fi/simulate/realtime/__init__.py +40 -0
- fi/simulate/realtime/events.py +107 -0
- fi/simulate/realtime/media.py +61 -0
- fi/simulate/realtime/session.py +91 -0
- fi/simulate/recording/__init__.py +5 -0
- fi/simulate/recording/room_recorder.py +326 -0
- fi/simulate/registry.py +185 -0
- fi/simulate/results/__init__.py +9 -0
- fi/simulate/results/base.py +18 -0
- fi/simulate/results/filesystem.py +71 -0
- fi/simulate/results/futureagi.py +1340 -0
- fi/simulate/runtime/__init__.py +85 -0
- fi/simulate/runtime/capabilities.py +40 -0
- fi/simulate/runtime/events.py +63 -0
- fi/simulate/runtime/failures.py +25 -0
- fi/simulate/runtime/ids.py +34 -0
- fi/simulate/runtime/plan.py +70 -0
- fi/simulate/runtime/planner.py +102 -0
- fi/simulate/runtime/report.py +174 -0
- fi/simulate/runtime/run.py +75 -0
- fi/simulate/runtime/runner.py +333 -0
- fi/simulate/runtime/spec.py +186 -0
- fi/simulate/simulation/__init__.py +30 -0
- fi/simulate/simulation/behavior_policy.py +425 -0
- fi/simulate/simulation/bridge/__init__.py +9 -0
- fi/simulate/simulation/bridge/audio.py +29 -0
- fi/simulate/simulation/bridge/connector.py +46 -0
- fi/simulate/simulation/bridge/livekit.py +252 -0
- fi/simulate/simulation/bridge/retell.py +188 -0
- fi/simulate/simulation/bridge/vapi.py +177 -0
- fi/simulate/simulation/contract.py +419 -0
- fi/simulate/simulation/engines/__init__.py +12 -0
- fi/simulate/simulation/engines/base.py +21 -0
- fi/simulate/simulation/engines/cloud.py +517 -0
- fi/simulate/simulation/engines/livekit.py +4167 -0
- fi/simulate/simulation/engines/local_text.py +89 -0
- fi/simulate/simulation/fidelity.py +374 -0
- fi/simulate/simulation/gemini_tts_stream.py +110 -0
- fi/simulate/simulation/generator.py +91 -0
- fi/simulate/simulation/goal_machine.py +185 -0
- fi/simulate/simulation/livekit_models.py +467 -0
- fi/simulate/simulation/matrix.py +170 -0
- fi/simulate/simulation/models.py +279 -0
- fi/simulate/simulation/runner.py +153 -0
- fi/simulate/simulation/synthetic.py +880 -0
- fi/simulate/simulation/voice_prompt.py +502 -0
- fi/simulate/simulator/__init__.py +55 -0
- fi/simulate/simulator/builtins.py +53 -0
- fi/simulate/suite.py +1288 -0
- fi/simulate/utils/routes.py +164 -0
- fi/simulate/voice.py +225 -0
- fi/simulate/voice_cli.py +182 -0
- fi/utils/__init__.py +1 -0
- fi/utils/constants.py +14 -0
- fi/utils/errors.py +200 -0
- fi/utils/executor.py +26 -0
- fi/utils/routes.py +119 -0
- fi/utils/utils.py +17 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Context propagation utilities for distributed tracing.
|
|
3
|
+
|
|
4
|
+
This module provides utilities for propagating trace context across thread
|
|
5
|
+
and process boundaries, enabling:
|
|
6
|
+
- Background threads to operate within the original trace context
|
|
7
|
+
- Distributed workers to maintain trace continuity
|
|
8
|
+
- Async evaluations to enrich parent spans
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Dict, Any, Optional, Generator
|
|
12
|
+
from contextlib import contextmanager
|
|
13
|
+
from .context import EvalContext
|
|
14
|
+
from .registry import get_span
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SpanContextPropagator:
|
|
18
|
+
"""
|
|
19
|
+
Propagate and restore span context across boundaries.
|
|
20
|
+
|
|
21
|
+
Supports:
|
|
22
|
+
- Thread boundaries (same process)
|
|
23
|
+
- Process boundaries (via headers)
|
|
24
|
+
- Async boundaries (futures)
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
# Capture context before spawning thread
|
|
28
|
+
carrier = {}
|
|
29
|
+
SpanContextPropagator.inject(carrier)
|
|
30
|
+
|
|
31
|
+
# In background thread
|
|
32
|
+
context = SpanContextPropagator.extract(carrier)
|
|
33
|
+
with SpanContextPropagator.with_context(context):
|
|
34
|
+
# Code runs in original trace context
|
|
35
|
+
pass
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def inject(carrier: Dict[str, str]) -> bool:
|
|
40
|
+
"""
|
|
41
|
+
Inject current trace context into carrier.
|
|
42
|
+
|
|
43
|
+
Uses W3C Trace Context format (traceparent, baggage headers).
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
carrier: Dict to inject headers into (modified in place)
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
True if context was injected, False if no active context
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
from opentelemetry.propagate import inject
|
|
53
|
+
inject(carrier)
|
|
54
|
+
return bool(carrier)
|
|
55
|
+
except ImportError:
|
|
56
|
+
# Fallback: inject from EvalContext
|
|
57
|
+
try:
|
|
58
|
+
ctx = EvalContext.from_current_span()
|
|
59
|
+
if ctx.is_valid:
|
|
60
|
+
carrier.update(ctx.to_headers())
|
|
61
|
+
return True
|
|
62
|
+
except Exception:
|
|
63
|
+
pass
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def extract(carrier: Dict[str, str]) -> EvalContext:
|
|
68
|
+
"""
|
|
69
|
+
Extract trace context from carrier.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
carrier: Dict containing trace headers
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
EvalContext reconstructed from headers
|
|
76
|
+
"""
|
|
77
|
+
return EvalContext.from_headers(carrier)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
@contextmanager
|
|
81
|
+
def with_context(context: EvalContext) -> Generator[None, None, None]:
|
|
82
|
+
"""
|
|
83
|
+
Context manager to run code with specific trace context.
|
|
84
|
+
|
|
85
|
+
Useful for background threads that need to operate in
|
|
86
|
+
the context of a specific trace.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
context: EvalContext to activate
|
|
90
|
+
|
|
91
|
+
Yields:
|
|
92
|
+
None
|
|
93
|
+
|
|
94
|
+
Example:
|
|
95
|
+
ctx = EvalContext.from_current_span()
|
|
96
|
+
|
|
97
|
+
def background_task():
|
|
98
|
+
with SpanContextPropagator.with_context(ctx):
|
|
99
|
+
# This code runs in the original trace context
|
|
100
|
+
span = trace.get_current_span()
|
|
101
|
+
span.set_attribute("from_background", True)
|
|
102
|
+
"""
|
|
103
|
+
try:
|
|
104
|
+
from opentelemetry import trace
|
|
105
|
+
from opentelemetry.trace import NonRecordingSpan, SpanContext, TraceFlags
|
|
106
|
+
from opentelemetry.context import attach, detach
|
|
107
|
+
|
|
108
|
+
# Create a span context from our EvalContext
|
|
109
|
+
span_context = SpanContext(
|
|
110
|
+
trace_id=int(context.trace_id, 16),
|
|
111
|
+
span_id=int(context.span_id, 16),
|
|
112
|
+
is_remote=True,
|
|
113
|
+
trace_flags=TraceFlags(0x01), # Sampled
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Create a non-recording span with this context
|
|
117
|
+
span = NonRecordingSpan(span_context)
|
|
118
|
+
|
|
119
|
+
# Attach to current context
|
|
120
|
+
ctx = trace.set_span_in_context(span)
|
|
121
|
+
token = attach(ctx)
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
yield
|
|
125
|
+
finally:
|
|
126
|
+
detach(token)
|
|
127
|
+
except ImportError:
|
|
128
|
+
# No OTEL - just yield
|
|
129
|
+
yield
|
|
130
|
+
except Exception:
|
|
131
|
+
# Any other error - just yield
|
|
132
|
+
yield
|
|
133
|
+
|
|
134
|
+
@staticmethod
|
|
135
|
+
def create_child_context(parent: EvalContext) -> EvalContext:
|
|
136
|
+
"""
|
|
137
|
+
Create a child context from a parent.
|
|
138
|
+
|
|
139
|
+
Maintains the same trace_id but generates a new span_id.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
parent: Parent context
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
New child EvalContext
|
|
146
|
+
"""
|
|
147
|
+
return parent.child_context()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def enrich_span_by_context(
|
|
151
|
+
context: EvalContext,
|
|
152
|
+
attributes: Dict[str, Any],
|
|
153
|
+
) -> bool:
|
|
154
|
+
"""
|
|
155
|
+
Enrich a span using its context, even from a different thread.
|
|
156
|
+
|
|
157
|
+
This looks up the span in the registry and adds attributes to it.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
context: The EvalContext identifying the span
|
|
161
|
+
attributes: Attributes to add (will be filtered for valid types)
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
True if enrichment succeeded, False otherwise
|
|
165
|
+
|
|
166
|
+
Example:
|
|
167
|
+
# In main thread
|
|
168
|
+
ctx = EvalContext.from_current_span()
|
|
169
|
+
register_current_span()
|
|
170
|
+
|
|
171
|
+
# In background thread
|
|
172
|
+
enrich_span_by_context(ctx, {
|
|
173
|
+
"eval.faithfulness.score": 0.95,
|
|
174
|
+
"eval.faithfulness.async": True,
|
|
175
|
+
})
|
|
176
|
+
"""
|
|
177
|
+
span = get_span(context.trace_id, context.span_id)
|
|
178
|
+
if span is None:
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
if not span.is_recording():
|
|
183
|
+
return False
|
|
184
|
+
|
|
185
|
+
for key, value in attributes.items():
|
|
186
|
+
if value is not None and _is_valid_attribute(value):
|
|
187
|
+
span.set_attribute(key, value)
|
|
188
|
+
|
|
189
|
+
return True
|
|
190
|
+
except Exception:
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def enrich_span_by_ids(
|
|
195
|
+
trace_id: str,
|
|
196
|
+
span_id: str,
|
|
197
|
+
attributes: Dict[str, Any],
|
|
198
|
+
) -> bool:
|
|
199
|
+
"""
|
|
200
|
+
Enrich a span by trace/span IDs.
|
|
201
|
+
|
|
202
|
+
Convenience wrapper around enrich_span_by_context.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
trace_id: The trace ID
|
|
206
|
+
span_id: The span ID
|
|
207
|
+
attributes: Attributes to add
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
True if enrichment succeeded
|
|
211
|
+
"""
|
|
212
|
+
span = get_span(trace_id, span_id)
|
|
213
|
+
if span is None:
|
|
214
|
+
return False
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
if not span.is_recording():
|
|
218
|
+
return False
|
|
219
|
+
|
|
220
|
+
for key, value in attributes.items():
|
|
221
|
+
if value is not None and _is_valid_attribute(value):
|
|
222
|
+
span.set_attribute(key, value)
|
|
223
|
+
|
|
224
|
+
return True
|
|
225
|
+
except Exception:
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def add_event_by_context(
|
|
230
|
+
context: EvalContext,
|
|
231
|
+
name: str,
|
|
232
|
+
attributes: Optional[Dict[str, Any]] = None,
|
|
233
|
+
) -> bool:
|
|
234
|
+
"""
|
|
235
|
+
Add an event to a span using its context.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
context: The EvalContext identifying the span
|
|
239
|
+
name: Event name
|
|
240
|
+
attributes: Optional event attributes
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
True if event was added
|
|
244
|
+
"""
|
|
245
|
+
span = get_span(context.trace_id, context.span_id)
|
|
246
|
+
if span is None:
|
|
247
|
+
return False
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
if not span.is_recording():
|
|
251
|
+
return False
|
|
252
|
+
|
|
253
|
+
event_attrs = {}
|
|
254
|
+
if attributes:
|
|
255
|
+
for key, value in attributes.items():
|
|
256
|
+
if value is not None and _is_valid_attribute(value):
|
|
257
|
+
event_attrs[key] = value
|
|
258
|
+
|
|
259
|
+
span.add_event(name, attributes=event_attrs if event_attrs else None)
|
|
260
|
+
return True
|
|
261
|
+
except Exception:
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _is_valid_attribute(value: Any) -> bool:
|
|
266
|
+
"""Check if a value is valid for span attributes."""
|
|
267
|
+
return isinstance(value, (str, int, float, bool))
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class ContextCarrier:
|
|
271
|
+
"""
|
|
272
|
+
Helper class for carrying context across boundaries.
|
|
273
|
+
|
|
274
|
+
Combines EvalContext with additional metadata needed for
|
|
275
|
+
distributed evaluation.
|
|
276
|
+
|
|
277
|
+
Example:
|
|
278
|
+
# Create carrier
|
|
279
|
+
carrier = ContextCarrier.capture()
|
|
280
|
+
|
|
281
|
+
# Serialize for transmission
|
|
282
|
+
data = carrier.to_dict()
|
|
283
|
+
|
|
284
|
+
# Reconstruct in worker
|
|
285
|
+
carrier = ContextCarrier.from_dict(data)
|
|
286
|
+
with carrier.activate():
|
|
287
|
+
# Run in original context
|
|
288
|
+
pass
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
def __init__(
|
|
292
|
+
self,
|
|
293
|
+
context: EvalContext,
|
|
294
|
+
headers: Optional[Dict[str, str]] = None,
|
|
295
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
296
|
+
):
|
|
297
|
+
self.context = context
|
|
298
|
+
self.headers = headers or {}
|
|
299
|
+
self.metadata = metadata or {}
|
|
300
|
+
|
|
301
|
+
@classmethod
|
|
302
|
+
def capture(cls, metadata: Optional[Dict[str, Any]] = None) -> "ContextCarrier":
|
|
303
|
+
"""
|
|
304
|
+
Capture current context into a carrier.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
metadata: Optional additional metadata
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
ContextCarrier with captured context
|
|
311
|
+
"""
|
|
312
|
+
context = EvalContext.from_current_span()
|
|
313
|
+
|
|
314
|
+
# Also capture raw headers
|
|
315
|
+
headers: Dict[str, str] = {}
|
|
316
|
+
SpanContextPropagator.inject(headers)
|
|
317
|
+
|
|
318
|
+
return cls(
|
|
319
|
+
context=context,
|
|
320
|
+
headers=headers,
|
|
321
|
+
metadata=metadata or {},
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
325
|
+
"""Serialize to dict for transmission."""
|
|
326
|
+
return {
|
|
327
|
+
"context": self.context.to_dict(),
|
|
328
|
+
"headers": self.headers,
|
|
329
|
+
"metadata": self.metadata,
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
@classmethod
|
|
333
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ContextCarrier":
|
|
334
|
+
"""Deserialize from dict."""
|
|
335
|
+
return cls(
|
|
336
|
+
context=EvalContext.from_dict(data["context"]),
|
|
337
|
+
headers=data.get("headers", {}),
|
|
338
|
+
metadata=data.get("metadata", {}),
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
@contextmanager
|
|
342
|
+
def activate(self) -> Generator["ContextCarrier", None, None]:
|
|
343
|
+
"""
|
|
344
|
+
Context manager to activate this carrier's context.
|
|
345
|
+
|
|
346
|
+
Yields:
|
|
347
|
+
Self for accessing context/metadata
|
|
348
|
+
"""
|
|
349
|
+
with SpanContextPropagator.with_context(self.context):
|
|
350
|
+
yield self
|
|
351
|
+
|
|
352
|
+
def enrich_span(self, attributes: Dict[str, Any]) -> bool:
|
|
353
|
+
"""
|
|
354
|
+
Enrich the original span with attributes.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
attributes: Attributes to add
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
True if enrichment succeeded
|
|
361
|
+
"""
|
|
362
|
+
return enrich_span_by_context(self.context, attributes)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def propagate_context(func):
|
|
366
|
+
"""
|
|
367
|
+
Decorator to propagate context to a function running in another thread.
|
|
368
|
+
|
|
369
|
+
Captures the current context at call time (when the wrapper is invoked)
|
|
370
|
+
and activates it in the background thread.
|
|
371
|
+
|
|
372
|
+
Example:
|
|
373
|
+
@propagate_context
|
|
374
|
+
def background_task(x, y):
|
|
375
|
+
# This runs in the caller's trace context
|
|
376
|
+
return x + y
|
|
377
|
+
|
|
378
|
+
# Context is captured when submit() calls the wrapper
|
|
379
|
+
executor.submit(background_task, 1, 2)
|
|
380
|
+
"""
|
|
381
|
+
import functools
|
|
382
|
+
|
|
383
|
+
@functools.wraps(func)
|
|
384
|
+
def wrapper(*args, **kwargs):
|
|
385
|
+
# Capture context at call time, not decoration time
|
|
386
|
+
carrier = ContextCarrier.capture()
|
|
387
|
+
with carrier.activate():
|
|
388
|
+
return func(*args, **kwargs)
|
|
389
|
+
|
|
390
|
+
return wrapper
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def propagate_context_lazy(func):
|
|
394
|
+
"""
|
|
395
|
+
Decorator to propagate context, capturing at call time.
|
|
396
|
+
|
|
397
|
+
Unlike propagate_context, this captures context when the wrapped
|
|
398
|
+
function is called, not when decorated.
|
|
399
|
+
|
|
400
|
+
Example:
|
|
401
|
+
@propagate_context_lazy
|
|
402
|
+
def background_task(x, y):
|
|
403
|
+
return x + y
|
|
404
|
+
|
|
405
|
+
# Context is captured here, when submitted
|
|
406
|
+
executor.submit(background_task, 1, 2)
|
|
407
|
+
"""
|
|
408
|
+
import functools
|
|
409
|
+
|
|
410
|
+
@functools.wraps(func)
|
|
411
|
+
def wrapper(*args, **kwargs):
|
|
412
|
+
# Capture context at call time
|
|
413
|
+
carrier = ContextCarrier.capture()
|
|
414
|
+
|
|
415
|
+
def run():
|
|
416
|
+
with carrier.activate():
|
|
417
|
+
return func(*args, **kwargs)
|
|
418
|
+
|
|
419
|
+
return run
|
|
420
|
+
|
|
421
|
+
return wrapper
|