evalkit-py 0.2.0.dev12__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.
- evalkit/__init__.py +0 -0
- evalkit/api/__init__.py +0 -0
- evalkit/api/access.py +74 -0
- evalkit/api/agents.py +159 -0
- evalkit/api/app.py +360 -0
- evalkit/api/auth.py +225 -0
- evalkit/api/cli_dist.py +10 -0
- evalkit/api/datasets.py +169 -0
- evalkit/api/deps.py +79 -0
- evalkit/api/download.py +15 -0
- evalkit/api/evaluators.py +121 -0
- evalkit/api/experiments.py +616 -0
- evalkit/api/fixtures.py +95 -0
- evalkit/api/harness_check.py +48 -0
- evalkit/api/imports.py +180 -0
- evalkit/api/limits.py +84 -0
- evalkit/api/llm_providers.py +120 -0
- evalkit/api/mcp/__init__.py +0 -0
- evalkit/api/mcp/auth.py +100 -0
- evalkit/api/mcp/descriptions.py +336 -0
- evalkit/api/mcp/models.py +259 -0
- evalkit/api/mcp/server.py +101 -0
- evalkit/api/mcp/tools.py +844 -0
- evalkit/api/meta.py +19 -0
- evalkit/api/otel.py +350 -0
- evalkit/api/pull.py +197 -0
- evalkit/api/review.py +271 -0
- evalkit/api/runs.py +555 -0
- evalkit/api/server_keys.py +44 -0
- evalkit/api/tokens.py +51 -0
- evalkit/api/trace_imports.py +173 -0
- evalkit/api/trace_sources.py +49 -0
- evalkit/api/traces.py +196 -0
- evalkit/api/users.py +72 -0
- evalkit/api/workspaces.py +131 -0
- evalkit/bundled/contracts/atif-accepted.json +5 -0
- evalkit/bundled/contracts/custom-evaluator-api-v1.json +243 -0
- evalkit/bundled/contracts/harness-api-v1.json +938 -0
- evalkit/bundled/contracts/span-mapping-v1.json +314 -0
- evalkit/bundled/docs/concepts.md +26 -0
- evalkit/bundled/docs/config.md +38 -0
- evalkit/bundled/docs/harness-api.md +44 -0
- evalkit/bundled/docs/install.md +60 -0
- evalkit/bundled/docs/login.md +36 -0
- evalkit/bundled/docs/mappings.md +136 -0
- evalkit/bundled/docs/mcp.md +44 -0
- evalkit/bundled/docs/quickstart.md +142 -0
- evalkit/bundled/docs/sdk-runs.md +171 -0
- evalkit/bundled/docs/tracing.md +171 -0
- evalkit/bundled/docs/try-locally.md +288 -0
- evalkit/bundled/docs/workspaces.md +45 -0
- evalkit/bundled/skills/authoring-eval-cases/SKILL.md +387 -0
- evalkit/bundled/skills/authoring-eval-cases/references/overlays.md +83 -0
- evalkit/bundled/skills/authoring-eval-cases/references/tool-checks.md +71 -0
- evalkit/bundled/skills/connect-traces/SKILL.md +296 -0
- evalkit/bundled/skills/connect-traces/references/gen_ai.json +42 -0
- evalkit/bundled/skills/connect-traces/references/openinference.json +35 -0
- evalkit/bundled/skills/connect-traces/references/span-mapping-schema.md +88 -0
- evalkit/bundled/skills/eval-driven-development/SKILL.md +458 -0
- evalkit/bundled/skills/eval-driven-development/references/analyze-run.md +97 -0
- evalkit/bundled/skills/eval-driven-development/references/diagnose.md +130 -0
- evalkit/bundled/skills/eval-driven-development/references/synthesize-cases.md +87 -0
- evalkit/bundled/skills/eval-driven-development/references/synthesize.md +165 -0
- evalkit/bundled/skills/evalkit-deployment/SKILL.md +332 -0
- evalkit/bundled/skills/evalkit-deployment/config.example.yaml +49 -0
- evalkit/bundled/skills/evalkit-deployment/docker-compose.yml +51 -0
- evalkit/bundled/skills/evalkit-deployment/references/config-and-deploy.md +333 -0
- evalkit/bundled/skills/evalkit-deployment/references/harness-api.md +139 -0
- evalkit/bundled/skills/evalkit-deployment/try/.env.example +11 -0
- evalkit/bundled/skills/evalkit-deployment/try/agent.py +131 -0
- evalkit/bundled/skills/evalkit-deployment/try/cases/acme/balance-sheet/cases.yaml +25 -0
- evalkit/bundled/skills/evalkit-deployment/try/cases/acme/income-statement/cases.yaml +43 -0
- evalkit/bundled/skills/evalkit-deployment/try/config.yaml +17 -0
- evalkit/bundled/skills/evalkit-deployment/try/docker-compose.yml +82 -0
- evalkit/bundled/skills/evalkit-deployment/try/evalkit.yaml +4 -0
- evalkit/bundled/skills/evalkit-deployment/try/mapping.json +42 -0
- evalkit/bundled/skills/evalkit-deployment/try/run.py +33 -0
- evalkit/bundled/skills/evalkit-usage/SKILL.md +509 -0
- evalkit/bundled/skills/evalkit-usage/references/suite-fixtures.md +42 -0
- evalkit/bundled/ui/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- evalkit/bundled/ui/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- evalkit/bundled/ui/assets/abap-08VXUWAP.js +1 -0
- evalkit/bundled/ui/assets/apex-BWPQTe0t.js +1 -0
- evalkit/bundled/ui/assets/azcli-Bc_sGQ0U.js +1 -0
- evalkit/bundled/ui/assets/bat-i0X4ZdIN.js +1 -0
- evalkit/bundled/ui/assets/bicep-B5-_aFwp.js +2 -0
- evalkit/bundled/ui/assets/cameligo-DMUM7wLl.js +1 -0
- evalkit/bundled/ui/assets/clojure-Cm7r79vr.js +1 -0
- evalkit/bundled/ui/assets/codicon-DF1abBS2.ttf +0 -0
- evalkit/bundled/ui/assets/coffee-Ba7i2nA0.js +1 -0
- evalkit/bundled/ui/assets/cpp-C7h46wYY.js +1 -0
- evalkit/bundled/ui/assets/csharp-BKxtCVv1.js +1 -0
- evalkit/bundled/ui/assets/csp-bTuwJoIa.js +1 -0
- evalkit/bundled/ui/assets/css-DIMkf-bt.js +3 -0
- evalkit/bundled/ui/assets/css.worker-DwfUZ3fB.js +96 -0
- evalkit/bundled/ui/assets/cssMode-C97l1pbB.js +1 -0
- evalkit/bundled/ui/assets/cypher-CVaqCwHa.js +1 -0
- evalkit/bundled/ui/assets/dart-onAF5SnQ.js +1 -0
- evalkit/bundled/ui/assets/dockerfile-DZFCIeNp.js +1 -0
- evalkit/bundled/ui/assets/ecl-94qehhXe.js +1 -0
- evalkit/bundled/ui/assets/editor-DjpsE8to.css +1 -0
- evalkit/bundled/ui/assets/editor.api-NTesIxw5.js +908 -0
- evalkit/bundled/ui/assets/editor.worker-CRz__AKW.js +33 -0
- evalkit/bundled/ui/assets/elixir-6RTg0lbw.js +1 -0
- evalkit/bundled/ui/assets/flow9-C5_-GSwl.js +1 -0
- evalkit/bundled/ui/assets/freemarker2-BWqEFagp.js +3 -0
- evalkit/bundled/ui/assets/fsharp-C8Ef5oNN.js +1 -0
- evalkit/bundled/ui/assets/go-C-y9NEjX.js +1 -0
- evalkit/bundled/ui/assets/graphql-fmXr3nnJ.js +1 -0
- evalkit/bundled/ui/assets/handlebars-DkIF-whN.js +1 -0
- evalkit/bundled/ui/assets/hcl-CpzslTdj.js +1 -0
- evalkit/bundled/ui/assets/html-C_rpeQXJ.js +1 -0
- evalkit/bundled/ui/assets/html.worker-D9ugpX4y.js +509 -0
- evalkit/bundled/ui/assets/htmlMode-B0YIq3DF.js +1 -0
- evalkit/bundled/ui/assets/index-Cw-jBH6M.js +736 -0
- evalkit/bundled/ui/assets/index-DKtoQZtm.css +1 -0
- evalkit/bundled/ui/assets/ini-sBoK_t0W.js +1 -0
- evalkit/bundled/ui/assets/java-BEtHBSE6.js +1 -0
- evalkit/bundled/ui/assets/javascript-D4EGhYA6.js +1 -0
- evalkit/bundled/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- evalkit/bundled/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- evalkit/bundled/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- evalkit/bundled/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- evalkit/bundled/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- evalkit/bundled/ui/assets/json.worker-CV9fqkUp.js +65 -0
- evalkit/bundled/ui/assets/jsonMode-pQjSfIH6.js +7 -0
- evalkit/bundled/ui/assets/julia-Bri6UV-V.js +1 -0
- evalkit/bundled/ui/assets/kotlin-BOotOW0E.js +1 -0
- evalkit/bundled/ui/assets/less-B9JPFI3C.js +2 -0
- evalkit/bundled/ui/assets/lexon-CfSJPG6W.js +1 -0
- evalkit/bundled/ui/assets/liquid-DbrvoYjD.js +1 -0
- evalkit/bundled/ui/assets/lspLanguageFeatures-D0B7cH6y.js +4 -0
- evalkit/bundled/ui/assets/lua-CsQS60Ue.js +1 -0
- evalkit/bundled/ui/assets/m3-D-oSqn_W.js +1 -0
- evalkit/bundled/ui/assets/markdown-Cimd5fb3.js +1 -0
- evalkit/bundled/ui/assets/mdx-B0HrujLR.js +1 -0
- evalkit/bundled/ui/assets/mips-CIPQ_RoX.js +1 -0
- evalkit/bundled/ui/assets/monacoEditor-DsoPncxW.js +68 -0
- evalkit/bundled/ui/assets/monacoEditor-n7clI0si.css +1 -0
- evalkit/bundled/ui/assets/msdax-DauUninz.js +1 -0
- evalkit/bundled/ui/assets/mysql-SOo6toE5.js +1 -0
- evalkit/bundled/ui/assets/objective-c-FvmIjYaQ.js +1 -0
- evalkit/bundled/ui/assets/pascal-DrH0SRf2.js +1 -0
- evalkit/bundled/ui/assets/pascaligo-D-ptJ9y-.js +1 -0
- evalkit/bundled/ui/assets/perl-oz_6vUea.js +1 -0
- evalkit/bundled/ui/assets/pgsql-DTj74zXo.js +1 -0
- evalkit/bundled/ui/assets/php-nr791fC2.js +1 -0
- evalkit/bundled/ui/assets/pla-CopQ2nXW.js +1 -0
- evalkit/bundled/ui/assets/postiats-43DmfD33.js +1 -0
- evalkit/bundled/ui/assets/powerquery-D3hlyOfw.js +1 -0
- evalkit/bundled/ui/assets/powershell-DmHpPYUd.js +1 -0
- evalkit/bundled/ui/assets/protobuf-C531GsRP.js +2 -0
- evalkit/bundled/ui/assets/pug-Z5eAx3Zn.js +1 -0
- evalkit/bundled/ui/assets/python-CieHVM9n.js +1 -0
- evalkit/bundled/ui/assets/qsharp-DkqhCAOL.js +1 -0
- evalkit/bundled/ui/assets/r-BwWrilGY.js +1 -0
- evalkit/bundled/ui/assets/razor-sLewSMyp.js +1 -0
- evalkit/bundled/ui/assets/redis-ClamHrr6.js +1 -0
- evalkit/bundled/ui/assets/redshift-DT7zqm-g.js +1 -0
- evalkit/bundled/ui/assets/restructuredtext-BYgofb2h.js +1 -0
- evalkit/bundled/ui/assets/ruby-DezsRK8O.js +1 -0
- evalkit/bundled/ui/assets/rust-DdL9SqIa.js +1 -0
- evalkit/bundled/ui/assets/sb-CcwsVR0C.js +1 -0
- evalkit/bundled/ui/assets/scala-DHpiXF5c.js +1 -0
- evalkit/bundled/ui/assets/scheme-BeGwcela.js +1 -0
- evalkit/bundled/ui/assets/scss-gp-XZpBa.js +3 -0
- evalkit/bundled/ui/assets/shell-CC2rA5mh.js +1 -0
- evalkit/bundled/ui/assets/solidity-BEEn4gHE.js +1 -0
- evalkit/bundled/ui/assets/sophia-CRfGWb83.js +1 -0
- evalkit/bundled/ui/assets/sparql-D_Lu-MrJ.js +1 -0
- evalkit/bundled/ui/assets/sql-NEE52Syq.js +1 -0
- evalkit/bundled/ui/assets/st-DbInun42.js +1 -0
- evalkit/bundled/ui/assets/swift-Bxkupp3x.js +1 -0
- evalkit/bundled/ui/assets/systemverilog-Bz4Y3fRF.js +1 -0
- evalkit/bundled/ui/assets/tcl-DISqw1ZD.js +1 -0
- evalkit/bundled/ui/assets/ts.worker-DIAQkoB3.js +67741 -0
- evalkit/bundled/ui/assets/tsMode-BcVQ1nu0.js +11 -0
- evalkit/bundled/ui/assets/twig-De2hgUGE.js +1 -0
- evalkit/bundled/ui/assets/typescript-CUvNWd9p.js +1 -0
- evalkit/bundled/ui/assets/typespec-B8J7ngcE.js +1 -0
- evalkit/bundled/ui/assets/vb-DV3o63ZY.js +1 -0
- evalkit/bundled/ui/assets/wgsl-DpFanUEy.js +298 -0
- evalkit/bundled/ui/assets/workers-CwpYQtzp.js +1 -0
- evalkit/bundled/ui/assets/xml-C1HnXMdF.js +1 -0
- evalkit/bundled/ui/assets/yaml-D7Ey3HQu.js +1 -0
- evalkit/bundled/ui/favicon.svg +6 -0
- evalkit/bundled/ui/index.html +14 -0
- evalkit/cli/__init__.py +0 -0
- evalkit/cli/admin_commands.py +590 -0
- evalkit/cli/client.py +67 -0
- evalkit/cli/init_server.py +165 -0
- evalkit/cli/local_run.py +195 -0
- evalkit/cli/main.py +1365 -0
- evalkit/cli/runs_commands.py +539 -0
- evalkit/cli/server_commands.py +130 -0
- evalkit/cli/skill_targets.py +43 -0
- evalkit/cli/tokens_commands.py +52 -0
- evalkit/cli/traces_commands.py +332 -0
- evalkit/cli/update.py +85 -0
- evalkit/client/__init__.py +0 -0
- evalkit/client/agents.py +25 -0
- evalkit/client/api.py +193 -0
- evalkit/client/blob.py +104 -0
- evalkit/client/connection.py +88 -0
- evalkit/client/evaluators.py +11 -0
- evalkit/client/sessions.py +17 -0
- evalkit/client/store.py +139 -0
- evalkit/client/summary.py +46 -0
- evalkit/client/sync.py +198 -0
- evalkit/config.py +227 -0
- evalkit/contracts/__init__.py +0 -0
- evalkit/contracts/atif.py +115 -0
- evalkit/contracts/cases.py +456 -0
- evalkit/contracts/custom_evaluator.py +58 -0
- evalkit/contracts/enums.py +86 -0
- evalkit/contracts/esf.py +120 -0
- evalkit/contracts/harness.py +281 -0
- evalkit/contracts/notes.json +4 -0
- evalkit/contracts/notes.py +7 -0
- evalkit/contracts/settings.py +41 -0
- evalkit/core/__init__.py +0 -0
- evalkit/core/access.py +75 -0
- evalkit/core/agents.py +65 -0
- evalkit/core/blob.py +46 -0
- evalkit/core/capabilities.py +36 -0
- evalkit/core/costmap.py +90 -0
- evalkit/core/custom_eval.py +50 -0
- evalkit/core/data/cost_map.json +81546 -0
- evalkit/core/endpoints.py +31 -0
- evalkit/core/evaluators/__init__.py +29 -0
- evalkit/core/evaluators/base.py +121 -0
- evalkit/core/evaluators/gauges.py +84 -0
- evalkit/core/evaluators/presentation.py +166 -0
- evalkit/core/evaluators/response_time.py +21 -0
- evalkit/core/evaluators/rubrics.py +494 -0
- evalkit/core/evaluators/tool_trajectory.py +187 -0
- evalkit/core/evaluators/trajectory_rubrics.py +198 -0
- evalkit/core/fixtures.py +57 -0
- evalkit/core/harness.py +227 -0
- evalkit/core/harness_check.py +191 -0
- evalkit/core/importer.py +257 -0
- evalkit/core/judge.py +78 -0
- evalkit/core/lint.py +265 -0
- evalkit/core/overlays.py +76 -0
- evalkit/core/paths.py +25 -0
- evalkit/core/promotion.py +94 -0
- evalkit/core/pull.py +198 -0
- evalkit/core/python_eval.py +59 -0
- evalkit/core/remote_evaluators.py +32 -0
- evalkit/core/review.py +220 -0
- evalkit/core/run_digest.py +421 -0
- evalkit/core/runner.py +995 -0
- evalkit/core/scorecard.py +255 -0
- evalkit/core/traces/__init__.py +0 -0
- evalkit/core/traces/convert.py +336 -0
- evalkit/core/traces/importer.py +113 -0
- evalkit/core/traces/mapping.py +385 -0
- evalkit/core/traces/poll.py +38 -0
- evalkit/core/traces/raw.py +21 -0
- evalkit/core/traces/sessions.py +172 -0
- evalkit/core/traces/settle.py +14 -0
- evalkit/core/traces/sources/__init__.py +19 -0
- evalkit/core/traces/sources/base.py +25 -0
- evalkit/core/traces/sources/phoenix.py +121 -0
- evalkit/core/trajectory.py +248 -0
- evalkit/core/workspace.py +30 -0
- evalkit/credentials.py +119 -0
- evalkit/db/__init__.py +0 -0
- evalkit/db/agents.py +289 -0
- evalkit/db/alembic/env.py +90 -0
- evalkit/db/alembic/script.py.mako +28 -0
- evalkit/db/alembic/versions/0011_baseline.py +1002 -0
- evalkit/db/alembic/versions/0012_ticket_token_kind.py +27 -0
- evalkit/db/alembic/versions/0013_keys_and_llm_providers.py +67 -0
- evalkit/db/cases.py +608 -0
- evalkit/db/crypto.py +12 -0
- evalkit/db/evaluators.py +156 -0
- evalkit/db/experiments.py +363 -0
- evalkit/db/fixture_blobs.py +91 -0
- evalkit/db/keys.py +78 -0
- evalkit/db/llm_providers.py +176 -0
- evalkit/db/locks.py +6 -0
- evalkit/db/mappings.py +168 -0
- evalkit/db/models.py +567 -0
- evalkit/db/promotion.py +271 -0
- evalkit/db/rekey.py +46 -0
- evalkit/db/review.py +250 -0
- evalkit/db/review_state.py +50 -0
- evalkit/db/runs.py +533 -0
- evalkit/db/scorecard.py +300 -0
- evalkit/db/session.py +71 -0
- evalkit/db/sessions.py +90 -0
- evalkit/db/spans.py +360 -0
- evalkit/db/store.py +209 -0
- evalkit/db/tokens.py +100 -0
- evalkit/db/trace_imports.py +308 -0
- evalkit/db/trace_sources.py +131 -0
- evalkit/db/users.py +186 -0
- evalkit/db/workspaces.py +232 -0
- evalkit/paths.py +33 -0
- evalkit/sdk/__init__.py +29 -0
- evalkit/sdk/binding.py +69 -0
- evalkit/sdk/evaluators.py +56 -0
- evalkit/sdk/runner.py +957 -0
- evalkit/sdk/tracing.py +166 -0
- evalkit/store/__init__.py +0 -0
- evalkit/store/base.py +354 -0
- evalkit/store/blob.py +69 -0
- evalkit/version.py +44 -0
- evalkit_py-0.2.0.dev12.dist-info/METADATA +205 -0
- evalkit_py-0.2.0.dev12.dist-info/RECORD +371 -0
- evalkit_py-0.2.0.dev12.dist-info/WHEEL +4 -0
- evalkit_py-0.2.0.dev12.dist-info/entry_points.txt +2 -0
- evalkit_py-0.2.0.dev12.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: connect-traces
|
|
3
|
+
description: Use when wiring a client's OpenTelemetry traces into evalkit so run_experiment or a harness run gets trajectories, when creating an OTel agent (it needs a span mapping), or when `evalkit traces check` shows wrong span kinds, empty messages or missing tokens.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# connect-traces
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
evalkit scores an agent on its **trajectory**: the LLM calls, messages, tool
|
|
11
|
+
calls and token counts of one run. When the agent emits OpenTelemetry spans,
|
|
12
|
+
evalkit builds that trajectory from the spans itself: the agent exports every
|
|
13
|
+
span to the evalkit server (the **collector**), the server groups the spans of
|
|
14
|
+
one run into an **agent session** by the `session.id` attribute, reads each
|
|
15
|
+
span into the evalkit span format (**ESF**) with a **mapping**, and converts
|
|
16
|
+
the session to ATIF. Nothing in the client's code converts anything.
|
|
17
|
+
|
|
18
|
+
Your job ends when `evalkit traces check` shows the right span kinds,
|
|
19
|
+
messages, tool calls and tokens for one session. Scoring, scorecards and the
|
|
20
|
+
ATIF conversion are evalkit's side and need nothing from you.
|
|
21
|
+
|
|
22
|
+
Traces replace the trajectory only. The files a run wrote (the run's
|
|
23
|
+
Workspace tab in evalkit) come from the Harness API files endpoints, which
|
|
24
|
+
spans do not carry. If the developer wants that tab, the agent needs a
|
|
25
|
+
Harness API with those endpoints (see the evalkit-usage skill).
|
|
26
|
+
|
|
27
|
+
Every OTel agent has its own mapping, set when the agent is created. Two
|
|
28
|
+
starting points ship in `references/`: `openinference.json` for spans with
|
|
29
|
+
`openinference.span.kind`, and `gen_ai.json` for spans with
|
|
30
|
+
`gen_ai.operation.name`. Copy the one that
|
|
31
|
+
fits and change it if the agent's attributes differ. The mapping also holds
|
|
32
|
+
two run-level settings:
|
|
33
|
+
|
|
34
|
+
- `answer`: where the run's answer comes from. `root` (the usual value), a
|
|
35
|
+
span name, or `<span name>.<output key>`.
|
|
36
|
+
- `exclude_spans`: span names left out of the trajectory.
|
|
37
|
+
|
|
38
|
+
A span the agent's mapping cannot read is not an error: it comes out as kind
|
|
39
|
+
`other` with every attribute listed as unmapped, and the trajectory simply
|
|
40
|
+
lacks it. That is what a wrong mapping looks like in the check.
|
|
41
|
+
|
|
42
|
+
## Steps
|
|
43
|
+
|
|
44
|
+
1. **Identify the instrumentation.** Grep the repository for `openinference`
|
|
45
|
+
and `gen_ai.`. Note which one applies, or neither. Then make sure the
|
|
46
|
+
instrumentation records message content: without it evalkit gets token
|
|
47
|
+
counts but no messages, tool arguments or results, and the trajectory is
|
|
48
|
+
close to empty. The GenAI conventions turn content capture off by
|
|
49
|
+
default; the usual switches are:
|
|
50
|
+
|
|
51
|
+
| Instrumentation | Switch |
|
|
52
|
+
| -- | -- |
|
|
53
|
+
| OpenTelemetry GenAI instrumentations (Python `opentelemetry-instrumentation-openai-v2`, Google GenAI, Vertex AI, …) | `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true` |
|
|
54
|
+
| OpenInference | on by default; check `OPENINFERENCE_HIDE_INPUTS` / `OPENINFERENCE_HIDE_OUTPUTS` (and the `_MESSAGES` variants) are not `true` |
|
|
55
|
+
| OpenLLMetry (Traceloop) | on by default; check `TRACELOOP_TRACE_CONTENT` is not `false` |
|
|
56
|
+
| Vercel AI SDK | `experimental_telemetry: { isEnabled: true }`; `recordInputs` / `recordOutputs` default to on |
|
|
57
|
+
|
|
58
|
+
Turn it on wherever spans are exported to evalkit: the process that runs
|
|
59
|
+
the eval, and any deployed agent or worker those runs call. Whether a
|
|
60
|
+
deployed agent also exports its app traffic (runs outside any experiment:
|
|
61
|
+
production, staging, or by hand) is the developer's choice; ask them.
|
|
62
|
+
evalkit shows app sessions on the Runs page too, and `evalkit runs pull
|
|
63
|
+
<agent> --source app` downloads them. Exporting app traffic is also what
|
|
64
|
+
lets the eval-driven-development skill mine new cases from real runs
|
|
65
|
+
(its Loop 2).
|
|
66
|
+
To export only eval runs, see "Choosing what a shared worker exports"
|
|
67
|
+
below.
|
|
68
|
+
2. **Create the agent with a mapping.** Copy the starting point from
|
|
69
|
+
step 1 into the repo and create the agent with it. Add `--harness-url`
|
|
70
|
+
when the agent also has a Harness API; leave it out for a code-driven
|
|
71
|
+
agent.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cp <this skill>/references/openinference.json eval/span-mapping.json
|
|
75
|
+
evalkit agents create <agent> --trajectory-source otel --mapping eval/span-mapping.json
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The agent must exist before any span arrives: the collector refuses spans
|
|
79
|
+
for an unknown agent, and neither a token nor the first export creates
|
|
80
|
+
one.
|
|
81
|
+
3. **Register the exporter.** *After* the client's own tracer provider is set
|
|
82
|
+
up, add
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from evalkit.sdk import tracing
|
|
86
|
+
|
|
87
|
+
tracing.register(agent="<agent name>")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`register` adds an exporter to the provider that exists; placed before the
|
|
91
|
+
client's setup it creates a second provider and the agent's spans never
|
|
92
|
+
reach it. It needs the `otel` extra (`uv add "evalkit-py[otel]==<server version>"`).
|
|
93
|
+
When the client builds its own pipeline and should not touch the global
|
|
94
|
+
provider, use the parts `register` is made of:
|
|
95
|
+
`tracing.processor(agent=...)` returns evalkit's batch processor (it also
|
|
96
|
+
stamps the run's `session.id` and `evalkit.*` attributes),
|
|
97
|
+
`tracing.exporter(agent=...)` the OTLP HTTP exporter inside it, and
|
|
98
|
+
`tracing.headers(agent=...)` its headers. All three read the server URL
|
|
99
|
+
and token like `register` does, `EVALKIT_OTEL_TOKEN` first.
|
|
100
|
+
`register` only sees spans that pass through the provider's span
|
|
101
|
+
processors. Code that hands spans straight to one processor or exporter
|
|
102
|
+
(a bridge that converts another tool's spans, for example) bypasses it;
|
|
103
|
+
give that code `tracing.processor(...)` as well, or one
|
|
104
|
+
`SynchronousMultiSpanProcessor` that holds every processor, evalkit's
|
|
105
|
+
included. Such spans are already finished, so the processor cannot stamp
|
|
106
|
+
them: the bridge copies `session.id` onto each span it converts.
|
|
107
|
+
A non-Python agent, or any exporter outside the process that calls
|
|
108
|
+
`run_experiment`, sets
|
|
109
|
+
`OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=<server>/api/otel/v1/traces` and
|
|
110
|
+
`OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <token>,X-Evalkit-Agent=<agent>"`
|
|
111
|
+
instead, with an agent token from `evalkit tokens create --agent <agent>`.
|
|
112
|
+
The login token expires and a long-running worker then loses every span
|
|
113
|
+
without an error of its own. One process that serves several agents can
|
|
114
|
+
name the agent per span or per resource with the `evalkit.agent`
|
|
115
|
+
attribute; the header is the default for spans that carry none.
|
|
116
|
+
LLM spans that carry the full input of every call (OpenInference and
|
|
117
|
+
GenAI instrumentations do) are large, so also set
|
|
118
|
+
`OTEL_BSP_MAX_EXPORT_BATCH_SIZE=16` and `OTEL_EXPORTER_OTLP_TIMEOUT=60`
|
|
119
|
+
on every process that exports (seconds in Python; other SDKs read
|
|
120
|
+
milliseconds, `60000`). The server refuses a batch over
|
|
121
|
+
`otel.max_batch_bytes` (16 MiB by default) with `413` and the spans are
|
|
122
|
+
lost, and the default 10 s timeout is too short for multi-MB spans.
|
|
123
|
+
4. **Run one session.** `run_experiment(..., dry_run=True)` runs one case,
|
|
124
|
+
creates no experiment, and prints the session id (`session <id>: N spans
|
|
125
|
+
...`). The agent's own entry point works too; the Runs page lists the
|
|
126
|
+
session either way.
|
|
127
|
+
5. **Check it.**
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
evalkit traces check <agent> <session id> --dump spans.json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Read the lines against this table. `spans.json` holds the raw attributes.
|
|
134
|
+
|
|
135
|
+
| Line | What it tells you |
|
|
136
|
+
| -- | -- |
|
|
137
|
+
| `session` | span count, trace count, settled or not |
|
|
138
|
+
| `root` | the root span's name and kind; missing root means the session id is not on the root span |
|
|
139
|
+
| `mapping` | the active version, `vN` |
|
|
140
|
+
| `llm` | spans read as `llm`, the model, token totals; `no llm spans` means the kind rule does not match; `without messages` means those spans carry no messages, usually because message content capture is off |
|
|
141
|
+
| `tools` | spans read as `tool`, and how many carry a `tool_call_id` that matches a call the LLM spans emitted; a gap means tool spans exist but their call ids are not read, so results only match by time and order; `in no step` names tool spans that started before any LLM span and so are not in the trajectory |
|
|
142
|
+
| `unmapped` | attributes no rule read, apart from the mapping's `known_attributes` |
|
|
143
|
+
| `trajectory` | ATIF steps, tool calls, subagents |
|
|
144
|
+
|
|
145
|
+
Then check the agent's top-level span is an AGENT span
|
|
146
|
+
(`openinference.span.kind=AGENT` or `gen_ai.operation.name=invoke_agent`).
|
|
147
|
+
evalkit builds the main trajectory from it, and every AGENT span inside it
|
|
148
|
+
becomes a subagent named by its `agent.name` (`gen_ai.agent.name`). When
|
|
149
|
+
the root span is not an AGENT span, evalkit takes the earliest AGENT span
|
|
150
|
+
that is not inside another one as the main agent. If that span is a tool
|
|
151
|
+
call that starts a subagent partway through the run, the subagent's steps
|
|
152
|
+
end up in the main trajectory and its call has no result. Fix that in the
|
|
153
|
+
agent's instrumentation: mark its top-level span as an AGENT span.
|
|
154
|
+
|
|
155
|
+
If the check fails with `413` and names `otel.max_session_bytes`, the
|
|
156
|
+
session holds more span attributes than the server will build into a
|
|
157
|
+
trajectory (384 MiB by default). The limit counts what a build loads: the
|
|
158
|
+
input messages of each agent's first LLM call, and the output, tool calls
|
|
159
|
+
and tokens of every LLM call, not the input of later calls. Check a shorter session, and tell the
|
|
160
|
+
developer: the deployment's admin can raise the limit together with the
|
|
161
|
+
server's memory.
|
|
162
|
+
|
|
163
|
+
When the lines look right, stop.
|
|
164
|
+
6. **Fix the mapping** when they do not. Edit `eval/span-mapping.json` (it is
|
|
165
|
+
JSON, one rule per ESF field) and change the attribute keys to the ones in
|
|
166
|
+
`spans.json`.
|
|
167
|
+
`references/span-mapping-schema.md` explains every rule shape and the
|
|
168
|
+
three message formats. Push it as a draft and check with it:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
evalkit traces mapping push <agent> eval/span-mapping.json
|
|
172
|
+
evalkit traces check <agent> <session id> --mapping draft
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Repeat until the unmapped list holds nothing that matters and the counts
|
|
176
|
+
are right. A push replaces the previous draft and gets the next version.
|
|
177
|
+
7. **Activation needs the developer's approval.** If the developer has
|
|
178
|
+
approved the document in this conversation, run
|
|
179
|
+
`evalkit traces mapping push <agent> eval/span-mapping.json --activate`.
|
|
180
|
+
Otherwise tell them to review it on the agent's Mappings tab (Agents →
|
|
181
|
+
the agent → Mappings in the web UI) and activate it there. Green check
|
|
182
|
+
output is not approval; a mapping applies to every future run of the agent.
|
|
183
|
+
|
|
184
|
+
## An agent in another process
|
|
185
|
+
|
|
186
|
+
`tracing.register` stamps `session.id` and the `evalkit.*` attributes only on
|
|
187
|
+
spans made in the process that calls `run_experiment`. An agent behind HTTP
|
|
188
|
+
or a job queue, or written in another language, joins the run in one of two
|
|
189
|
+
ways. Pick one, not both.
|
|
190
|
+
|
|
191
|
+
- **Continue the trace.** The task injects the W3C trace context into the
|
|
192
|
+
request (`opentelemetry.propagate.inject(headers)`) and the agent starts its
|
|
193
|
+
spans from it (`traceparent`). Every span in a trace belongs to the session
|
|
194
|
+
of the trace's root, the SDK's `evalkit.run` span, even when the agent
|
|
195
|
+
stamps its own `session.id` or `gen_ai.conversation.id`. The task returns
|
|
196
|
+
only the answer.
|
|
197
|
+
- **Return the agent's session.** The agent puts its own session id on its
|
|
198
|
+
root span as `session.id`, and the task returns
|
|
199
|
+
`RunResult(answer=..., session_id=<that id>)`. Use this when the trace
|
|
200
|
+
context cannot reach the agent, for example through a queue. The SDK moves
|
|
201
|
+
its `evalkit.run` span into that session so no empty session is left
|
|
202
|
+
behind, and the server builds the trajectory from the agent's trace.
|
|
203
|
+
|
|
204
|
+
Either way the run's row on the Runs page links the session to its case.
|
|
205
|
+
|
|
206
|
+
A queue-backed agent usually opens its session in the worker, after the API
|
|
207
|
+
call has returned. Two ways to get the session id to evalkit, no new field
|
|
208
|
+
needed on either path:
|
|
209
|
+
|
|
210
|
+
- **Code-driven (`run_experiment`).** The task returns
|
|
211
|
+
`RunResult(session_id=...)` with whatever id the agent's own API returns.
|
|
212
|
+
If the API cannot return one, the task passes `metadata["session_id"]`
|
|
213
|
+
(the SDK's own session id) along with the job, and the agent uses it as
|
|
214
|
+
its session id; the task then returns only the answer.
|
|
215
|
+
- **Harness API with an `otel` trajectory source.** The session evalkit polls is the `run_id`
|
|
216
|
+
that `POST /runs` returns. Return the agent's own session id as `run_id`,
|
|
217
|
+
or stamp the returned `run_id` on the job's spans as `session.id`.
|
|
218
|
+
|
|
219
|
+
## Choosing what a shared worker exports
|
|
220
|
+
|
|
221
|
+
A worker that serves app and eval runs exports every span it makes, so each
|
|
222
|
+
app turn also becomes a session on the evalkit server, where
|
|
223
|
+
the developer can browse it on the Runs page. That is a valid setup; ask the
|
|
224
|
+
developer whether they want it. evalkit provides the stamping to tell eval
|
|
225
|
+
runs apart either way. To export only the eval runs:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from evalkit.sdk import tracing
|
|
229
|
+
|
|
230
|
+
provider.add_span_processor(tracing.processor(agent="<agent>", only=tracing.is_eval_span))
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def handle_job(job):
|
|
234
|
+
if job.evalkit: # the task's metadata, sent with the job
|
|
235
|
+
with tracing.eval_run(job.evalkit):
|
|
236
|
+
return run_agent(job)
|
|
237
|
+
return run_agent(job)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
`eval_run` stamps `session.id` (the SDK's session id) and the `evalkit.*`
|
|
241
|
+
attributes on every span started inside it, so those spans also join the
|
|
242
|
+
run's session. `is_eval_span` is true for a span that carries
|
|
243
|
+
`evalkit.case_id`. Spans started in another thread need that thread inside
|
|
244
|
+
`eval_run` too. Do not use a sampler: it drops spans for every exporter, the
|
|
245
|
+
client's own backend included.
|
|
246
|
+
|
|
247
|
+
A harness agent learns that a run is an eval run from the `metadata` of
|
|
248
|
+
`POST /runs` (`experiment_id`, `case_id`, `repetition`). That is what it
|
|
249
|
+
passes to `eval_run`, with the `run_id` it returns as the session id:
|
|
250
|
+
`tracing.eval_run({**metadata, "session_id": run_id})`.
|
|
251
|
+
|
|
252
|
+
`only` decides by trace. It runs on each span as it starts and as it ends;
|
|
253
|
+
once it is true for one span, the processor keeps every span of that trace
|
|
254
|
+
that reaches it, including finished spans a bridge hands straight to
|
|
255
|
+
`processor.on_end` and the job's spans started before `eval_run`. Other
|
|
256
|
+
traces are dropped. A custom `only` picks whole traces the same way.
|
|
257
|
+
|
|
258
|
+
- **Order.** A span is kept when its trace is already marked as the span
|
|
259
|
+
ends. The first span started inside `eval_run` marks the trace as it
|
|
260
|
+
starts, so spans that end before it and spans bridged later are kept. A
|
|
261
|
+
span that ends before any span of its trace was marked is dropped; a
|
|
262
|
+
bridge that may hand spans over that early can copy the `evalkit.*`
|
|
263
|
+
attributes onto them so each marks its own trace.
|
|
264
|
+
- **Bridges.** Still copy `session.id` onto every converted span: the server
|
|
265
|
+
takes a trace's session from its root span when the root reaches it, and
|
|
266
|
+
from each span's own `session.id` otherwise.
|
|
267
|
+
- **Memory.** The processor remembers the 10,000 most recently used eval
|
|
268
|
+
traces and forgets the oldest.
|
|
269
|
+
- **Other processes.** Spans from another process in the same trace (an MCP
|
|
270
|
+
gateway pod, for example) never reach this processor; they go through that
|
|
271
|
+
process's own exporter. That process makes its own choice: continue the
|
|
272
|
+
trace, wrap its work in `eval_run` with the run's metadata sent along with
|
|
273
|
+
the request and filter with `only=tracing.is_eval_span`, or export
|
|
274
|
+
everything. Ask the developer which.
|
|
275
|
+
|
|
276
|
+
A worker in another language does the same with its own processor: forward
|
|
277
|
+
a span to the evalkit exporter only when its trace has a span carrying an
|
|
278
|
+
attribute the worker set on eval jobs.
|
|
279
|
+
|
|
280
|
+
## Capabilities of a code-driven agent
|
|
281
|
+
|
|
282
|
+
A code-driven agent has no capabilities endpoint, so evalkit records
|
|
283
|
+
`thinking: false` (and `artifacts`, `workspace` false) for it and never reads
|
|
284
|
+
capabilities from spans. When the agent's spans carry the model's reasoning,
|
|
285
|
+
set it on the agent:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
evalkit agents edit <agent> --provides thinking=true
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Declare only what works; evaluators gated on a flag trust it.
|
|
292
|
+
|
|
293
|
+
If the agent's spans cannot be expressed with the rule shapes in the schema
|
|
294
|
+
reference, open an evalkit issue rather than working around it.
|
|
295
|
+
|
|
296
|
+
For bugs, feature requests and feedback on evalkit, open an issue at https://github.com/inferedge-ai/evalkit/issues; questions go to https://github.com/inferedge-ai/evalkit/discussions.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1",
|
|
3
|
+
"kind": {
|
|
4
|
+
"attribute": "gen_ai.operation.name",
|
|
5
|
+
"values": {
|
|
6
|
+
"chat": "llm", "text_completion": "llm", "generate_content": "llm",
|
|
7
|
+
"embeddings": "other", "execute_tool": "tool", "invoke_agent": "agent",
|
|
8
|
+
"create_agent": "other"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"session_id": {"attribute": "gen_ai.conversation.id"},
|
|
12
|
+
"model": {"attribute": "gen_ai.request.model"},
|
|
13
|
+
"system_instructions": {"attribute": "gen_ai.system_instructions", "json": true},
|
|
14
|
+
"input_messages": {"attribute": "gen_ai.input.messages", "message_format": "gen_ai"},
|
|
15
|
+
"output_messages": {"attribute": "gen_ai.output.messages", "message_format": "gen_ai"},
|
|
16
|
+
"tokens": {
|
|
17
|
+
"prompt": {"attribute": "gen_ai.usage.input_tokens"},
|
|
18
|
+
"completion": {"attribute": "gen_ai.usage.output_tokens"},
|
|
19
|
+
"cached": {"attribute": "gen_ai.usage.cache_read.input_tokens"},
|
|
20
|
+
"cache_write": {"attribute": "gen_ai.usage.cache_creation.input_tokens"}
|
|
21
|
+
},
|
|
22
|
+
"cost_usd": null,
|
|
23
|
+
"tool": {
|
|
24
|
+
"name": {"attribute": "gen_ai.tool.name"},
|
|
25
|
+
"call_id": {"attribute": "gen_ai.tool.call.id"},
|
|
26
|
+
"arguments": {"attribute": "gen_ai.tool.call.arguments", "json": true},
|
|
27
|
+
"result": {"attribute": "gen_ai.tool.call.result"}
|
|
28
|
+
},
|
|
29
|
+
"agent_name": {"attribute": "gen_ai.agent.name"},
|
|
30
|
+
"input": {"attribute": "gen_ai.input.messages", "json": true},
|
|
31
|
+
"output": {"attribute": "gen_ai.output.messages", "json": true},
|
|
32
|
+
"known_attributes": [
|
|
33
|
+
"gen_ai.system", "gen_ai.provider.name", "gen_ai.agent.*", "gen_ai.main_agent.*",
|
|
34
|
+
"gen_ai.conversation.id", "gen_ai.conversation.compacted", "gen_ai.data_source.id",
|
|
35
|
+
"gen_ai.operation.name", "gen_ai.output.type", "gen_ai.prompt.*", "gen_ai.request.*",
|
|
36
|
+
"gen_ai.response.*", "gen_ai.skill.*", "gen_ai.system_instructions",
|
|
37
|
+
"gen_ai.token.modality", "gen_ai.tool.definitions", "gen_ai.tool.description",
|
|
38
|
+
"gen_ai.tool.type", "gen_ai.usage.reasoning.output_tokens", "gen_ai.usage.audio.*",
|
|
39
|
+
"gen_ai.usage.image.*", "gen_ai.usage.text.*", "gen_ai.workflow.name",
|
|
40
|
+
"server.address", "server.port", "error.type"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1",
|
|
3
|
+
"kind": {
|
|
4
|
+
"attribute": "openinference.span.kind",
|
|
5
|
+
"values": {"LLM": "llm", "TOOL": "tool", "AGENT": "agent", "CHAIN": "chain", "RETRIEVER": "retriever"}
|
|
6
|
+
},
|
|
7
|
+
"session_id": {"attribute": "session.id"},
|
|
8
|
+
"model": {"attribute": "llm.model_name"},
|
|
9
|
+
"input_messages": {"attribute": "llm.input_messages", "message_format": "openinference"},
|
|
10
|
+
"output_messages": {"attribute": "llm.output_messages", "message_format": "openinference"},
|
|
11
|
+
"tokens": {
|
|
12
|
+
"prompt": {"attribute": "llm.token_count.prompt"},
|
|
13
|
+
"completion": {"attribute": "llm.token_count.completion"},
|
|
14
|
+
"cached": {"attribute": "llm.token_count.prompt_details.cache_read"},
|
|
15
|
+
"cache_write": {"attribute": "llm.token_count.prompt_details.cache_write"}
|
|
16
|
+
},
|
|
17
|
+
"cost_usd": {"attribute": "llm.cost.total"},
|
|
18
|
+
"tool": {
|
|
19
|
+
"name": {"attribute": "tool.name"},
|
|
20
|
+
"call_id": {"attribute": "tool.id"},
|
|
21
|
+
"arguments": {"attribute": "input.value", "json": true},
|
|
22
|
+
"result": {"attribute": "output.value"}
|
|
23
|
+
},
|
|
24
|
+
"agent_name": {"attribute": "agent.name"},
|
|
25
|
+
"input": {"attribute": "input.value", "json": true},
|
|
26
|
+
"output": {"attribute": "output.value", "json": true},
|
|
27
|
+
"known_attributes": [
|
|
28
|
+
"openinference.span.kind", "session.id", "user.id", "metadata", "tag.tags",
|
|
29
|
+
"input.mime_type", "output.mime_type", "llm.provider", "llm.system",
|
|
30
|
+
"llm.invocation_parameters", "llm.finish_reason", "llm.tools.*",
|
|
31
|
+
"llm.token_count.total", "llm.token_count.prompt_details.*",
|
|
32
|
+
"llm.token_count.completion_details.*", "llm.cost.*", "tool.description",
|
|
33
|
+
"tool.parameters", "tool.json_schema", "agent.name", "graph.node.*"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Span mapping schema (version 1)
|
|
2
|
+
|
|
3
|
+
A mapping is one JSON document with one rule per ESF field. Every mapping is
|
|
4
|
+
complete on its own; there is no inheritance. The JSON Schema ships as
|
|
5
|
+
`span-mapping-v1.json` with `evalkit contracts export`.
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"schema_version": "1",
|
|
10
|
+
"kind": {"attribute": "...", "values": {"<raw>": "llm|tool|agent|chain|retriever|other"}},
|
|
11
|
+
"session_id": {"attribute": "..."},
|
|
12
|
+
"model": {"attribute": "..."},
|
|
13
|
+
"system_instructions": {"attribute": "...", "json": true},
|
|
14
|
+
"input_messages": {"attribute": "...", "message_format": "openinference|gen_ai|openai"},
|
|
15
|
+
"output_messages": {"attribute": "...", "message_format": "openinference|gen_ai|openai"},
|
|
16
|
+
"tokens": {
|
|
17
|
+
"prompt": {"attribute": "..."},
|
|
18
|
+
"completion": {"attribute": "..."},
|
|
19
|
+
"cached": {"attribute": "..."},
|
|
20
|
+
"cache_write": {"attribute": "..."}
|
|
21
|
+
},
|
|
22
|
+
"cost_usd": {"attribute": "..."},
|
|
23
|
+
"tool": {
|
|
24
|
+
"name": {"attribute": "..."},
|
|
25
|
+
"call_id": {"attribute": "..."},
|
|
26
|
+
"arguments": {"attribute": "...", "json": true},
|
|
27
|
+
"result": {"attribute": "..."}
|
|
28
|
+
},
|
|
29
|
+
"agent_name": {"attribute": "..."},
|
|
30
|
+
"input": {"attribute": "...", "json": true},
|
|
31
|
+
"output": {"attribute": "...", "json": true},
|
|
32
|
+
"known_attributes": ["...", "prefix.*"],
|
|
33
|
+
"answer": "root",
|
|
34
|
+
"exclude_spans": ["..."]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Two fields apply to the whole run, not to one span:
|
|
39
|
+
|
|
40
|
+
- `answer` (default `root`): where the run's answer comes from. `root`, a
|
|
41
|
+
span name, or `<span name>.<output key>`.
|
|
42
|
+
- `exclude_spans` (default empty): span names left out of the trajectory.
|
|
43
|
+
|
|
44
|
+
## Rule shapes
|
|
45
|
+
|
|
46
|
+
| Shape | What evalkit does |
|
|
47
|
+
| -- | -- |
|
|
48
|
+
| `{"attribute": K}` | reads attribute `K`; null when absent |
|
|
49
|
+
| `{"attribute": K, "json": true}` | reads `K` and parses it with `json.loads` when it is a string; a parse failure keeps the string |
|
|
50
|
+
| `{"attribute": K, "values": {...}}` | reads `K` and translates the value through the table; for `kind`, an unlisted value becomes `other` |
|
|
51
|
+
| `{"attribute": K, "message_format": F}` | collects the messages laid out per format `F` under `K` (see below) |
|
|
52
|
+
| `null` | the field is never read |
|
|
53
|
+
|
|
54
|
+
Which fields are read depends on the kind: `system_instructions`,
|
|
55
|
+
`input_messages`, `output_messages` and the token rules on `llm` spans; the `tool` rules on
|
|
56
|
+
`tool` spans, and `tool.call_id` on `agent` spans too (the call that started
|
|
57
|
+
a subagent); `agent_name` on `agent` spans (it names the subagent's
|
|
58
|
+
trajectory; the span name is used without it); `input` and `output` on everything that is not an llm span.
|
|
59
|
+
Attributes no rule read are reported as unmapped by `evalkit traces check`,
|
|
60
|
+
except those matching an entry of `known_attributes` (exact keys or glob
|
|
61
|
+
patterns such as `llm.tools.*`): list there the attributes you know about and
|
|
62
|
+
do not need.
|
|
63
|
+
|
|
64
|
+
`system_instructions` holds a system prompt kept outside the input messages,
|
|
65
|
+
as a string or a list of `{"type": "text", "content"}` parts; it becomes the
|
|
66
|
+
first input message, with role `system`. `tokens.cache_write` counts input
|
|
67
|
+
tokens written to the prompt cache; it lands in the step's
|
|
68
|
+
`metrics.extra.cache_creation_input_tokens`.
|
|
69
|
+
|
|
70
|
+
## Message formats
|
|
71
|
+
|
|
72
|
+
- `openinference`: flattened indexed keys under the attribute prefix `K`:
|
|
73
|
+
`K.{i}.message.role`, `K.{i}.message.content`,
|
|
74
|
+
`K.{i}.message.tool_calls.{j}.tool_call.id`,
|
|
75
|
+
`K.{i}.message.tool_calls.{j}.tool_call.function.name`,
|
|
76
|
+
`K.{i}.message.tool_calls.{j}.tool_call.function.arguments`,
|
|
77
|
+
`K.{i}.message.tool_call_id`, and content parts
|
|
78
|
+
`K.{i}.message.contents.{j}.message_content.type` / `.text`, where type
|
|
79
|
+
`text` is message text (when `message.content` is absent) and type
|
|
80
|
+
`reasoning` is the model's reasoning.
|
|
81
|
+
- `gen_ai`: attribute `K` holds a JSON string: a list of messages with `role`
|
|
82
|
+
and `parts`, each part typed `text` (`content`), `reasoning` (`content`),
|
|
83
|
+
`tool_call` (`id`, `name`, `arguments`) or `tool_call_response` (`id`,
|
|
84
|
+
`response`, or `result` when `response` is absent).
|
|
85
|
+
- `openai`: attribute `K` holds a JSON string: a list of OpenAI chat messages
|
|
86
|
+
with `role`, `content` (a string or a list of `{"type": "text", "text"}`
|
|
87
|
+
parts), `tool_calls` (`id`, `function.name`, `function.arguments` as a JSON
|
|
88
|
+
string) and `tool_call_id`.
|