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,799 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import copy
|
|
4
|
+
import json
|
|
5
|
+
from typing import Any, Callable, Mapping, Optional, Sequence
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from ..base.base_optimizer import BaseOptimizer
|
|
10
|
+
from ..deployment import AgentDeploymentExport, export_agent_deployment
|
|
11
|
+
from ..observability import (
|
|
12
|
+
AgentRegressionDataset,
|
|
13
|
+
AgentObservabilityWindow,
|
|
14
|
+
AgentRegistryReplayPackLineageReport,
|
|
15
|
+
AgentRegistryReplayPackTriageReport,
|
|
16
|
+
load_futureagi_experiment_history,
|
|
17
|
+
load_futureagi_regression_dataset,
|
|
18
|
+
)
|
|
19
|
+
from ..targets import AgentCandidate, CandidateEvaluation, OptimizationTarget
|
|
20
|
+
from ..types import EvaluationResult
|
|
21
|
+
from .agent_feedback import (
|
|
22
|
+
AgentFeedbackOptimizationResult,
|
|
23
|
+
AgentFeedbackOptimizer,
|
|
24
|
+
AgentMultiInteractionOptimizationResult,
|
|
25
|
+
AgentMultiInteractionOptimizer,
|
|
26
|
+
DEFAULT_MULTI_INTERACTION_BACKENDS,
|
|
27
|
+
_normalize_optimizer_name,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
CandidateScorer = Callable[
|
|
32
|
+
[AgentCandidate],
|
|
33
|
+
CandidateEvaluation | EvaluationResult | float,
|
|
34
|
+
]
|
|
35
|
+
FUTUREAGI_REPLAY_OPTIMIZER_SCHEDULE_SCHEMA_VERSION = (
|
|
36
|
+
"agent-opt.futureagi-replay-optimizer-schedule.v1"
|
|
37
|
+
)
|
|
38
|
+
_REPLAY_EVIDENCE_BLOCKERS = {
|
|
39
|
+
"futureagi_readback_signature_mismatch",
|
|
40
|
+
"futureagi_readback_case_count_mismatch",
|
|
41
|
+
"futureagi_replay_record_count_mismatch",
|
|
42
|
+
"latest_promotion_failed",
|
|
43
|
+
"latest_promotion_failures",
|
|
44
|
+
"missing_latest_promotion_check",
|
|
45
|
+
"missing_latest_optimizer_score",
|
|
46
|
+
}
|
|
47
|
+
_REPLAY_PORTFOLIO_TRIGGERS = {
|
|
48
|
+
"optimizer_score_regression",
|
|
49
|
+
"latest_below_best_optimizer_score",
|
|
50
|
+
"selected_patch_changed",
|
|
51
|
+
"optimizer_backend_changed",
|
|
52
|
+
"case_signature_changed",
|
|
53
|
+
}
|
|
54
|
+
_REPLAY_CURRICULUM_TRIGGERS = {
|
|
55
|
+
"coverage_regression",
|
|
56
|
+
"coverage_drift",
|
|
57
|
+
"required_contract_expanded",
|
|
58
|
+
"required_presets_removed",
|
|
59
|
+
"required_invariant_families_removed",
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class FutureAGIReplayOptimizerSchedule(BaseModel):
|
|
64
|
+
"""Optimizer replay plan derived from Future AGI registry replay-pack triage."""
|
|
65
|
+
|
|
66
|
+
schema_version: str = FUTUREAGI_REPLAY_OPTIMIZER_SCHEDULE_SCHEMA_VERSION
|
|
67
|
+
provider: str = "futureagi"
|
|
68
|
+
should_optimize: bool
|
|
69
|
+
selected_optimizer: str = "none"
|
|
70
|
+
reason: str
|
|
71
|
+
replay_dataset_id: Optional[str] = None
|
|
72
|
+
replay_dataset_name: Optional[str] = None
|
|
73
|
+
registry_version: Optional[str] = None
|
|
74
|
+
baseline_registry_version: Optional[str] = None
|
|
75
|
+
triage_decision: str
|
|
76
|
+
triage_severity: str
|
|
77
|
+
triage_block_rollout: bool
|
|
78
|
+
triggers: list[str] = Field(default_factory=list)
|
|
79
|
+
optimizer_pool: list[str] = Field(default_factory=list)
|
|
80
|
+
max_backends: Optional[int] = None
|
|
81
|
+
optimizer_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
82
|
+
optimizer_kwargs_by_backend: dict[str, dict[str, Any]] = Field(default_factory=dict)
|
|
83
|
+
rollback_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
84
|
+
recommendations: list[str] = Field(default_factory=list)
|
|
85
|
+
evidence: dict[str, Any] = Field(default_factory=dict)
|
|
86
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
87
|
+
|
|
88
|
+
def to_manifest(self) -> dict[str, Any]:
|
|
89
|
+
return self.model_dump()
|
|
90
|
+
|
|
91
|
+
def to_json(self, *, indent: int = 2) -> str:
|
|
92
|
+
return json.dumps(self.to_manifest(), sort_keys=True, indent=indent, default=str)
|
|
93
|
+
|
|
94
|
+
def to_optimizer_kwargs(self) -> dict[str, Any]:
|
|
95
|
+
"""Arguments that can be passed to FutureAGIRegressionReplayOptimizer."""
|
|
96
|
+
|
|
97
|
+
payload: dict[str, Any] = {
|
|
98
|
+
"optimizer": self.selected_optimizer,
|
|
99
|
+
"optimizer_kwargs": copy.deepcopy(self.optimizer_kwargs),
|
|
100
|
+
"optimizer_kwargs_by_backend": copy.deepcopy(
|
|
101
|
+
self.optimizer_kwargs_by_backend
|
|
102
|
+
),
|
|
103
|
+
"rollback_kwargs": copy.deepcopy(self.rollback_kwargs),
|
|
104
|
+
"optimizer_schedule": self,
|
|
105
|
+
}
|
|
106
|
+
if self.optimizer_pool:
|
|
107
|
+
payload["optimizer_pool"] = list(self.optimizer_pool)
|
|
108
|
+
if self.max_backends is not None:
|
|
109
|
+
payload["max_backends"] = self.max_backends
|
|
110
|
+
return payload
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def schedule_futureagi_registry_replay_optimization(
|
|
114
|
+
triage: AgentRegistryReplayPackTriageReport | Mapping[str, Any],
|
|
115
|
+
*,
|
|
116
|
+
lineage: Optional[AgentRegistryReplayPackLineageReport | Mapping[str, Any]] = None,
|
|
117
|
+
schedule_on_review: bool = True,
|
|
118
|
+
force: bool = False,
|
|
119
|
+
optimizer_pool: Optional[Sequence[str]] = None,
|
|
120
|
+
max_backends: Optional[int] = None,
|
|
121
|
+
optimizer_kwargs: Optional[Mapping[str, Any]] = None,
|
|
122
|
+
optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
|
|
123
|
+
rollback_kwargs: Optional[Mapping[str, Any]] = None,
|
|
124
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
|
125
|
+
) -> FutureAGIReplayOptimizerSchedule:
|
|
126
|
+
"""
|
|
127
|
+
Convert replay-pack triage into Future AGI replay optimizer arguments.
|
|
128
|
+
|
|
129
|
+
Coverage and required-contract drift schedules curriculum replay. Optimizer
|
|
130
|
+
score, selected-patch, backend, or case-signature drift schedules the
|
|
131
|
+
multi-interaction backend portfolio. Pure Future AGI readback/promotion
|
|
132
|
+
evidence failures do not schedule optimizer work until the retained pack can
|
|
133
|
+
be read back cleanly.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
active_triage = _coerce_futureagi_replay_triage(triage)
|
|
137
|
+
active_lineage = _coerce_futureagi_replay_lineage(lineage)
|
|
138
|
+
latest_entry = _lineage_entry_for_triage(active_lineage, active_triage)
|
|
139
|
+
trigger_candidates = list(active_triage.blocking_reasons)
|
|
140
|
+
if active_triage.block_rollout or schedule_on_review or force:
|
|
141
|
+
trigger_candidates.extend(active_triage.warnings)
|
|
142
|
+
triggers = _unique_schedule_items(trigger_candidates)
|
|
143
|
+
optimizer_triggers = [
|
|
144
|
+
trigger
|
|
145
|
+
for trigger in triggers
|
|
146
|
+
if trigger in _REPLAY_PORTFOLIO_TRIGGERS
|
|
147
|
+
or trigger in _REPLAY_CURRICULUM_TRIGGERS
|
|
148
|
+
]
|
|
149
|
+
evidence_only_block = (
|
|
150
|
+
active_triage.block_rollout
|
|
151
|
+
and not optimizer_triggers
|
|
152
|
+
and all(trigger in _REPLAY_EVIDENCE_BLOCKERS for trigger in triggers)
|
|
153
|
+
)
|
|
154
|
+
should_optimize = bool(force or optimizer_triggers) and not evidence_only_block
|
|
155
|
+
selected_optimizer = "none"
|
|
156
|
+
reason = "no replay optimization scheduled"
|
|
157
|
+
schedule_optimizer_pool: list[str] = []
|
|
158
|
+
schedule_optimizer_kwargs = {"target_score": 1.0}
|
|
159
|
+
if should_optimize:
|
|
160
|
+
if any(trigger in _REPLAY_PORTFOLIO_TRIGGERS for trigger in optimizer_triggers):
|
|
161
|
+
selected_optimizer = "multi_interaction"
|
|
162
|
+
schedule_optimizer_pool = _unique_schedule_items(
|
|
163
|
+
optimizer_pool or DEFAULT_MULTI_INTERACTION_BACKENDS
|
|
164
|
+
)
|
|
165
|
+
reason = "portfolio replay for optimizer-score or selected-patch drift"
|
|
166
|
+
else:
|
|
167
|
+
selected_optimizer = "curriculum"
|
|
168
|
+
reason = "curriculum replay for coverage or required-contract drift"
|
|
169
|
+
elif evidence_only_block:
|
|
170
|
+
reason = "fix Future AGI readback or promotion evidence before optimizer replay"
|
|
171
|
+
|
|
172
|
+
schedule_optimizer_kwargs.update(dict(optimizer_kwargs or {}))
|
|
173
|
+
schedule_kwargs_by_backend = {
|
|
174
|
+
_normalize_optimizer_name(key): dict(value)
|
|
175
|
+
for key, value in dict(optimizer_kwargs_by_backend or {}).items()
|
|
176
|
+
}
|
|
177
|
+
schedule_rollback_kwargs = {
|
|
178
|
+
"consecutive_failures": 1,
|
|
179
|
+
"min_evaluations": 1,
|
|
180
|
+
**dict(rollback_kwargs or {}),
|
|
181
|
+
}
|
|
182
|
+
recommendations = list(active_triage.recommendations)
|
|
183
|
+
if should_optimize:
|
|
184
|
+
recommendations.append(
|
|
185
|
+
"Run FutureAGIRegressionReplayOptimizer with this optimizer schedule "
|
|
186
|
+
"against the latest retained Future AGI replay pack."
|
|
187
|
+
)
|
|
188
|
+
return FutureAGIReplayOptimizerSchedule(
|
|
189
|
+
should_optimize=should_optimize,
|
|
190
|
+
selected_optimizer=selected_optimizer,
|
|
191
|
+
reason=reason,
|
|
192
|
+
replay_dataset_id=active_triage.latest_dataset_id,
|
|
193
|
+
replay_dataset_name=latest_entry.dataset_name if latest_entry else None,
|
|
194
|
+
registry_version=active_triage.latest_registry_version,
|
|
195
|
+
baseline_registry_version=active_triage.baseline_registry_version,
|
|
196
|
+
triage_decision=active_triage.decision,
|
|
197
|
+
triage_severity=active_triage.severity,
|
|
198
|
+
triage_block_rollout=active_triage.block_rollout,
|
|
199
|
+
triggers=triggers,
|
|
200
|
+
optimizer_pool=schedule_optimizer_pool,
|
|
201
|
+
max_backends=max_backends,
|
|
202
|
+
optimizer_kwargs=schedule_optimizer_kwargs,
|
|
203
|
+
optimizer_kwargs_by_backend=schedule_kwargs_by_backend,
|
|
204
|
+
rollback_kwargs=schedule_rollback_kwargs,
|
|
205
|
+
recommendations=_unique_schedule_items(recommendations),
|
|
206
|
+
evidence={
|
|
207
|
+
"triage": active_triage.to_manifest(),
|
|
208
|
+
"lineage": active_lineage.to_manifest() if active_lineage else None,
|
|
209
|
+
},
|
|
210
|
+
metadata={
|
|
211
|
+
"kind": "futureagi_registry_replay_optimizer_schedule",
|
|
212
|
+
**dict(metadata or {}),
|
|
213
|
+
},
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class FutureAGIRegressionReplayOptimizer(BaseOptimizer):
|
|
218
|
+
"""
|
|
219
|
+
Re-optimize an agent from a Future AGI regression dataset.
|
|
220
|
+
|
|
221
|
+
The optimizer accepts either an already-loaded `AgentRegressionDataset` or a
|
|
222
|
+
Future AGI `dataset_id`, turns the regression cases into an observability
|
|
223
|
+
replay window, and delegates the repair search to `AgentFeedbackOptimizer`.
|
|
224
|
+
Use `optimizer="society"`, `"social_memory"`, `"curriculum"`,
|
|
225
|
+
`"council"`, `"evolution"`, `"bandit"`, `"tpe"`, `"pareto"`, or
|
|
226
|
+
`"agent"` to select the backend.
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
def __init__(
|
|
230
|
+
self,
|
|
231
|
+
target: Optional[OptimizationTarget] = None,
|
|
232
|
+
*,
|
|
233
|
+
dataset: Optional[AgentRegressionDataset] = None,
|
|
234
|
+
dataset_id: Optional[str] = None,
|
|
235
|
+
dataset_name: Optional[str] = None,
|
|
236
|
+
fi_api_key: Optional[str] = None,
|
|
237
|
+
fi_secret_key: Optional[str] = None,
|
|
238
|
+
fi_base_url: Optional[str] = None,
|
|
239
|
+
client: Any = None,
|
|
240
|
+
page_size: int = 100,
|
|
241
|
+
max_pages: int = 100,
|
|
242
|
+
timeout: float = 30.0,
|
|
243
|
+
candidate: Optional[AgentCandidate] = None,
|
|
244
|
+
deployment: Optional[AgentDeploymentExport] = None,
|
|
245
|
+
evaluate_candidate: Optional[CandidateScorer] = None,
|
|
246
|
+
simulation_evaluator: Any = None,
|
|
247
|
+
optimizer: str = "society",
|
|
248
|
+
optimizer_kwargs: Optional[Mapping[str, Any]] = None,
|
|
249
|
+
optimizer_pool: Optional[Sequence[str]] = None,
|
|
250
|
+
max_backends: Optional[int] = None,
|
|
251
|
+
optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
|
|
252
|
+
optimizer_schedule: Optional[
|
|
253
|
+
FutureAGIReplayOptimizerSchedule | Mapping[str, Any]
|
|
254
|
+
] = None,
|
|
255
|
+
rollback_kwargs: Optional[Mapping[str, Any]] = None,
|
|
256
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
|
257
|
+
) -> None:
|
|
258
|
+
self.target = target
|
|
259
|
+
self.dataset = dataset
|
|
260
|
+
self.dataset_id = dataset_id
|
|
261
|
+
self.dataset_name = dataset_name
|
|
262
|
+
self.fi_api_key = fi_api_key
|
|
263
|
+
self.fi_secret_key = fi_secret_key
|
|
264
|
+
self.fi_base_url = fi_base_url
|
|
265
|
+
self.client = client
|
|
266
|
+
self.page_size = page_size
|
|
267
|
+
self.max_pages = max_pages
|
|
268
|
+
self.timeout = timeout
|
|
269
|
+
self.candidate = candidate
|
|
270
|
+
self.deployment = deployment
|
|
271
|
+
self.evaluate_candidate = evaluate_candidate
|
|
272
|
+
self.simulation_evaluator = simulation_evaluator
|
|
273
|
+
self.optimizer = optimizer
|
|
274
|
+
self.optimizer_kwargs = dict(optimizer_kwargs or {})
|
|
275
|
+
self.optimizer_pool = list(optimizer_pool) if optimizer_pool is not None else None
|
|
276
|
+
self.max_backends = max_backends
|
|
277
|
+
self.optimizer_kwargs_by_backend = {
|
|
278
|
+
str(key): dict(value)
|
|
279
|
+
for key, value in dict(optimizer_kwargs_by_backend or {}).items()
|
|
280
|
+
}
|
|
281
|
+
self.optimizer_schedule = _coerce_futureagi_replay_optimizer_schedule(
|
|
282
|
+
optimizer_schedule
|
|
283
|
+
)
|
|
284
|
+
self.rollback_kwargs = dict(rollback_kwargs or {})
|
|
285
|
+
self.metadata = dict(metadata or {})
|
|
286
|
+
super().__init__()
|
|
287
|
+
|
|
288
|
+
def optimize(
|
|
289
|
+
self,
|
|
290
|
+
evaluator: Any = None,
|
|
291
|
+
data_mapper: Any = None,
|
|
292
|
+
dataset_records: Optional[list[dict[str, Any]]] = None,
|
|
293
|
+
metric: Optional[Callable] = None,
|
|
294
|
+
*,
|
|
295
|
+
target: Optional[OptimizationTarget] = None,
|
|
296
|
+
dataset: Optional[AgentRegressionDataset] = None,
|
|
297
|
+
dataset_id: Optional[str] = None,
|
|
298
|
+
dataset_name: Optional[str] = None,
|
|
299
|
+
fi_api_key: Optional[str] = None,
|
|
300
|
+
fi_secret_key: Optional[str] = None,
|
|
301
|
+
fi_base_url: Optional[str] = None,
|
|
302
|
+
client: Any = None,
|
|
303
|
+
page_size: Optional[int] = None,
|
|
304
|
+
max_pages: Optional[int] = None,
|
|
305
|
+
timeout: Optional[float] = None,
|
|
306
|
+
candidate: Optional[AgentCandidate] = None,
|
|
307
|
+
deployment: Optional[AgentDeploymentExport] = None,
|
|
308
|
+
evaluate_candidate: Optional[CandidateScorer] = None,
|
|
309
|
+
simulation_evaluator: Any = None,
|
|
310
|
+
optimizer: Optional[str] = None,
|
|
311
|
+
optimizer_kwargs: Optional[Mapping[str, Any]] = None,
|
|
312
|
+
optimizer_pool: Optional[Sequence[str]] = None,
|
|
313
|
+
max_backends: Optional[int] = None,
|
|
314
|
+
optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
|
|
315
|
+
optimizer_schedule: Optional[
|
|
316
|
+
FutureAGIReplayOptimizerSchedule | Mapping[str, Any]
|
|
317
|
+
] = None,
|
|
318
|
+
rollback_kwargs: Optional[Mapping[str, Any]] = None,
|
|
319
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
|
320
|
+
**backend_kwargs: Any,
|
|
321
|
+
) -> AgentFeedbackOptimizationResult | AgentMultiInteractionOptimizationResult:
|
|
322
|
+
active_target = target or self.target
|
|
323
|
+
if active_target is None:
|
|
324
|
+
raise ValueError("FutureAGIRegressionReplayOptimizer requires a target.")
|
|
325
|
+
|
|
326
|
+
active_dataset = dataset or self.dataset
|
|
327
|
+
active_dataset_id = dataset_id or self.dataset_id
|
|
328
|
+
if active_dataset is None:
|
|
329
|
+
if not active_dataset_id:
|
|
330
|
+
raise ValueError(
|
|
331
|
+
"FutureAGIRegressionReplayOptimizer requires dataset or dataset_id."
|
|
332
|
+
)
|
|
333
|
+
active_dataset = load_futureagi_regression_dataset(
|
|
334
|
+
dataset_id=active_dataset_id,
|
|
335
|
+
dataset_name=dataset_name or self.dataset_name,
|
|
336
|
+
fi_api_key=fi_api_key or self.fi_api_key,
|
|
337
|
+
fi_secret_key=fi_secret_key or self.fi_secret_key,
|
|
338
|
+
fi_base_url=fi_base_url or self.fi_base_url,
|
|
339
|
+
client=client or self.client,
|
|
340
|
+
page_size=page_size if page_size is not None else self.page_size,
|
|
341
|
+
max_pages=max_pages if max_pages is not None else self.max_pages,
|
|
342
|
+
timeout=timeout if timeout is not None else self.timeout,
|
|
343
|
+
metadata={
|
|
344
|
+
"optimizer": "FutureAGIRegressionReplayOptimizer",
|
|
345
|
+
**self.metadata,
|
|
346
|
+
**dict(metadata or {}),
|
|
347
|
+
},
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
active_candidate = candidate or self.candidate or active_target.seed_candidate()
|
|
351
|
+
active_deployment = (
|
|
352
|
+
deployment
|
|
353
|
+
or self.deployment
|
|
354
|
+
or export_agent_deployment(
|
|
355
|
+
active_candidate,
|
|
356
|
+
metadata={
|
|
357
|
+
"futureagi_regression_dataset_name": active_dataset.name,
|
|
358
|
+
"futureagi_regression_dataset_id": active_dataset_id,
|
|
359
|
+
},
|
|
360
|
+
)
|
|
361
|
+
)
|
|
362
|
+
replay_window = active_dataset.to_observability_window(
|
|
363
|
+
candidate=active_candidate,
|
|
364
|
+
metadata={
|
|
365
|
+
"futureagi_regression_replay_optimizer": True,
|
|
366
|
+
"futureagi_regression_dataset_id": active_dataset_id,
|
|
367
|
+
},
|
|
368
|
+
)
|
|
369
|
+
live_evaluations = replay_window.to_live_evaluations()
|
|
370
|
+
active_rollback_kwargs = {
|
|
371
|
+
"required_metrics": replay_window.required_metrics,
|
|
372
|
+
"consecutive_failures": 1,
|
|
373
|
+
"min_evaluations": 1,
|
|
374
|
+
**self.rollback_kwargs,
|
|
375
|
+
**dict(rollback_kwargs or {}),
|
|
376
|
+
}
|
|
377
|
+
active_schedule = (
|
|
378
|
+
_coerce_futureagi_replay_optimizer_schedule(optimizer_schedule)
|
|
379
|
+
if optimizer_schedule is not None
|
|
380
|
+
else self.optimizer_schedule
|
|
381
|
+
)
|
|
382
|
+
if (
|
|
383
|
+
active_schedule is not None
|
|
384
|
+
and not active_schedule.should_optimize
|
|
385
|
+
and optimizer is None
|
|
386
|
+
):
|
|
387
|
+
raise ValueError(
|
|
388
|
+
"Future AGI replay optimizer schedule does not require "
|
|
389
|
+
"re-optimization."
|
|
390
|
+
)
|
|
391
|
+
schedule_optimizer_kwargs = (
|
|
392
|
+
copy.deepcopy(active_schedule.optimizer_kwargs)
|
|
393
|
+
if active_schedule is not None
|
|
394
|
+
else {}
|
|
395
|
+
)
|
|
396
|
+
active_optimizer_kwargs = {
|
|
397
|
+
**schedule_optimizer_kwargs,
|
|
398
|
+
**self.optimizer_kwargs,
|
|
399
|
+
**dict(optimizer_kwargs or {}),
|
|
400
|
+
**backend_kwargs,
|
|
401
|
+
}
|
|
402
|
+
active_optimizer_pool = (
|
|
403
|
+
list(optimizer_pool)
|
|
404
|
+
if optimizer_pool is not None
|
|
405
|
+
else (
|
|
406
|
+
self.optimizer_pool
|
|
407
|
+
if self.optimizer_pool is not None
|
|
408
|
+
else (
|
|
409
|
+
list(active_schedule.optimizer_pool)
|
|
410
|
+
if active_schedule is not None and active_schedule.optimizer_pool
|
|
411
|
+
else None
|
|
412
|
+
)
|
|
413
|
+
)
|
|
414
|
+
)
|
|
415
|
+
active_max_backends = (
|
|
416
|
+
max_backends
|
|
417
|
+
if max_backends is not None
|
|
418
|
+
else (
|
|
419
|
+
self.max_backends
|
|
420
|
+
if self.max_backends is not None
|
|
421
|
+
else (active_schedule.max_backends if active_schedule is not None else None)
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
schedule_kwargs_by_backend = (
|
|
425
|
+
copy.deepcopy(active_schedule.optimizer_kwargs_by_backend)
|
|
426
|
+
if active_schedule is not None
|
|
427
|
+
else {}
|
|
428
|
+
)
|
|
429
|
+
active_optimizer_kwargs_by_backend = {
|
|
430
|
+
**schedule_kwargs_by_backend,
|
|
431
|
+
**self.optimizer_kwargs_by_backend,
|
|
432
|
+
**{
|
|
433
|
+
str(key): dict(value)
|
|
434
|
+
for key, value in dict(optimizer_kwargs_by_backend or {}).items()
|
|
435
|
+
},
|
|
436
|
+
}
|
|
437
|
+
schedule_backend = (
|
|
438
|
+
active_schedule.selected_optimizer
|
|
439
|
+
if active_schedule is not None and active_schedule.selected_optimizer != "none"
|
|
440
|
+
else None
|
|
441
|
+
)
|
|
442
|
+
resolved_backend = optimizer or schedule_backend or self.optimizer
|
|
443
|
+
normalized_backend = _normalize_optimizer_name(resolved_backend)
|
|
444
|
+
if normalized_backend == "social_memory":
|
|
445
|
+
active_optimizer_kwargs.setdefault("experiment_history", replay_window)
|
|
446
|
+
if normalized_backend == "curriculum":
|
|
447
|
+
active_optimizer_kwargs.setdefault("curriculum_history", replay_window)
|
|
448
|
+
result_metadata = {
|
|
449
|
+
**self.metadata,
|
|
450
|
+
**dict(metadata or {}),
|
|
451
|
+
"futureagi_regression_dataset_id": active_dataset_id,
|
|
452
|
+
"futureagi_regression_dataset_name": active_dataset.name,
|
|
453
|
+
"futureagi_regression_case_count": len(active_dataset.cases),
|
|
454
|
+
"futureagi_replay_record_count": len(replay_window.records),
|
|
455
|
+
"futureagi_replay_required_metrics": dict(replay_window.required_metrics),
|
|
456
|
+
"futureagi_replay_required_trace_signals": list(
|
|
457
|
+
replay_window.required_trace_signals
|
|
458
|
+
),
|
|
459
|
+
}
|
|
460
|
+
if active_schedule is not None:
|
|
461
|
+
result_metadata.update(
|
|
462
|
+
{
|
|
463
|
+
"futureagi_replay_optimizer_schedule": active_schedule.to_manifest(),
|
|
464
|
+
"futureagi_replay_scheduled_optimizer": active_schedule.selected_optimizer,
|
|
465
|
+
"futureagi_replay_schedule_triggers": list(active_schedule.triggers),
|
|
466
|
+
}
|
|
467
|
+
)
|
|
468
|
+
if normalized_backend == "multi_interaction":
|
|
469
|
+
active_optimizer_kwargs_by_backend.setdefault(
|
|
470
|
+
"social_memory",
|
|
471
|
+
{},
|
|
472
|
+
).setdefault("experiment_history", replay_window)
|
|
473
|
+
active_optimizer_kwargs_by_backend.setdefault(
|
|
474
|
+
"curriculum",
|
|
475
|
+
{},
|
|
476
|
+
).setdefault("curriculum_history", replay_window)
|
|
477
|
+
return AgentMultiInteractionOptimizer(
|
|
478
|
+
target=active_target,
|
|
479
|
+
deployment=active_deployment,
|
|
480
|
+
live_evaluations=live_evaluations,
|
|
481
|
+
evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
|
|
482
|
+
simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
|
|
483
|
+
optimizer_pool=active_optimizer_pool,
|
|
484
|
+
max_backends=active_max_backends,
|
|
485
|
+
optimizer_kwargs=active_optimizer_kwargs,
|
|
486
|
+
optimizer_kwargs_by_backend=active_optimizer_kwargs_by_backend,
|
|
487
|
+
rollback_kwargs=active_rollback_kwargs,
|
|
488
|
+
metadata=result_metadata,
|
|
489
|
+
).optimize()
|
|
490
|
+
return AgentFeedbackOptimizer(
|
|
491
|
+
target=active_target,
|
|
492
|
+
deployment=active_deployment,
|
|
493
|
+
live_evaluations=live_evaluations,
|
|
494
|
+
evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
|
|
495
|
+
simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
|
|
496
|
+
optimizer=resolved_backend,
|
|
497
|
+
optimizer_kwargs=active_optimizer_kwargs,
|
|
498
|
+
rollback_kwargs=active_rollback_kwargs,
|
|
499
|
+
metadata=result_metadata,
|
|
500
|
+
).optimize()
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def _coerce_futureagi_replay_optimizer_schedule(
|
|
504
|
+
value: Optional[FutureAGIReplayOptimizerSchedule | Mapping[str, Any]],
|
|
505
|
+
) -> Optional[FutureAGIReplayOptimizerSchedule]:
|
|
506
|
+
if value is None:
|
|
507
|
+
return None
|
|
508
|
+
if isinstance(value, FutureAGIReplayOptimizerSchedule):
|
|
509
|
+
return value
|
|
510
|
+
if isinstance(value, Mapping):
|
|
511
|
+
return FutureAGIReplayOptimizerSchedule(**dict(value))
|
|
512
|
+
raise TypeError(
|
|
513
|
+
"optimizer_schedule must be FutureAGIReplayOptimizerSchedule or mapping."
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def _coerce_futureagi_replay_triage(
|
|
518
|
+
value: AgentRegistryReplayPackTriageReport | Mapping[str, Any],
|
|
519
|
+
) -> AgentRegistryReplayPackTriageReport:
|
|
520
|
+
if isinstance(value, AgentRegistryReplayPackTriageReport):
|
|
521
|
+
return value
|
|
522
|
+
if isinstance(value, Mapping):
|
|
523
|
+
return AgentRegistryReplayPackTriageReport(**dict(value))
|
|
524
|
+
raise TypeError("triage must be AgentRegistryReplayPackTriageReport or mapping.")
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def _coerce_futureagi_replay_lineage(
|
|
528
|
+
value: Optional[AgentRegistryReplayPackLineageReport | Mapping[str, Any]],
|
|
529
|
+
) -> Optional[AgentRegistryReplayPackLineageReport]:
|
|
530
|
+
if value is None:
|
|
531
|
+
return None
|
|
532
|
+
if isinstance(value, AgentRegistryReplayPackLineageReport):
|
|
533
|
+
return value
|
|
534
|
+
if isinstance(value, Mapping):
|
|
535
|
+
return AgentRegistryReplayPackLineageReport(**dict(value))
|
|
536
|
+
raise TypeError("lineage must be AgentRegistryReplayPackLineageReport or mapping.")
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
def _lineage_entry_for_triage(
|
|
540
|
+
lineage: Optional[AgentRegistryReplayPackLineageReport],
|
|
541
|
+
triage: AgentRegistryReplayPackTriageReport,
|
|
542
|
+
) -> Any:
|
|
543
|
+
if lineage is None:
|
|
544
|
+
return None
|
|
545
|
+
for entry in reversed(lineage.entries):
|
|
546
|
+
if triage.latest_dataset_id and entry.dataset_id == triage.latest_dataset_id:
|
|
547
|
+
return entry
|
|
548
|
+
if (
|
|
549
|
+
triage.latest_registry_version
|
|
550
|
+
and entry.registry_version == triage.latest_registry_version
|
|
551
|
+
):
|
|
552
|
+
return entry
|
|
553
|
+
return lineage.entries[-1] if lineage.entries else None
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def _unique_schedule_items(values: Sequence[Any]) -> list[str]:
|
|
557
|
+
return list(dict.fromkeys(str(value) for value in values if value))
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
class FutureAGIExperimentHistoryOptimizer(BaseOptimizer):
|
|
561
|
+
"""
|
|
562
|
+
Re-optimize an agent from native Future AGI experiment history.
|
|
563
|
+
|
|
564
|
+
This backend reads Future AGI experiment detail/stats/row payloads, converts
|
|
565
|
+
variant and row-level scores into observability feedback, and delegates the
|
|
566
|
+
repair search to `AgentFeedbackOptimizer`. Use this when the production
|
|
567
|
+
signal lives in Future AGI experiments rather than regression-pack datasets.
|
|
568
|
+
"""
|
|
569
|
+
|
|
570
|
+
def __init__(
|
|
571
|
+
self,
|
|
572
|
+
target: Optional[OptimizationTarget] = None,
|
|
573
|
+
*,
|
|
574
|
+
experiment_history: Optional[AgentObservabilityWindow] = None,
|
|
575
|
+
experiment_id: Optional[str] = None,
|
|
576
|
+
fi_api_key: Optional[str] = None,
|
|
577
|
+
fi_secret_key: Optional[str] = None,
|
|
578
|
+
fi_base_url: Optional[str] = None,
|
|
579
|
+
client: Any = None,
|
|
580
|
+
page_size: int = 100,
|
|
581
|
+
max_pages: int = 20,
|
|
582
|
+
timeout: float = 30.0,
|
|
583
|
+
include_rows: bool = True,
|
|
584
|
+
include_stats: bool = True,
|
|
585
|
+
prefer_v2: bool = True,
|
|
586
|
+
required_metrics: Optional[Mapping[str, float]] = None,
|
|
587
|
+
required_trace_signals: Optional[list[str]] = None,
|
|
588
|
+
candidate: Optional[AgentCandidate] = None,
|
|
589
|
+
deployment: Optional[AgentDeploymentExport] = None,
|
|
590
|
+
evaluate_candidate: Optional[CandidateScorer] = None,
|
|
591
|
+
simulation_evaluator: Any = None,
|
|
592
|
+
optimizer: str = "society",
|
|
593
|
+
optimizer_kwargs: Optional[Mapping[str, Any]] = None,
|
|
594
|
+
optimizer_pool: Optional[Sequence[str]] = None,
|
|
595
|
+
max_backends: Optional[int] = None,
|
|
596
|
+
optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
|
|
597
|
+
rollback_kwargs: Optional[Mapping[str, Any]] = None,
|
|
598
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
|
599
|
+
) -> None:
|
|
600
|
+
self.target = target
|
|
601
|
+
self.experiment_history = experiment_history
|
|
602
|
+
self.experiment_id = experiment_id
|
|
603
|
+
self.fi_api_key = fi_api_key
|
|
604
|
+
self.fi_secret_key = fi_secret_key
|
|
605
|
+
self.fi_base_url = fi_base_url
|
|
606
|
+
self.client = client
|
|
607
|
+
self.page_size = page_size
|
|
608
|
+
self.max_pages = max_pages
|
|
609
|
+
self.timeout = timeout
|
|
610
|
+
self.include_rows = include_rows
|
|
611
|
+
self.include_stats = include_stats
|
|
612
|
+
self.prefer_v2 = prefer_v2
|
|
613
|
+
self.required_metrics = dict(required_metrics or {})
|
|
614
|
+
self.required_trace_signals = list(required_trace_signals or [])
|
|
615
|
+
self.candidate = candidate
|
|
616
|
+
self.deployment = deployment
|
|
617
|
+
self.evaluate_candidate = evaluate_candidate
|
|
618
|
+
self.simulation_evaluator = simulation_evaluator
|
|
619
|
+
self.optimizer = optimizer
|
|
620
|
+
self.optimizer_kwargs = dict(optimizer_kwargs or {})
|
|
621
|
+
self.optimizer_pool = list(optimizer_pool) if optimizer_pool is not None else None
|
|
622
|
+
self.max_backends = max_backends
|
|
623
|
+
self.optimizer_kwargs_by_backend = {
|
|
624
|
+
str(key): dict(value)
|
|
625
|
+
for key, value in dict(optimizer_kwargs_by_backend or {}).items()
|
|
626
|
+
}
|
|
627
|
+
self.rollback_kwargs = dict(rollback_kwargs or {})
|
|
628
|
+
self.metadata = dict(metadata or {})
|
|
629
|
+
super().__init__()
|
|
630
|
+
|
|
631
|
+
def optimize(
|
|
632
|
+
self,
|
|
633
|
+
evaluator: Any = None,
|
|
634
|
+
data_mapper: Any = None,
|
|
635
|
+
dataset_records: Optional[list[dict[str, Any]]] = None,
|
|
636
|
+
metric: Optional[Callable] = None,
|
|
637
|
+
*,
|
|
638
|
+
target: Optional[OptimizationTarget] = None,
|
|
639
|
+
experiment_history: Optional[AgentObservabilityWindow] = None,
|
|
640
|
+
experiment_id: Optional[str] = None,
|
|
641
|
+
fi_api_key: Optional[str] = None,
|
|
642
|
+
fi_secret_key: Optional[str] = None,
|
|
643
|
+
fi_base_url: Optional[str] = None,
|
|
644
|
+
client: Any = None,
|
|
645
|
+
page_size: Optional[int] = None,
|
|
646
|
+
max_pages: Optional[int] = None,
|
|
647
|
+
timeout: Optional[float] = None,
|
|
648
|
+
include_rows: Optional[bool] = None,
|
|
649
|
+
include_stats: Optional[bool] = None,
|
|
650
|
+
prefer_v2: Optional[bool] = None,
|
|
651
|
+
required_metrics: Optional[Mapping[str, float]] = None,
|
|
652
|
+
required_trace_signals: Optional[list[str]] = None,
|
|
653
|
+
candidate: Optional[AgentCandidate] = None,
|
|
654
|
+
deployment: Optional[AgentDeploymentExport] = None,
|
|
655
|
+
evaluate_candidate: Optional[CandidateScorer] = None,
|
|
656
|
+
simulation_evaluator: Any = None,
|
|
657
|
+
optimizer: Optional[str] = None,
|
|
658
|
+
optimizer_kwargs: Optional[Mapping[str, Any]] = None,
|
|
659
|
+
optimizer_pool: Optional[Sequence[str]] = None,
|
|
660
|
+
max_backends: Optional[int] = None,
|
|
661
|
+
optimizer_kwargs_by_backend: Optional[Mapping[str, Mapping[str, Any]]] = None,
|
|
662
|
+
rollback_kwargs: Optional[Mapping[str, Any]] = None,
|
|
663
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
|
664
|
+
**backend_kwargs: Any,
|
|
665
|
+
) -> AgentFeedbackOptimizationResult | AgentMultiInteractionOptimizationResult:
|
|
666
|
+
active_target = target or self.target
|
|
667
|
+
if active_target is None:
|
|
668
|
+
raise ValueError("FutureAGIExperimentHistoryOptimizer requires a target.")
|
|
669
|
+
|
|
670
|
+
active_candidate = candidate or self.candidate or active_target.seed_candidate()
|
|
671
|
+
active_history = experiment_history or self.experiment_history
|
|
672
|
+
active_experiment_id = experiment_id or self.experiment_id
|
|
673
|
+
active_required_metrics = {
|
|
674
|
+
**self.required_metrics,
|
|
675
|
+
**dict(required_metrics or {}),
|
|
676
|
+
}
|
|
677
|
+
active_required_signals = list(
|
|
678
|
+
required_trace_signals
|
|
679
|
+
if required_trace_signals is not None
|
|
680
|
+
else self.required_trace_signals
|
|
681
|
+
)
|
|
682
|
+
if active_history is None:
|
|
683
|
+
if not active_experiment_id:
|
|
684
|
+
raise ValueError(
|
|
685
|
+
"FutureAGIExperimentHistoryOptimizer requires "
|
|
686
|
+
"experiment_history or experiment_id."
|
|
687
|
+
)
|
|
688
|
+
active_history = load_futureagi_experiment_history(
|
|
689
|
+
experiment_id=active_experiment_id,
|
|
690
|
+
candidate=active_candidate,
|
|
691
|
+
required_metrics=active_required_metrics,
|
|
692
|
+
required_trace_signals=active_required_signals,
|
|
693
|
+
fi_api_key=fi_api_key or self.fi_api_key,
|
|
694
|
+
fi_secret_key=fi_secret_key or self.fi_secret_key,
|
|
695
|
+
fi_base_url=fi_base_url or self.fi_base_url,
|
|
696
|
+
client=client or self.client,
|
|
697
|
+
page_size=page_size if page_size is not None else self.page_size,
|
|
698
|
+
max_pages=max_pages if max_pages is not None else self.max_pages,
|
|
699
|
+
timeout=timeout if timeout is not None else self.timeout,
|
|
700
|
+
include_rows=include_rows if include_rows is not None else self.include_rows,
|
|
701
|
+
include_stats=include_stats if include_stats is not None else self.include_stats,
|
|
702
|
+
prefer_v2=prefer_v2 if prefer_v2 is not None else self.prefer_v2,
|
|
703
|
+
metadata={
|
|
704
|
+
"optimizer": "FutureAGIExperimentHistoryOptimizer",
|
|
705
|
+
**self.metadata,
|
|
706
|
+
**dict(metadata or {}),
|
|
707
|
+
},
|
|
708
|
+
)
|
|
709
|
+
|
|
710
|
+
resolved_experiment_id = active_experiment_id or str(
|
|
711
|
+
active_history.metadata.get("experiment_id") or ""
|
|
712
|
+
)
|
|
713
|
+
active_deployment = (
|
|
714
|
+
deployment
|
|
715
|
+
or self.deployment
|
|
716
|
+
or export_agent_deployment(
|
|
717
|
+
active_candidate,
|
|
718
|
+
metadata={
|
|
719
|
+
"futureagi_experiment_id": resolved_experiment_id,
|
|
720
|
+
"futureagi_experiment_name": active_history.metadata.get(
|
|
721
|
+
"experiment_name"
|
|
722
|
+
),
|
|
723
|
+
},
|
|
724
|
+
)
|
|
725
|
+
)
|
|
726
|
+
live_evaluations = active_history.to_live_evaluations(candidate=active_candidate)
|
|
727
|
+
active_rollback_kwargs = {
|
|
728
|
+
"required_metrics": active_history.required_metrics,
|
|
729
|
+
"consecutive_failures": 1,
|
|
730
|
+
"min_evaluations": 1,
|
|
731
|
+
**self.rollback_kwargs,
|
|
732
|
+
**dict(rollback_kwargs or {}),
|
|
733
|
+
}
|
|
734
|
+
active_optimizer_kwargs = {
|
|
735
|
+
**self.optimizer_kwargs,
|
|
736
|
+
**dict(optimizer_kwargs or {}),
|
|
737
|
+
**backend_kwargs,
|
|
738
|
+
}
|
|
739
|
+
active_optimizer_pool = (
|
|
740
|
+
list(optimizer_pool) if optimizer_pool is not None else self.optimizer_pool
|
|
741
|
+
)
|
|
742
|
+
active_max_backends = self.max_backends if max_backends is None else max_backends
|
|
743
|
+
active_optimizer_kwargs_by_backend = {
|
|
744
|
+
**self.optimizer_kwargs_by_backend,
|
|
745
|
+
**{
|
|
746
|
+
str(key): dict(value)
|
|
747
|
+
for key, value in dict(optimizer_kwargs_by_backend or {}).items()
|
|
748
|
+
},
|
|
749
|
+
}
|
|
750
|
+
resolved_backend = optimizer or self.optimizer
|
|
751
|
+
normalized_backend = _normalize_optimizer_name(resolved_backend)
|
|
752
|
+
if normalized_backend == "social_memory":
|
|
753
|
+
active_optimizer_kwargs.setdefault("experiment_history", active_history)
|
|
754
|
+
if normalized_backend == "curriculum":
|
|
755
|
+
active_optimizer_kwargs.setdefault("curriculum_history", active_history)
|
|
756
|
+
result_metadata = {
|
|
757
|
+
**self.metadata,
|
|
758
|
+
**dict(metadata or {}),
|
|
759
|
+
"futureagi_experiment_id": resolved_experiment_id,
|
|
760
|
+
"futureagi_experiment_name": active_history.metadata.get("experiment_name"),
|
|
761
|
+
"futureagi_experiment_record_count": len(active_history.records),
|
|
762
|
+
"futureagi_experiment_required_metrics": dict(active_history.required_metrics),
|
|
763
|
+
"futureagi_experiment_required_trace_signals": list(
|
|
764
|
+
active_history.required_trace_signals
|
|
765
|
+
),
|
|
766
|
+
}
|
|
767
|
+
if normalized_backend == "multi_interaction":
|
|
768
|
+
active_optimizer_kwargs_by_backend.setdefault(
|
|
769
|
+
"social_memory",
|
|
770
|
+
{},
|
|
771
|
+
).setdefault("experiment_history", active_history)
|
|
772
|
+
active_optimizer_kwargs_by_backend.setdefault(
|
|
773
|
+
"curriculum",
|
|
774
|
+
{},
|
|
775
|
+
).setdefault("curriculum_history", active_history)
|
|
776
|
+
return AgentMultiInteractionOptimizer(
|
|
777
|
+
target=active_target,
|
|
778
|
+
deployment=active_deployment,
|
|
779
|
+
live_evaluations=live_evaluations,
|
|
780
|
+
evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
|
|
781
|
+
simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
|
|
782
|
+
optimizer_pool=active_optimizer_pool,
|
|
783
|
+
max_backends=active_max_backends,
|
|
784
|
+
optimizer_kwargs=active_optimizer_kwargs,
|
|
785
|
+
optimizer_kwargs_by_backend=active_optimizer_kwargs_by_backend,
|
|
786
|
+
rollback_kwargs=active_rollback_kwargs,
|
|
787
|
+
metadata=result_metadata,
|
|
788
|
+
).optimize()
|
|
789
|
+
return AgentFeedbackOptimizer(
|
|
790
|
+
target=active_target,
|
|
791
|
+
deployment=active_deployment,
|
|
792
|
+
live_evaluations=live_evaluations,
|
|
793
|
+
evaluate_candidate=evaluate_candidate or self.evaluate_candidate or evaluator,
|
|
794
|
+
simulation_evaluator=simulation_evaluator or self.simulation_evaluator,
|
|
795
|
+
optimizer=resolved_backend,
|
|
796
|
+
optimizer_kwargs=active_optimizer_kwargs,
|
|
797
|
+
rollback_kwargs=active_rollback_kwargs,
|
|
798
|
+
metadata=result_metadata,
|
|
799
|
+
).optimize()
|