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,385 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Protocol definitions for evaluations.
|
|
3
|
+
|
|
4
|
+
This module defines the BaseEvaluation protocol that all evaluations must implement,
|
|
5
|
+
and the EvalRegistry for registering and looking up evaluations by name/version.
|
|
6
|
+
|
|
7
|
+
The protocol-based approach allows:
|
|
8
|
+
- Type checking at development time
|
|
9
|
+
- Runtime validation of evaluation implementations
|
|
10
|
+
- Decoupled evaluation logic from execution mode
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import (
|
|
14
|
+
Protocol,
|
|
15
|
+
TypeVar,
|
|
16
|
+
Dict,
|
|
17
|
+
Any,
|
|
18
|
+
Optional,
|
|
19
|
+
runtime_checkable,
|
|
20
|
+
Type,
|
|
21
|
+
List,
|
|
22
|
+
Callable,
|
|
23
|
+
)
|
|
24
|
+
from abc import abstractmethod
|
|
25
|
+
|
|
26
|
+
T = TypeVar("T")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@runtime_checkable
|
|
30
|
+
class BaseEvaluation(Protocol[T]):
|
|
31
|
+
"""
|
|
32
|
+
Protocol that all evaluations must implement.
|
|
33
|
+
|
|
34
|
+
Evaluations are stateless functions that:
|
|
35
|
+
1. Take inputs (dict)
|
|
36
|
+
2. Return a typed result
|
|
37
|
+
3. Can convert results to span attributes
|
|
38
|
+
|
|
39
|
+
The protocol is runtime checkable, so you can verify implementations:
|
|
40
|
+
isinstance(my_eval, BaseEvaluation) # True if properly implemented
|
|
41
|
+
|
|
42
|
+
Attributes:
|
|
43
|
+
name: Unique name for this evaluation (e.g., "faithfulness")
|
|
44
|
+
version: Semantic version string (e.g., "1.0.0")
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
class FaithfulnessEval(BaseEvaluation[FaithfulnessResult]):
|
|
48
|
+
name = "faithfulness"
|
|
49
|
+
version = "1.0.0"
|
|
50
|
+
|
|
51
|
+
def evaluate(self, inputs: Dict[str, Any]) -> FaithfulnessResult:
|
|
52
|
+
query = inputs["query"]
|
|
53
|
+
response = inputs["response"]
|
|
54
|
+
context = inputs["context"]
|
|
55
|
+
# ... evaluation logic ...
|
|
56
|
+
return FaithfulnessResult(score=0.95, reason="...")
|
|
57
|
+
|
|
58
|
+
def get_span_attributes(self, result: FaithfulnessResult) -> Dict[str, Any]:
|
|
59
|
+
return {
|
|
60
|
+
"score": result.score,
|
|
61
|
+
"passed": result.score >= 0.7,
|
|
62
|
+
}
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
name: str
|
|
66
|
+
version: str
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def evaluate(self, inputs: Dict[str, Any]) -> T:
|
|
70
|
+
"""
|
|
71
|
+
Synchronous evaluation - implement this.
|
|
72
|
+
|
|
73
|
+
This is the main evaluation method. It should be stateless and
|
|
74
|
+
deterministic given the same inputs.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
inputs: Dict containing evaluation inputs. Keys depend on
|
|
78
|
+
the specific evaluation (e.g., "query", "response", "context")
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Typed result object containing evaluation output
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
ValueError: If inputs are invalid
|
|
85
|
+
RuntimeError: If evaluation fails for other reasons
|
|
86
|
+
"""
|
|
87
|
+
...
|
|
88
|
+
|
|
89
|
+
@abstractmethod
|
|
90
|
+
def get_span_attributes(self, result: T) -> Dict[str, Any]:
|
|
91
|
+
"""
|
|
92
|
+
Convert result to span attributes.
|
|
93
|
+
|
|
94
|
+
Returns a flat dict suitable for OTEL span attributes.
|
|
95
|
+
Keys should NOT include the eval name prefix - that's added by the framework.
|
|
96
|
+
|
|
97
|
+
The returned values must be OTEL-compatible types:
|
|
98
|
+
- str, int, float, bool
|
|
99
|
+
- Lists of the above types
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
result: The evaluation result
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Dict of attribute name to value
|
|
106
|
+
|
|
107
|
+
Example:
|
|
108
|
+
def get_span_attributes(self, result: MyResult) -> Dict[str, Any]:
|
|
109
|
+
return {
|
|
110
|
+
"score": result.score,
|
|
111
|
+
"passed": result.passed,
|
|
112
|
+
"category": result.category,
|
|
113
|
+
}
|
|
114
|
+
# Framework adds prefix: eval.my_eval.score, eval.my_eval.passed, etc.
|
|
115
|
+
"""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def validate_inputs(self, inputs: Dict[str, Any]) -> List[str]:
|
|
119
|
+
"""
|
|
120
|
+
Validate inputs before evaluation.
|
|
121
|
+
|
|
122
|
+
Override to add custom validation logic. Called before evaluate().
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
inputs: Dict containing evaluation inputs
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Empty list if valid, list of error message strings if invalid
|
|
129
|
+
"""
|
|
130
|
+
return []
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class EvalRegistry:
|
|
134
|
+
"""
|
|
135
|
+
Registry for evaluation classes.
|
|
136
|
+
|
|
137
|
+
Allows lookups by name/version for distributed execution where
|
|
138
|
+
the evaluation class needs to be instantiated on a worker.
|
|
139
|
+
|
|
140
|
+
The registry is a singleton - all registrations go to the same global registry.
|
|
141
|
+
|
|
142
|
+
Example:
|
|
143
|
+
# Register an evaluation
|
|
144
|
+
@register_evaluation
|
|
145
|
+
class MyEval(BaseEvaluation[MyResult]):
|
|
146
|
+
name = "my_eval"
|
|
147
|
+
version = "1.0.0"
|
|
148
|
+
...
|
|
149
|
+
|
|
150
|
+
# Look up later
|
|
151
|
+
eval_class = EvalRegistry.get("my_eval", "1.0.0")
|
|
152
|
+
eval_instance = eval_class()
|
|
153
|
+
"""
|
|
154
|
+
_registry: Dict[str, Dict[str, Type[BaseEvaluation]]] = {}
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def register(cls, eval_class: Type[BaseEvaluation]) -> Type[BaseEvaluation]:
|
|
158
|
+
"""
|
|
159
|
+
Register an evaluation class.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
eval_class: The evaluation class to register
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
The same class (for use as decorator)
|
|
166
|
+
|
|
167
|
+
Raises:
|
|
168
|
+
ValueError: If class doesn't have name or version attributes
|
|
169
|
+
"""
|
|
170
|
+
name = getattr(eval_class, 'name', None)
|
|
171
|
+
version = getattr(eval_class, 'version', '1.0.0')
|
|
172
|
+
|
|
173
|
+
if not name:
|
|
174
|
+
name = eval_class.__name__
|
|
175
|
+
|
|
176
|
+
if name not in cls._registry:
|
|
177
|
+
cls._registry[name] = {}
|
|
178
|
+
|
|
179
|
+
cls._registry[name][version] = eval_class
|
|
180
|
+
return eval_class
|
|
181
|
+
|
|
182
|
+
@classmethod
|
|
183
|
+
def get(cls, name: str, version: str = "latest") -> Type[BaseEvaluation]:
|
|
184
|
+
"""
|
|
185
|
+
Get evaluation class by name and version.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
name: Evaluation name
|
|
189
|
+
version: Version string or "latest" for highest version
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
The evaluation class
|
|
193
|
+
|
|
194
|
+
Raises:
|
|
195
|
+
ValueError: If evaluation or version not found
|
|
196
|
+
"""
|
|
197
|
+
if name not in cls._registry:
|
|
198
|
+
raise ValueError(f"Evaluation '{name}' not found in registry")
|
|
199
|
+
|
|
200
|
+
versions = cls._registry[name]
|
|
201
|
+
|
|
202
|
+
if version == "latest":
|
|
203
|
+
# Get highest version using semantic versioning comparison
|
|
204
|
+
version = cls._get_latest_version(list(versions.keys()))
|
|
205
|
+
|
|
206
|
+
if version not in versions:
|
|
207
|
+
available = list(versions.keys())
|
|
208
|
+
raise ValueError(
|
|
209
|
+
f"Version '{version}' not found for evaluation '{name}'. "
|
|
210
|
+
f"Available versions: {available}"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return versions[version]
|
|
214
|
+
|
|
215
|
+
@classmethod
|
|
216
|
+
def _get_latest_version(cls, versions: List[str]) -> str:
|
|
217
|
+
"""Get the latest version from a list of version strings."""
|
|
218
|
+
def version_key(v: str) -> tuple:
|
|
219
|
+
# Parse semver: major.minor.patch
|
|
220
|
+
parts = v.split(".")
|
|
221
|
+
result = []
|
|
222
|
+
for part in parts:
|
|
223
|
+
try:
|
|
224
|
+
result.append(int(part))
|
|
225
|
+
except ValueError:
|
|
226
|
+
result.append(0)
|
|
227
|
+
# Pad to 3 elements
|
|
228
|
+
while len(result) < 3:
|
|
229
|
+
result.append(0)
|
|
230
|
+
return tuple(result)
|
|
231
|
+
|
|
232
|
+
return max(versions, key=version_key)
|
|
233
|
+
|
|
234
|
+
@classmethod
|
|
235
|
+
def get_instance(
|
|
236
|
+
cls,
|
|
237
|
+
name: str,
|
|
238
|
+
version: str = "latest",
|
|
239
|
+
**kwargs,
|
|
240
|
+
) -> BaseEvaluation:
|
|
241
|
+
"""
|
|
242
|
+
Get an instantiated evaluation.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
name: Evaluation name
|
|
246
|
+
version: Version string or "latest"
|
|
247
|
+
**kwargs: Arguments to pass to evaluation constructor
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Instantiated evaluation object
|
|
251
|
+
"""
|
|
252
|
+
eval_class = cls.get(name, version)
|
|
253
|
+
return eval_class(**kwargs)
|
|
254
|
+
|
|
255
|
+
@classmethod
|
|
256
|
+
def list_all(cls) -> Dict[str, List[str]]:
|
|
257
|
+
"""
|
|
258
|
+
List all registered evaluations.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Dict mapping evaluation names to list of available versions
|
|
262
|
+
"""
|
|
263
|
+
return {name: list(versions.keys()) for name, versions in cls._registry.items()}
|
|
264
|
+
|
|
265
|
+
@classmethod
|
|
266
|
+
def is_registered(cls, name: str, version: Optional[str] = None) -> bool:
|
|
267
|
+
"""
|
|
268
|
+
Check if an evaluation is registered.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
name: Evaluation name
|
|
272
|
+
version: Optional specific version to check
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
True if registered, False otherwise
|
|
276
|
+
"""
|
|
277
|
+
if name not in cls._registry:
|
|
278
|
+
return False
|
|
279
|
+
if version is None:
|
|
280
|
+
return True
|
|
281
|
+
return version in cls._registry[name]
|
|
282
|
+
|
|
283
|
+
@classmethod
|
|
284
|
+
def unregister(cls, name: str, version: Optional[str] = None) -> bool:
|
|
285
|
+
"""
|
|
286
|
+
Remove an evaluation from the registry.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
name: Evaluation name
|
|
290
|
+
version: Specific version to remove, or None to remove all versions
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
True if something was removed, False otherwise
|
|
294
|
+
"""
|
|
295
|
+
if name not in cls._registry:
|
|
296
|
+
return False
|
|
297
|
+
|
|
298
|
+
if version is None:
|
|
299
|
+
del cls._registry[name]
|
|
300
|
+
return True
|
|
301
|
+
|
|
302
|
+
if version in cls._registry[name]:
|
|
303
|
+
del cls._registry[name][version]
|
|
304
|
+
if not cls._registry[name]:
|
|
305
|
+
del cls._registry[name]
|
|
306
|
+
return True
|
|
307
|
+
|
|
308
|
+
return False
|
|
309
|
+
|
|
310
|
+
@classmethod
|
|
311
|
+
def clear(cls) -> None:
|
|
312
|
+
"""Clear all registrations (for testing)."""
|
|
313
|
+
cls._registry.clear()
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def register_evaluation(cls: Type[BaseEvaluation]) -> Type[BaseEvaluation]:
|
|
317
|
+
"""
|
|
318
|
+
Decorator to register an evaluation class.
|
|
319
|
+
|
|
320
|
+
Example:
|
|
321
|
+
@register_evaluation
|
|
322
|
+
class MyEval(BaseEvaluation[MyResult]):
|
|
323
|
+
name = "my_eval"
|
|
324
|
+
version = "1.0.0"
|
|
325
|
+
|
|
326
|
+
def evaluate(self, inputs: Dict[str, Any]) -> MyResult:
|
|
327
|
+
...
|
|
328
|
+
|
|
329
|
+
def get_span_attributes(self, result: MyResult) -> Dict[str, Any]:
|
|
330
|
+
...
|
|
331
|
+
"""
|
|
332
|
+
return EvalRegistry.register(cls)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def create_evaluation(
|
|
336
|
+
name: str,
|
|
337
|
+
version: str = "1.0.0",
|
|
338
|
+
evaluate_fn: Optional[Callable[[Dict[str, Any]], Any]] = None,
|
|
339
|
+
span_attributes_fn: Optional[Callable[[Any], Dict[str, Any]]] = None,
|
|
340
|
+
) -> Type[BaseEvaluation]:
|
|
341
|
+
"""
|
|
342
|
+
Factory function to create an evaluation class from functions.
|
|
343
|
+
|
|
344
|
+
Useful for simple evaluations that don't need a full class definition.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
name: Evaluation name
|
|
348
|
+
version: Version string
|
|
349
|
+
evaluate_fn: The evaluation function
|
|
350
|
+
span_attributes_fn: Function to convert result to span attributes
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
A new evaluation class
|
|
354
|
+
|
|
355
|
+
Example:
|
|
356
|
+
MyEval = create_evaluation(
|
|
357
|
+
name="simple_check",
|
|
358
|
+
evaluate_fn=lambda inputs: {"passed": len(inputs["response"]) > 10},
|
|
359
|
+
span_attributes_fn=lambda result: {"passed": result["passed"]},
|
|
360
|
+
)
|
|
361
|
+
"""
|
|
362
|
+
class DynamicEvaluation:
|
|
363
|
+
def __init__(self):
|
|
364
|
+
pass
|
|
365
|
+
|
|
366
|
+
def evaluate(self, inputs: Dict[str, Any]) -> Any:
|
|
367
|
+
if evaluate_fn is None:
|
|
368
|
+
raise NotImplementedError("evaluate_fn not provided")
|
|
369
|
+
return evaluate_fn(inputs)
|
|
370
|
+
|
|
371
|
+
def get_span_attributes(self, result: Any) -> Dict[str, Any]:
|
|
372
|
+
if span_attributes_fn is None:
|
|
373
|
+
# Default: try to convert result to dict
|
|
374
|
+
if isinstance(result, dict):
|
|
375
|
+
return {k: v for k, v in result.items() if isinstance(v, (str, int, float, bool))}
|
|
376
|
+
return {}
|
|
377
|
+
return span_attributes_fn(result)
|
|
378
|
+
|
|
379
|
+
def validate_inputs(self, inputs: Dict[str, Any]) -> List[str]:
|
|
380
|
+
return []
|
|
381
|
+
|
|
382
|
+
DynamicEvaluation.name = name
|
|
383
|
+
DynamicEvaluation.version = version
|
|
384
|
+
|
|
385
|
+
return DynamicEvaluation
|