diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 487870cd52..f9ffdc4e6b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,7 +16,6 @@ inferencex-e2e/configs/nvidia-master.yaml @ankur-singh @kedarpotdar-nv @wzhao18 # PoR for Models & general direction inferencex-e2e/docs/MODELS.md @ankur-singh @chunfangamd @SemiAnalysisAI/core -inferencex-e2e/docs/MODELS_zh.md @ankur-singh @chunfangamd @SemiAnalysisAI/core # CollectiveX collectivex/ @Oseltamivir @functionstackx diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index d0667bf866..c36885c07f 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -573,4 +573,4 @@ jobs: - Reject new active entries for retired models, scenarios, or precisions unless `inferencex-e2e/docs/MODELS.md` explicitly documents an exception. - Preserve the conditional non-speculative AgentX policy; do not infer retirement from the existence of a speculative counterpart. - Retired entries are deleted from the master configs, not archived, following `AGENTS.md`; git history and `inferencex-e2e/perf-changelog.yaml` are the historical record. - - For a newly supported model, require matching updates to `inferencex-e2e/docs/MODELS.md` and `inferencex-e2e/docs/MODELS_zh.md` rather than rejecting it against an obsolete model list. + - For a newly supported model, require an update to `inferencex-e2e/docs/MODELS.md` rather than rejecting it against an obsolete model list. Only READMEs retain Chinese translations; do not require or recreate Chinese versions of other docs. diff --git a/AGENTS.md b/AGENTS.md index 3088bd1060..5b8dac415e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,10 +2,12 @@ Guidance for AI agents working with InferenceX. +> PR titles MUST MUST MUST HAVE CHINESE + ## Start here 1. **Start every task with [`inferencex-e2e/docs/index.md`](inferencex-e2e/docs/index.md).** Choose the one focused guide that matches the task. Do not load every documentation page. -2. Repository source, schemas, workflows, launchers, and collectors are authoritative. If documentation disagrees with implementation, follow the implementation and update the nearest English guide plus its Chinese counterpart. +2. Repository source, schemas, workflows, launchers, and collectors are authoritative. If documentation disagrees with implementation, follow the implementation and update the nearest English guide. Keep Chinese translations only for READMEs. 3. Read [`CONTRIBUTING.md`](CONTRIBUTING.md) before opening or reviewing a PR or changing review, sweep, or merge policy. Sweep labels and modifiers: see [PR primary and modifier labels](inferencex-e2e/docs/ci-procedures.md#pr-primary-and-modifier-labels). 4. Before debugging a Klaud-Cold or `claude/*` image-bump PR, read [`inferencex-e2e/docs/klaud.md`](inferencex-e2e/docs/klaud.md) and the [known failure signatures](inferencex-e2e/docs/troubleshooting.md#known-failure-signatures). @@ -21,7 +23,7 @@ The end-to-end Python project owns `inferencex-e2e/pyproject.toml`, `inferencex- - PR and issue descriptions and human-authored PR comments must include English and natural Simplified Chinese. In bodies and comments, keep English visible and put Chinese in one collapsed `
中文` section. Keep code, commands, logs, stack traces, model names, hardware SKUs, framework names, flags, and identifiers unchanged. The exact CODEOWNER sign-off template is English-only. See [`.github/AGENT_OPERATIONS.md`](.github/AGENT_OPERATIONS.md#translation-terminology). - **One reviewer checklist per PR:** Only one eligible CODEOWNER reviewer needs to post the completed PR Review Checklist. Check for an existing checklist before posting; other reviewers do not need to duplicate it. The original reviewer must edit their existing checklist comment when correcting items or adding evidence, rather than post a new checklist. Create a replacement only if the original was deleted. See [`CONTRIBUTING.md`](CONTRIBUTING.md#the-pr-review-checklist-codeowner-sign-off). - **Klaud Cold reports:** Follow the compact body/comment templates in [`inferencex-e2e/docs/klaud-reporting.md`](inferencex-e2e/docs/klaud-reporting.md), including cleanup and completion reports. -- Commit subjects use conventional English style, while commit bodies include the Chinese translation. Contributor-facing docs use English as the source version and ship with a synchronized `_zh.md` page and language switcher. +- Commit subjects use conventional English style, while commit bodies include the Chinese translation. Contributor-facing docs are English-only except READMEs. Keep existing `README_zh.md` translations synchronized with their English READMEs and preserve their language switchers; do not add or recreate Chinese translations of other docs. - Python under `inferencex-e2e/infx/` uses all stable Ruff rules with reviewed exclusions in `inferencex-e2e/infx/ruff.toml`, line length 100, and the Ruff formatter. The Lint job in `.github/workflows/ci.yml` runs whenever Python files change and fails on any finding. Before pushing Python changes, run the [commands in the testing guide](inferencex-e2e/docs/testing.md#python-lint-and-formatting). Fix findings where practical; justified exceptions use inline `# noqa: CODE` rather than file-wide ignores. - Follow the nearest existing pattern. Python uses typed signatures and strict Pydantic schemas. YAML uses kebab-case fields. Shared benchmark behavior that runs inside serving containers belongs in `inferencex-e2e/infx/bench/` as stdlib-only, Python 3.10 compatible commands (`python3 -m infx.bench `), with parameters passed through environment variables or flags. Bash entrypoints stay thin shims. @@ -57,7 +59,7 @@ check_env_vars IS_MULTINODE MODEL_NAME PRECISION ## Deprecating benchmark configs - Delete retired entries from the active master config; do not archive them. Git history and `inferencex-e2e/perf-changelog.yaml` are the record of past settings. For a partial deprecation, remove only the retired scenarios and retain the supported scenarios in the active entry. -- Check retirement statements in [`inferencex-e2e/docs/MODELS.md`](inferencex-e2e/docs/MODELS.md) against active configs and script routing in the same PR, and update `inferencex-e2e/docs/MODELS.md` plus `inferencex-e2e/docs/MODELS_zh.md` together. Preserve explicitly documented exceptions and conditional retirement policies; do not treat planned retirement as completed. +- Check retirement statements in [`inferencex-e2e/docs/MODELS.md`](inferencex-e2e/docs/MODELS.md) against active configs and script routing in the same PR, and update that guide. Preserve explicitly documented exceptions and conditional retirement policies; do not treat planned retirement as completed. - Remove unused retired-model rows from the launch workload tables (shared ones in `inferencex-e2e/infx/launch/policy.py`, srt-slurm ones in `inferencex-e2e/infx/launch/drivers/srt/{lanes,models,power}.py`) and cluster `models.entries`, and update workflow/agent guidance that still recommends retired coverage. Audit callers before removing shared helpers; retained SPEED-Bench collectors and historical result readers may still need model-specific support. - Delete recipes, setup scripts and other assets that no active config uses any more rather than moving them to a `deprecated/` directory. @@ -107,7 +109,7 @@ Deleting a test that fails these questions needs no replacement. Do not preserve - Every priority-scheduled benchmark job on a self-hosted cluster must request exactly one `nodes:N` label, where `N` is the positive integer number of physical Slurm nodes required. Single-node jobs use `nodes:1`; generated multi-node jobs must forward their computed `node-count`. A queued job missing this label is ineligible for priority scheduling, and labels cannot be added retroactively, so fix the source branch and dispatch a new run. - Every change that can affect benchmark performance and every recipe addition or modification requires a new `inferencex-e2e/perf-changelog.yaml` entry. The file is append-only and byte-sensitive. Preserve all existing bytes and separator whitespace, and append only at the tail. - One PR maps to one `inferencex-e2e/perf-changelog.yaml` block. By convention, a PR with a perf changelog entry is a change that affects inference performance or otherwise requires a rerun to collect up-to-date results. That block may list one or more `config-keys` to run, but do not add a second block for the same PR, even when the change evolved across commits. Revise the PR's existing block so it describes the final state of the change. -- New `inferencex-e2e/perf-changelog.yaml` entries must be English-only. Do not add Chinese translations or bilingual descriptions; the bilingual documentation and GitHub-content rules do not apply to these entries. Leave historical entries unchanged. +- New `inferencex-e2e/perf-changelog.yaml` entries must be English-only. Do not add Chinese translations or bilingual descriptions; the bilingual README and GitHub-content rules do not apply to these entries. Leave historical entries unchanged. - Multi-node srt-slurm changes update the recipe YAML and matching master config together. For image bumps, `model.container` must equal `image`. - Every speculative fixed-sequence benchmark renders prompts with the chat template: single-node srt-slurm recipes that speculate set `benchmark.env.USE_CHAT_TEMPLATE: "true"` (enforced by `inferencex-e2e/infx/srt_slurm/single_node.py::validate_recipe`), which `python3 -m infx.bench fixed-seq` (run by `srt_fixed_sequence.sh`) turns into `--use-chat-template` for the benchmark client. - Benchmarks create no new directories under `/workspace`. Root containers must not leave root-owned files in shared AMD runner workspaces. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 12637ef520..e0a5857ba5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ # Contributing to InferenceX -
+Thanks for contributing! PRs are welcome. This page covers the review process every PR goes through before it can be merged. -**English** | [中文](CONTRIBUTING_zh.md) +## Documentation language -
+Maintain contributor-facing docs in English. Only READMEs retain Chinese translations: keep existing `README_zh.md` files synchronized with their English READMEs and preserve their language switchers. Do not add or recreate Chinese versions of other docs. -Thanks for contributing! PRs are welcome. This page covers the review process every PR goes through before it can be merged. +PR titles must still include both English and Simplified Chinese, using ` / <中文标题>`. The existing bilingual requirements for issue titles, PR and issue descriptions, human-authored PR comments, and commit bodies remain unchanged; see [AGENTS.md](AGENTS.md). ## PR descriptions diff --git a/CONTRIBUTING_zh.md b/CONTRIBUTING_zh.md deleted file mode 100644 index 0647258dd6..0000000000 --- a/CONTRIBUTING_zh.md +++ /dev/null @@ -1,139 +0,0 @@ -# 为 InferenceX 做贡献 - -
- -[English](CONTRIBUTING.md) | **中文** - -
- -感谢你的贡献!我们欢迎 PR。本页介绍每个 PR 在合并前需要经过的审阅流程。 - -## PR 描述 - -开头用简短说明交代问题、变更后的行为及其意义。审阅者应当无需展开任何部分,就能理解 PR 的整体作用。重要风险、破坏性变更和尚未解决的失败应与摘要一同保持可见。仅在相关时附上 issue 链接。 - -将 AI 模型使用说明、变更类型、作者检查清单及其他流程性内容放在摘要之后,使用标题清晰的 `
…` 折叠块。不添加 `open` 属性,使其默认折叠,并在块内的 Markdown 前后保留空行。保留所有必需的检查项;折叠只改变展示方式,不改变审阅或合并要求。 - -验证说明只报告实际执行的集成测试或端到端运行:简述结果,并在有运行链接时附上。支持性验证证据、冗长的检查输出和日志放入默认折叠的 `Validation details` 块,重要失败和性能回退则保持可见。用于解释变更的实质性基准测试对比(包括专用的 Klaud 报告)保持可见;这些内容不属于流程性套话。省略例行本地检查清单(单元测试数量、mock 检查、lint/格式检查、schema 检查、矩阵生成及变更日志字节检查)、空章节和等待验证的套话。仍须执行适当的检查;此规则仅约束 PR 描述和评论中的报告内容。未执行集成测试或端到端运行时,省略验证章节。 - -每个 PR 描述都必须在默认折叠的 `
AI model disclosure` 块内包含 **AI model disclosure(AI 模型使用说明)** 部分,列出准备该 PR 时实际使用的完整模型名称/版本及各自的工作内容,包括委派给其他 agent 的工作。不能只写 Claude Code、Cursor 或 Perplexity Computer 等工具名。模型标识应以运行环境提供的信息为准,不得猜测;如果运行环境未提供确切模型,须明确说明无法确认。完全未使用 AI 的 PR 须填写 `No AI used`。后续修改使用其他模型时,须同步更新说明。 - -## PR 审阅流程 - -1. 打开你的 PR 并通过 PR 验证。只有修改了 `inferencex-e2e/perf-changelog.yaml`(矩阵来自新追加的条目)且恰好带有一个主标签(通常为 `full-sweep-fail-fast`)的同仓库 PR 才会运行 `run-sweep.yml` sweep。标签、修饰标签、canary、fail-fast 以及由维护者批准的 fork 路径详见 [PR 主标签与修饰标签](inferencex-e2e/docs/ci-procedures_zh.md#pr-主标签与修饰标签)。让基准测试 sweep 运行,并在 PR 的某个 commit 上获得全绿的完整 sweep,包括 evals。 - - **Fork PR:** 外部贡献者无法自行添加标签。PR 处于打开、非草稿且无合并冲突的状态后,由维护者添加标签,这只会批准当前的 head SHA。每次推送后,维护者都必须移除并重新添加主标签。 -2. 若修改的文件归属于仓库管理员及 `@SemiAnalysisAI/core` 之外的 CODEOWNER,请联系一位有资格的 [CODEOWNER](.github/CODEOWNERS) 审阅,并在批准评论中填写 **PR Review Checklist** 签署(见下文)。 -3. 在 Slack 上联系核心维护者进行最终批准;若要求清单签署,请先完成签署。 -4. 由授权维护者发布 `/use `(见下文),然后通过 reuse 路径合并 PR。 - -**性能变更日志要求:** 凡是可能影响基准测试性能的变更,以及任何配方(recipe)的新增或修改,都**必须**在 `inferencex-e2e/perf-changelog.yaml` 文件的物理末尾追加一个新条目。历史条目**严禁**编辑。 - -## Draft 模型精度 - -规则很简单:**按发布时的默认方式运行 draft。** 投机解码提交必须使用随所服务 checkpoint 一同发布的 draft head 或 draft 模型,保持其发布时的精度,并采用锁定上游框架对该 checkpoint 的默认加载处理。此规则适用于内嵌的 MTP/NextN/EAGLE draft head 及独立 draft 模型(包括 DSpark),覆盖所有硬件厂商和框架。 - -"按发布时的默认方式"既不是指 BF16,也不是指"未量化的原始发布版本"。它指的是默认值:checkpoint 作者为该 checkpoint 发布的内容,以及锁定上游镜像开箱即用时对它的处理方式。基线是:同一 checkpoint 由同一锁定镜像加载,且不带任何来自提交方的 draft 相关设置。提交的 draft 实际运行精度与该基线一致即为合规;使 draft 比该基线更"便宜"即为违规。 - -允许(这是基线本身,不是例外): - -- 内嵌于所服务 checkpoint 或随其一同发布的 draft head / draft 权重,保持其存储精度。若所服务的 FP8 checkpoint 内嵌 FP8 MTP head,则 FP8 head 就是正确的 draft。示例:Qwen FP8 checkpoint 以 FP8 存储其 MTP 权重,因此内嵌的 FP8 head 是合规的;换用 BF16 发布版本的 head,或强制添加 unquantized-draft 覆盖设置,才是违规,而不是"修复"。 -- 锁定上游框架对该 checkpoint 默认执行的加载时处理,包括 dtype 转换。示例:锁定的 SGLang 镜像将 DeepSeek V4.1 DSpark 以 FP8 存储的 `wo_a` 投影加载为 BF16,与 DeepSeek 参考实现一致。该转换就是发布路径;用本地补丁将其保持为 FP8 会改变 draft 计算,属于违规。 -- 框架对该 checkpoint 的默认 draft KV cache dtype,以及对 target 和 draft 一致应用的上游支持的 KV cache dtype(例如从 FP8 target 继承的 FP8 draft KV)。 -- 锁定镜像中自带、且被在意准确性的客户在生产中实际使用的真实上游优化:上游为该模型默认启用的融合或低精度 kernel、调度优化,以及任何在不降低 draft 权重或激活精度的前提下让同样的 draft 计算跑得更快的手段。 - -禁止(提交方对 draft 精度的 hack): - -- 今后明确禁止启用 `SGLANG_NVFP4_CKPT_FP8_NEXTN_MOE`(`=1` 或锁定实现认可的其他启用值),包括从环境、launcher、容器或镜像默认值继承的启用设置。上述基线允许项不能豁免此 flag。审阅者必须核实它在实际配方中已禁用;只有锁定实现确认未启用时,未设置或 `=0` 才可接受。历史运行不能作为当前待审提交的先例或例外,此要求也适用于仅更新镜像或重新启用配方的提交。本规则不追溯否定生效前的运行。 -- 通过 flag、环境变量、配置文件或转换步骤,将 draft 权重、激活或计算量化到发布精度以下,无论在线还是离线。包括对 BF16 MTP head 使用 `--speculative-draft-model-quantization quark_mxfp4`、`SGLANG_GLM_NEXTN_MOE_PTPC=1`,以及 `exclude_layer` 模式未覆盖整个 draft head 的 ATOM `--online_quant_config`。 -- 针对 draft 的 dtype 或 KV cache dtype 覆盖设置,使其精度低于框架对该 checkpoint 的默认值。 -- 替换为经过精度转换或不同量化方式的 draft checkpoint,或使用与所服务 target 不同发布版本的 draft head。 -- 给锁定镜像打补丁,使其以不同于默认的精度加载或计算 draft,无论升高还是降低。引擎补丁规则本已禁止此行为;waiver 不能豁免 draft 精度要求。 -- 以 checkpoint 作者未发布的方式减少 draft FLOPs,例如裁剪 draft 层或 expert。 - -Target/verifier 模型仍可在满足现有 eval 要求的前提下量化。只要 target 的量化不会同时把 draft 量化到发布精度以下即可;请核查继承的量化设置和 `exclude_layer` 覆盖范围,而不是假定。 - -匹配上游配方、通过 evals、声称接受长度(AL)未变,或重新测得的 AL 曲线,都不能豁免降低 draft 精度的提交。AgentX 的合成接受在任何方向上都不构成证据。draft 精度的改变会把准确性损失转移到接受率上,而 target 模型的 evals 无法测量这一点。 - -审阅者必须对照发布基线核实 draft 的实际运行精度,不能只看启动参数。检查 checkpoint 元数据与量化排除项、环境变量、锁定镜像中的框架默认行为,以及从 target 模型继承的量化设置。不得仅凭 target checkpoint 的名称或精度标签推断 draft 精度。 - -涉及投机解码的改动,CODEOWNER 必须在 Additional detail section 中注明 draft checkpoint 及其 revision(或内嵌 head)、其发布精度、锁定上游镜像对其的默认处理方式,以及实际运行精度,以便审阅者确认后两者一致。无法核实时,该条目不满足要求。参见[审阅清单](inferencex-e2e/docs/PR_REVIEW_CHECKLIST_zh.md)及[验证器检查 13](.github/codeowner-signoff-verify-prompt.md#check-13--draft-runs-as-shipped)。 - -此要求与 [MLPerf Inference Rules 附录 C:Speculative Decoding](https://github.com/mlcommons/inference_policies/blob/ff7edba545fded369e7e7e3d5a2f0bab4a95eece/inference_rules.adoc#appendix-c-speculative-decoding) 的原则一致:参考 MTP head 使用提供时的相同精度("at the same precision as provided"),并禁止参考 head 权重量化及其他人为操纵接受率的行为。InferenceX 不采用该版本针对特定量化边缘工作负载的例外、其允许模型列表,或其投机解码配置与接受率测试方法。 - -## PR Review Checklist(CODEOWNER 签署) - -CODEOWNER 自动验证目前仅供审阅参考。工作流会核验新提交及已编辑的清单,并为每个签署资源关联一条裁定评论,不再发布提交状态。GitHub 单独设置的 Core 团队和 CODEOWNER 批准要求仍然有效,除非有权限的维护者使用绕过权限。 - -仅当修改的文件存在仓库管理员及 `@SemiAnalysisAI/core` 之外的 CODEOWNER 时,才要求签核。归属以 PR 目标分支当前最新提交中的 CODEOWNERS 为准:先解析该分支的 SHA,再使用同一 SHA 校验并读取 CODEOWNERS,最后匹配的规则生效;重命名同时检查旧路径和新路径。归属规则不从 PR 的 Head 或其记录中可能过期的基础提交读取。同一文件有 core 团队作为 owner,不会豁免其他 owner。个人管理员必须同时拥有仓库 `permission: admin` 和 `role_name: admin`;其他团队和邮箱 owner 均要求签核。归属信息缺失或权限查询失败不能授予豁免。不涉及此类 owner 的改动会跳过验证。 - -由一名符合条件的 CODEOWNER 审阅者在批准评论中填写最新的 [PR_REVIEW_CHECKLIST.md](inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md)([中文说明](inferencex-e2e/docs/PR_REVIEW_CHECKLIST_zh.md))模板。 - -**每个 PR 只需一名符合条件的 CODEOWNER 审阅者发布清单。** 发布前先检查是否已有清单;其他审阅者无需重复发布。需要更正条目或补充证据时,原审阅者必须**编辑自己已有的清单评论**,不要另发一条。只有原评论被删除时才创建替代评论。 - -友情提醒。请**正确**遵循最新的清单模板: - -- 务必从 `main` 分支上**当前**的 [inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md](inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md) 复制模板。清单会不断演进,使用过期副本的签署会被标记为缺项。 -- 保持模板的开头语句原样不变(必须保留英文原文): - - > As a PR reviewer and CODEOWNER, I have reviewed this and have: - - 我们的 CI 验证工作流 [`codeowner-signoff-verify.yml`](https://github.com/SemiAnalysisAI/InferenceX/blob/main/.github/workflows/codeowner-signoff-verify.yml) 正是通过这句话触发的。**如果批准评论缺少这句话,工作流就不会核验该清单。** -- 签署可以以普通会话评论、review 总结或行内 review 评论的形式发布。这三种方式都会触发验证。 -- 请在 PR 处于打开且非草稿状态时提交新清单。编辑该清单会再次触发验证;推送、重新打开或退出草稿状态不会触发验证。如果合并冲突期间遗漏了 Review 事件,请在解决冲突后手动分发工作流来重试。 -- 启动 Claude 要求触发者为具有合格仓库写权限的人类用户。 -- 请在 "Additional detail section" 中填写清单要求的链接(验证/评测工作流运行、对应的 [vLLM recipe](https://github.com/vllm-project/recipes) / [SGLang cookbook](https://github.com/sgl-project/sglang/tree/main/docs/cookbook) PR,以及任何例外理由)。新的 SGLang cookbook PR 应提交到 `sgl-project/sglang` 的 `docs/cookbook/` 下,该目录是已发布网站的来源。`sgl-project/sgl-docs` 中的 cookbook 副本并非当前部署来源;`sgl-project/sgl-cookbook` 已归档。 - -签署发布后,CI 会独立复核审阅清单中的各项声明,包括 CODEOWNER 身份、PR 内 commit 上的全绿 sweep 与 evals、所链接的 recipe、复用命令、是否使用最新清单模板、上游 [vLLM](https://hub.docker.com/u/vllm)/[SGLang](https://hub.docker.com/u/lmsysorg) 镜像、没有更改模型架构的基准测试 hack、投机解码是否使用 chat template,以及 draft 模型和 draft head 的权重与精度是否保持不变。CI 会为该签署资源创建一条裁定评论,并注明实际评估的 SHA。编辑同一清单时只更新与其关联的裁定。替代清单或新增清单会获得独立裁定;与旧签署关联的裁定保持不变。未通过的条目直接显示;已通过和不适用(N/A)的条目统一放入折叠区域。勾选项不会被无条件信任,请只勾选你确实核实过的条目。 - -裁定只记录实际评估的提交,不会将批准延续到后续提交。需要重新评估时,先按需更正已有清单,再由有权限的协作者传入 `pr-number` 及其 `comment_url`(两者必须指向同一 PR)手动分发 `codeowner-signoff-verify.yml`。手动重新评估会更新与该签署资源关联的裁定。 - -## 使用 `/use` 在合并时复用 PR 的全绿 sweep - -完整基准测试 sweep 花费昂贵的 GPU 时间,且 runner 由所有打开的 PR 共享,因此一个已批准 PR 的 sweep 只会为 PR 验证运行一次。合并后 `main` 不会重新运行它,而是通过 reuse 路径发布该 PR sweep: - -- 当你的 PR 拥有符合条件的全绿完整 sweep 后,授权维护者(`OWNER`/`MEMBER`/`COLLABORATOR`)在 PR 上评论 `/use ` 来指定该 Run。命令和 Run ID 必须放在同一行。 -- `/reuse-sweep-run ` 仍受支持,行为完全相同。不带 ID 的 `/reuse-sweep-run` 会自动选择源 Run;不带 ID 的 `/use` 会被拒绝。 -- 合并到 `main` 的运行随后会验证并摄取该 PR sweep 的产物;`main` 本身不会再重新运行 sweep。 -- **复用是必需的。** 仅有全绿 sweep 还不够。复用命令必须在评论记录中(签署验证会检查这一点),否则 `main` 上的运行会失败,该 PR 的结果也不会被摄取。 -- 复用不要求保留主标签,但 PR 带有 `evals-only` 或 `agentx-fast` 时复用会被拒绝;PR 带有多个主标签时,`merge_with_reuse` 会拒绝合并。机器人会在命令被接受时添加 👍,拒绝时添加 👎,详情见 Actions 运行摘要;合并时仍会重新验证源产物。 -- 缺少授权维护者发布的复用命令时,Check 4 会给出 **WARN**,不会因此拒绝签署。警告会在签署裁定中保持展开;要实际复用产物,仍需先发布有效的授权命令。 -- 在仓库根目录运行 `uv run --project inferencex-e2e --extra workflows python -m infx.workflows.merge_with_reuse ` 是受支持的合并路径。它会发布命令、将分支与 `main` 同步、等待检查并 squash 合并。资格详情见 [workflows README](.github/workflows/README.md#reusing-an-approved-pr-full-sweep)。 - -## 使用 `append-only` 向最新曲线追加数据点 - -当 PR 只向现有曲线添加生成的数据点时,请为每个新的变更日志条目标记 `append-only: true`。新增内容可以引入新的并发值或新的配方变体,例如另一个张量并行度取值。Sweep setup 会比较 base 和 head 修订版本生成的矩阵,只运行新增的数据点,并输出元数据,让 InferenceX-app 扩展最近一条匹配的曲线,而不是把这次部分运行显示为一条单独的曲线。 - -此模式刻意限定在很窄的范围内,但并不依赖文件允许列表。只要改动的行为影响仅限于变更日志所列的新增数据点,支撑代码、基准测试脚本、launcher 和其他文件都可以修改。任何被修改的基准测试路径都不得在已有数据点上执行,也不得改变已有数据点。所选的每个配置和场景都必须已经存在,base 修订版本生成的每个数据点都必须以相同配方保留。在此范围内,head 可以包含任意新增的生成配方或数据点,包括新的拓扑或其他配方维度;sweep 会调度两次生成结果的差集。新增内容必须使用相同的非空镜像,并属于仪表盘中已有的可视化序列。每个生成的配方都带有确定性指纹,因此同一并发下的两个不同配方在数据库中仍是两个不同的数据点,而不会拆分可视化曲线。删除或修改已有数据点,或改动可能影响已有数据点的共享逻辑,都会被拒绝。Append-only 条目不能设置 `all-evals`、`evals-only` 或 `eval-min-prefill-ep` 条目字段,不能与常规条目共用一个 sweep,也不能与 `all-evals`/`evals-only` 修饰标签一起运行。矩阵验证器会强制执行"生成矩阵只能新增、不得删改"这一不变量;人工和 AI 审阅者必须检查完整 diff,并核实行为隔离。机械比对会使用每个配置修订版本自身的生成器、验证代码和 runner 元数据来渲染该版本。Launcher 和基准测试脚本的改动仍依赖完整 diff 审阅,因为仅凭矩阵一致无法证明其运行时控制流已被隔离。 - -```yaml -- config-keys: - - dsv4-fp4-b300-vllm-mtp - description: - - "Add TP8 at concurrency 12 and 16 to the existing curve" - pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/XXX - append-only: true -``` - -## AMD 集群:严禁在 runner 工作区留下 root 所属文件 - -AMD MI355X TW 集群上的多节点基准测试通过 Slurm 提交容器化任务,这些容器通常以 **root** 身份运行。如果容器将文件(通常是 `benchmark_logs/logs/slurm_job-*`)写入 GitHub Actions runner 工作区,而任务在 teardown 执行前被**取消**,root 所属目录就会被遗留。runner 用户无法删除这些文件,导致 `actions/checkout` 失败: - -``` -Error: File was unable to be removed -Error: EACCES: permission denied, rmdir '.../benchmark_logs/logs/slurm_job-' -``` - -**这会阻塞该 runner 上的所有后续任务**,直到拥有 `sudo` 权限的人在共享 `/it-share` 存储上手动删除这些文件。由于所有 AMD MI355X 扫描共享同一个 runner 池,一个遗留的 root 所属目录就会阻塞整个队列,影响所有人。 - -**基准测试脚本和 Slurm 容器规则:** - -1. **严禁以 root 身份写入 runner 工作区。** 如果容器必须以 root 运行,请将输出写入 `_work/` 之外的临时目录(例如 `/tmp` 或专用暂存路径)。 -2. **如果 root 写入不可避免**,请添加清理 trap 或 teardown 步骤,在任务退出前(包括取消时,使用 `trap cleanup EXIT`)`chown` 或 `rm` 工作区下所有 root 所属文件。 -3. **测试你的 teardown 路径。** 在运行中途取消基准测试,验证工作区中不会残留 root 所属文件。 - -如果发现遗留的 root 所属文件阻塞了 runner,恢复流程参见 [`.claude/commands/clean-amd-mi355-runner-root-files.md`](.claude/commands/clean-amd-mi355-runner-root-files.md):SSH 到中转主机,使用 `sudo` 扫描 `_work` 目录并删除问题文件。 - -## 合并之后 - -**PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。** 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。[参见 GitHub 关于重新运行失败任务的文档](https://docs.github.com/en/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs#re-running-failed-jobs-in-a-workflow)。 diff --git a/README_zh.md b/README_zh.md index 25c1d41be8..baa349e296 100644 --- a/README_zh.md +++ b/README_zh.md @@ -89,11 +89,11 @@ SGLang、vLLM、TensorRT-LLM、CUDA、ROCm 等 AI 软件通过核函式優化、 ## 参与贡献 -欢迎提交 PR!有关 PR 审阅流程、[PR 审阅清单](inferencex-e2e/docs/PR_REVIEW_CHECKLIST_zh.md)与合并流程的更多详情,请参阅 [CONTRIBUTING_zh.md](CONTRIBUTING_zh.md)。 -维护者与 Agent 的文档导航请从 [`docs/index_zh.md`](inferencex-e2e/docs/index_zh.md) 开始,其中集中链接架构、配置、Workflow、评估、Runner 与故障排查参考。 +欢迎提交 PR!有关 PR 审阅流程、[PR 审阅清单](inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md)与合并流程的更多详情,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。 +维护者与 Agent 的文档导航请从 [`docs/index.md`](inferencex-e2e/docs/index.md) 开始,其中集中链接架构、配置、Workflow、评估、Runner 与故障排查参考。 无需 CI 或 Slurm 即可对已有服务进行基准测试,请参阅 -[独立运行 AgentX-Harness](inferencex-e2e/docs/agentx-standalone_zh.md), +[独立运行 AgentX-Harness](inferencex-e2e/docs/agentx-standalone.md), 其中包含客户端安装步骤和直接执行的 `aiperf profile` 命令。 ## 致谢与支持者 diff --git a/collectivex/README.md b/collectivex/README.md index 8d9182787e..0579bd0e5e 100644 --- a/collectivex/README.md +++ b/collectivex/README.md @@ -4,8 +4,8 @@ CollectiveX is an experimental MoE expert-parallel communication benchmark. It m combine, and paired roundtrip latency across EP libraries and accelerator systems, then uploads neutral result artifacts. -A second suite, the [vLLM `swap_blocks` benchmark](docs/swap-blocks.md) -([中文](docs/swap-blocks_zh.md)), measures pinned CPU↔GPU and same-GPU block copies, +A second suite, the [vLLM `swap_blocks` benchmark](docs/swap-blocks.md), +measures pinned CPU↔GPU and same-GPU block copies, with its own correctness checks and latency/bandwidth JSON output. It runs through the same sweep matrix and pool launchers (`suites: swap-blocks`). diff --git a/collectivex/docs/swap-blocks.md b/collectivex/docs/swap-blocks.md index c3097b721c..1ee1c73a52 100644 --- a/collectivex/docs/swap-blocks.md +++ b/collectivex/docs/swap-blocks.md @@ -1,7 +1,5 @@ # vLLM block-copy benchmark -**English** | [中文](swap-blocks_zh.md) - `bench/run_swap_blocks.py` measures `from vllm._custom_ops import swap_blocks` on one CUDA or ROCm GPU using an installed, compatible vLLM build. Run it directly with Python inside that environment, or dispatch the suite through the GitHub Action below. diff --git a/collectivex/docs/swap-blocks_zh.md b/collectivex/docs/swap-blocks_zh.md deleted file mode 100644 index 28e0e1819c..0000000000 --- a/collectivex/docs/swap-blocks_zh.md +++ /dev/null @@ -1,86 +0,0 @@ -# vLLM 块复制基准测试 - -[English](swap-blocks.md) | **中文** - -`bench/run_swap_blocks.py` 在单个 CUDA 或 ROCm GPU 上测量 -`from vllm._custom_ops import swap_blocks`,需要安装兼容的 vLLM。 -可在该环境中直接使用 Python,或通过下方的 GitHub Action 触发该套件。 -无需 `torchrun`,也不会执行 EP 工作负载。 -结果记录已安装的 vLLM 版本,同时支持旧版三参数接口和显式传入 -`block_size_in_bytes` 的接口。 - -```bash -python3 collectivex/bench/run_swap_blocks.py \ - --directions h2d d2h d2d --block-bytes 4096 65536 1048576 \ - --num-blocks 1 16 256 --layout random --seed 0 \ - --device 0 --warmup 32 --iterations 100 --output /tmp/swap-blocks.json -``` - -`h2d` 和 `d2h` 使用锁页主机内存;`d2d` 使用同一 GPU 上的独立缓冲区。 -CPU int64 映射将每个选定源块复制一次,目标位置为连续布局或由固定种子生成的 -随机排列。缓冲区使用 uint8,块大小以字节精确指定。额外的两个块保持不变。 -测量前后逐位检查目标数据、未复制的块和源数据。失败时以非零状态退出, -不写入新的结果文件。 - -每个样本在 GPU 完全同步后,用主机单调时钟测量一次调用,包含 Python/C++ -提交开销和最终设备同步。内存分配、映射构建、初始化、正确性检查及预热均不计入。 -因此结果表示包含主机开销的独立复制端到端延迟,而非纯 DMA 时间或与推理重叠时的 -吞吐量。重复调用复用同一组缓冲区和映射,不属于冷缓存测量。 - -独立的 `collectivex-swap-blocks-v1` JSON schema 包含原始样本、以微秒表示的 -nearest-rank p50/p90/p95/p99 延迟,以及各延迟分位数对应的有效载荷 GB/s -(`num_blocks * block_bytes / elapsed_seconds / 1e9`)。复制字节仅计算一次, -不累计读写流量。记录还包含方向、布局、种子、API 类型、设备和运行时版本。 -EP 汇总与带宽工具不读取该 schema。输出目录必须已存在;基准测试不创建目录。 -较大的测试点需要为传输缓冲区和 CPU 正确性参考数据预留内存。 -可选参数 `--max-payload-bytes` 在分配内存之前排除 `block_bytes * num_blocks` -超过上限的组合;没有可执行测试点时直接失败。JSON 的 `selection` 记录请求网格、 -预算及被排除的组合与原因;被排除的组合没有计时或正确性结果。 -该有效载荷上限不包含两个保护块及 CPU 参考缓冲区。 - -GPU smoke 检查可使用 `--block-bytes 257 --num-blocks 4 --warmup 1 ---iterations 2` 并覆盖全部三个方向。可选 GPU 测试同样执行这些复制及正确性检查: - -```bash -python3 -m unittest discover collectivex/tests -p 'test_swap_blocks.py' -v -``` - -仅有 CPU 的环境会执行测量和映射测试,并跳过真实 GPU 测试。 - -## GitHub GPU Action - -swap-blocks 是 **CollectiveX Sweep** 的一个套件。设置 `suites: swap-blocks`(或 `ep,swap-blocks` -同时运行两者),或执行: - -```bash -gh workflow run collectivex-sweep.yml --ref main \ - -f suites=swap-blocks -f swap_profile=smoke -``` - -`only_sku` 留空时运行所有已注册的 GPU 池,也可单独指定 `h200-dgxc`、`h100-dgxc`、`b200-nscale`、 -`b300`、`gb200`、`gb300`、`mi300x`、`mi325x` 或 `mi355x`。`exclude_skus` 接受以逗号分隔的排除列表。 -EP 筛选项(`backend`、`ep_sizes`、`modes`)仅作用于 `ep` 套件;未选择该套件时,矩阵会拒绝这些筛选项。 - -每个池生成一个分片,包含两个用例,每种布局一个。分片使用该池自己的启动器运行,因此沿用该池的 -资源分配、节点校验、镜像导入和清理流程;它申请一个节点、一个 GPU,时长 45 分钟。`config.py` -把每个用例编码为 `run_swap_blocks.py` 的参数,rank 包装脚本执行它,而不是 `run_ep.py`。 - -测试网格和镜像都写在 `configs/swap_sweep.json` 中。CUDA 与 AMD 池使用其中指定的官方 vLLM 镜像; -GB 池通过注册表的 `image_platform` 选择 ARM64 镜像,`sku_images` 可为某个池固定镜像。如需其他 vLLM -版本,请在分支上修改配置后从该分支触发。每种配置都覆盖三个方向和两种布局,并在计时前后检查真实 GPU -复制;后端准备阶段会在任何用例运行前确认能导入 `swap_blocks`。`smoke`(默认,块最大 256 KiB,168 个 -测试点)和 `standard`(4 KiB 至 1 MiB,126 个测试点)的全部测试点都在 2 GiB 有效载荷上限内。 -`large-blocks` 扫描 257 B 至 1 GiB 的块,**复制有效载荷上限为 1 GiB**,超出的组合会被排除并记录 -(测量 294 个测试点,排除 126 个);每个缓冲区另含两个保护块,因此 1 GiB 块的测试点每个缓冲区分配 -3 GiB,另需 CPU 正确性参考缓冲区。 - -下载 `cxshard--swap-blocks--` 可获得两个 JSON 结果文件,文件名为 -`_-c.json`,其中 case_id 为 `-swap-blocks--`。 -结果记录实际 GPU、框架版本、镜像、源代码 SHA、正确性状态和测量数据;EP 汇总表会跳过这些文档。 -CPU CI 独立运行,不能证明 GPU 正确性。 - -无法自行导入镜像的池可以在 `sku_images` 中指定运维预置的镜像缓存(`staged_image_dir`)。H100 即如此: -它先在 `/mnt/nfs/lustre/containers` 中按推理启动器的文件命名规则查找与请求标签完全一致的镜像, -有效的 squash 可直接复用,无需在计算 pod 内导入;文件不存在时走常规导入路径。 -`refresh_image=true` 会绕过预置缓存,要求重新导入。工作流为 H100 选择 `/var/tmp` 作为镜像导入 -临时目录,其他平台使用 `/tmp`。 diff --git a/inferencex-e2e/README_zh.md b/inferencex-e2e/README_zh.md index d7086d917f..87e0144494 100644 --- a/inferencex-e2e/README_zh.md +++ b/inferencex-e2e/README_zh.md @@ -7,7 +7,7 @@ 此项目包含模型推理服务基准测试、配置、启动器、Python 工具、文档及性能历史记录。 -请从[文档索引](docs/index_zh.md)开始阅读。 +请从[文档索引](docs/index.md)开始阅读。 [Python 项目清单](pyproject.toml)与[锁文件](uv.lock)由此项目维护。 从仓库根目录执行以下命令,安装并运行本地工具: @@ -20,7 +20,7 @@ uv run --locked python -m infx.matrix.generate test-config \ ``` 将 `` 替换为选定的配置键。工作流手动触发时的生成器参数也使用相对此目录的路径。 -依赖组与检查命令详见[测试指南](docs/testing_zh.md)。 +依赖组与检查命令详见[测试指南](docs/testing.md)。 项目内的 [Python 版本](.python-version)文件指定所用解释器。仓库规范和 GitHub 工作流仍位于仓库根目录。 本目录的[许可证](LICENSE)确保仅挂载此项目目录的容器仍可生成许可证归属信息。 diff --git a/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES.md b/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES.md index e1437a10a0..22cedceac7 100644 --- a/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES.md +++ b/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES.md @@ -1,7 +1,5 @@ # srt-slurm recipes -**English** | [中文](RECIPES_zh.md) - InferenceX owns the recipes in this directory. For every NVIDIA srt-slurm launch, the srt driver ([`infx/launch/drivers/srt/checkout.py`](../../../infx/launch/drivers/srt/checkout.py)) makes a job-local Git clone of the pinned submodule and copies this entire tree into `recipes/`. It records the actual revision in `srt-slurm-sha.txt`; power lanes copy that revision into `power-producer-sha.txt` for result validation. The shared version is the Git submodule pointer at [`utils/srt-slurm`](../../../utils/srt-slurm), currently [v2.43.4](https://github.com/NVIDIA/srt-slurm/releases/tag/v2.43.4) (`848f72d45b05af0fc082a9d1df49a8b4e7e61507`). Update that submodule pointer when upgrading, then run the recipe and integration checks. Do not add model-specific checkout branches to launchers. diff --git a/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES_zh.md b/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES_zh.md deleted file mode 100644 index 85586ff012..0000000000 --- a/inferencex-e2e/benchmarks/multi_node/srt-slurm-recipes/RECIPES_zh.md +++ /dev/null @@ -1,76 +0,0 @@ -# srt-slurm 配置 - -[English](RECIPES.md) | **中文** - -InferenceX 负责维护本目录中的配置。每次 NVIDIA srt-slurm 启动时,srt 驱动([`infx/launch/drivers/srt/checkout.py`](../../../infx/launch/drivers/srt/checkout.py))都会为作业创建固定版本子模块的本地 Git 克隆,并将整个目录复制到 `recipes/`。它将实际提交记录到 `srt-slurm-sha.txt`;功耗测试路径还会将其复制到 `power-producer-sha.txt`,供结果校验使用。 - -统一版本由 [`utils/srt-slurm`](../../../utils/srt-slurm) 的 Git 子模块指针指定,目前为 [v2.43.4](https://github.com/NVIDIA/srt-slurm/releases/tag/v2.43.4)(`848f72d45b05af0fc082a9d1df49a8b4e7e61507`)。升级时更新该子模块指针,然后运行配置和集成检查。不要在启动器中新增按模型选择检出版本的分支。 - -InferenceX 要求 srt-slurm 2.0 或更新版本,且配置必须声明 `schema: 2`。不支持旧版配置结构;加入本目录前必须先完成迁移。 - -## 目录和文件命名规范 - -所有配置统一存放在 `//-//.yaml`: - -```text -dsr1/sglang/b200-fp4/8k1k/disagg-stp-mtp-variants.yaml -glm5.2/sglang/h200-fp8/agentx/disagg-1p1d-pcp8-tp8-dp8-mtp6-hicache.yaml -qwen3.5/trtllm/gb300-fp4/agentx/disagg-variants.yaml -``` - -- 使用主配置中的 `model-prefix` 和 `precision` 标签。引擎目录为 `sglang`、`vllm`、`trtllm` 或 `tilert`;前端仍在配置内显式声明。硬件目录使用 `b200`、`gb300` 等 GPU 型号,不使用集群名称。 -- 工作负载目录为 `1k1k`、`8k1k` 或 `agentx`。已有的跨序列长度配置集合放在 `fixed-seq-len` 下,保留其覆盖项选择器。 -- 文件名使用小写字母和连字符,以 `agg` 或 `disagg` 开头。包含拓扑及用于区分同目录配置的关键参数,例如并行方式、批大小、并发数、MTP、卸载或缓存设置。避免日期、带序号的延迟/吞吐量标签,以及重复目录中已有的模型或硬件信息。 -- 拓扑名中的 `1p4d` 表示预填充/解码 worker 数,不一定等于物理节点数。`p-tp4` 和 `d-tp8` 分别标识预填充和解码 TP;`b` 表示批大小,`c` 表示并发数。运行参数以 YAML 为准。 -- 覆盖项集合使用 `*-variants.yaml` 命名。仅在各配置间存在差异的多节点 AgentX 配置,按主配置条目合并为一个集合,通常为 `agg-variants.yaml` 或 `disagg-variants.yaml`:`base` 保存共享设置,每个原配置成为一个具名 `override_` 块,只包含其差异(使用普通覆盖项,而非 `zip_override_*`)。主配置通过 `CONFIG_FILE=recipes//.yaml:override_` 选择其一。启动器以文本方式读取的配置(例如带顶层 `telemetry:` 的功耗配置)保持独立文件。即使内容相同,也保留独立扫描入口:配置路径参与评估分组。Qwen3.5 的 `*-stp-sweep.yaml` 和 `*-mtp-sweep.yaml` 保留了这一既有区别。 -- 移动文件时,同步更新当前及已弃用主配置中的 `CONFIG_FILE`、`EVAL_CONFIG_FILE`,以及启动器路径规则、工作流过滤器和本地文档。保留上游来源 URL,并保持历史性能变更日志不变。不为旧目录结构提供别名。 - -共享运行时资源保留在模型目录旁的 `configs/` 中,不属于独立基准测试配置。`configs/dsv4-moe-load-balancer-configs/` 中的四个文件原样取自 NVIDIA/srt-slurm 提交 `deb1dfd9934398664f92d194169c183e009da83b`,保留了此前 DSV4 TRT 配置使用的 EPLB 初始专家分配;目前没有已提交的配置引用这些文件。srt driver([`infx/launch/drivers/srt/checkout.py`](../../../infx/launch/drivers/srt/checkout.py))将这些文件复制到作业仓库的 `configs/` 目录,供配置中的绑定挂载使用。将配置文件放入本目录不会启用该配置;实际基准测试矩阵由主配置决定。 - -## TileRT - -TileRT 使用固定版本的上游 srt-slurm 子模块。配置指定 `roles.prefill.engine: vllm`、`roles.decode.engine: tilert` 和 `frontend.type: tilert-router`。 - -## Schema 2 与主配置 - -配置使用 `schema: 2`、`engine` 和 `roles`。每个工作角色集中声明节点数、实例数、GPU 分配、环境变量和引擎参数。`resources` 保留 GPU 硬件信息,`placement` 控制前端和基准测试客户端的位置,`services` 描述辅助进程,`dynamo.source` 指定 Dynamo 软件包或源码提交。 - -| 配置字段 | `configs/nvidia-master.yaml` 字段 | -|---|---| -| `roles.prefill.workers` | `prefill.num-worker` | -| `roles.decode.workers` | `decode.num-worker` | -| `roles.prefill.args.tp-size`(SGLang) | `prefill.tp` | -| `roles.prefill.args.ep-size`(SGLang) | `prefill.ep` | -| `roles.prefill.args.enable-dp-attention` | `prefill.dp-attn` | -| `benchmark.concurrencies` | `conc-list` | -| 配置路径,可附带覆盖项选择器 | `additional-settings: CONFIG_FILE=recipes/...yaml` | - -配置文件和主配置必须同步更新。启动器执行配置文件;主配置提供结果标签和调度元数据。聚合式配置使用 `roles.agg`;`roles.decode.nodes: colocate` 表示解码角色与预填充角色共享节点,不增加调度所需的工作节点数。 - -所有被引用的配置都必须纳入版本控制:srt-slurm 2 提供精选示例,不再携带历史 `recipes/` 目录。本次迁移补齐了 204 个此前依赖外部仓库的配置,并从 InferenceX 历史记录恢复了两个仍被引用的 AgentX 配置。主配置路径遵循上述目录结构,原有覆盖项选择器保持不变。 - -## 迁移与验证 - -在隔离环境中安装统一版本,然后使用其 CLI: - -```bash -srtctl migrate --in-place -f benchmarks/multi_node/srt-slurm-recipes/dsr1/sglang -# 对其他模型/引擎目录重复执行。 -python -m pytest infx/tests/matrix/ -q -python -m infx.matrix.generate full-sweep \ - --config-files configs/nvidia-master.yaml \ - --framework dynamo-sglang dynamo-trt dynamo-vllm --multi-node -``` - -使用启动器指定的确切提交验证配置,包括全部覆盖变体。当前迁移 CLI 已不提供 `--verify`;迁移后对每个选中的配置运行 `srtctl dry-run`,必要时通过 `--set` 提供启动器注入的值,例如 `benchmark.concurrencies`。仅调整路径时,应按路径映射比较变更前后的生成矩阵;其他字段(包括评估选择和节点数)必须完全一致。本地配置校验通过不能替代完整硬件扫描和准确性评估。 - -本次迁移还修复了 `srtctl migrate` 无法自动处理的兼容性问题: - -- SGLang Model Gateway 配置使用 `frontend.type: sglang-router`;在 v2.36.0 中,`sglang` 表示不经过路由器的独立工作进程。 -- 对重复的 YAML 键,保留原 PyYAML 加载器实际采用的值。 -- DCGM 遥测使用 `collect_interval_ms: 1000`,替代 `provider` 和 `default_frequency`。采集器自动推导退出等待时间;原先显式设置的十秒不满足当前校验要求。保留原配置中服务发现进程的专用节点部署方式。固定的上游版本不支持在专用基础设施节点上启用遥测;该功耗兼容性问题仍待解决,不通过改变原有拓扑来绕过校验。H200 自定义配置声明默认并发数,提交前由启动器替换。 -- DeepSeek-V4 vLLM 基准测试使用受支持的 `custom_tokenizer` 加载器。删除已废弃的 `warmup_req_rate: inf` 字段;当前上游客户端的预热速率固定为每秒 250 个请求。 -- 功耗读取器兼容两代 samples CSV,校验利用率字段,并继续根据瓦特数计算 GPU 板级能耗。 -- 评估选择通过原生 `post_eval.command` 和 `post_eval.passthrough_env` 调用 [`srt_eval.sh`](../srt_eval.sh)。TRT AgentX 配置通过 `dynamo.source.git` 声明原有的 Dynamo 分支仓库,启动器不再改写 srt-slurm 源码。 - -每次修改配置或运行时,都必须在 `perf-changelog.yaml` 的物理末尾追加新条目,保留全部历史内容及空白。合并前使用 `full-sweep-fail-fast` 验证 PR(包括评估),再按仓库规定完成审查及产物复用合并流程。 diff --git a/inferencex-e2e/docs/MODELS.md b/inferencex-e2e/docs/MODELS.md index dc1fafbd61..888e0f007d 100644 --- a/inferencex-e2e/docs/MODELS.md +++ b/inferencex-e2e/docs/MODELS.md @@ -1,7 +1,5 @@ # Models -English | [中文](MODELS_zh.md) - This document tracks every model benchmarked by InferenceX-e2e: when it was added, which benchmark scenarios are currently active for it, and which scenarios are deprecated. Results for active scenarios are published to . ## Review and merge SLO @@ -136,4 +134,4 @@ Other offloading tiers, including NVMe KV cache offloading, are outside the init - Deprecating a precision (e.g. Qwen3.5 bf16) or one arm of an A/B pair (e.g. non-MTP) narrows a model's recipe coverage without retiring the model. The model stays listed as active as long as one scenario still runs. - Klaud Cold reads the Scenarios table and this page's Model support matrix when it freezes an image-refresh baseline. A published single-turn point is exempt from re-measurement only if the family no longer runs any point with its ISL/OSL; the only Scenarios row for that ISL/OSL starts with `Deprecated since YYYY-MM-DD ([#N](PR link))` or `**Deprecated for all models** since YYYY-MM-DD ([#N](PR link))`, dated after the baseline and linking a PR of this repository; and the model's row lists that scenario under deprecated and not under active scenarios. Removing only some topologies or concurrencies exempts nothing. Keep that wording, one row per ISL/OSL and per model, and one cell per column when editing these tables; see [Klaud Cold reports](klaud-reporting.md). - `dsr1` began as the DeepSeek-V3 workflow templates in the initial repo import and was switched to DeepSeek-R1 benchmarking on 2025-08-13 (renamed `dsv3` → `dsr1` on 2025-08-20). -- Adding a model? Use the [config reference](../configs/CONFIGS.md) and add a row here (and in [`MODELS_zh.md`](MODELS_zh.md)) in the same PR. +- Adding a model? Use the [config reference](../configs/CONFIGS.md) and add a row here in the same PR. diff --git a/inferencex-e2e/docs/MODELS_zh.md b/inferencex-e2e/docs/MODELS_zh.md deleted file mode 100644 index b053918b21..0000000000 --- a/inferencex-e2e/docs/MODELS_zh.md +++ /dev/null @@ -1,139 +0,0 @@ -# 模型列表 - -[English](MODELS.md) | 中文 - -本文档记录 InferenceX-e2e 基准测试覆盖的所有模型:加入日期、当前启用的基准测试场景,以及已弃用的场景。启用场景的结果发布于 。 - -## 审核与合并 SLO - -基于公平、公正的原则,我们对 PR 审核与合并所力求达到的服务级别目标(SLO)为 `max(从在 Slack 中收到提醒时起算 1 天, 厂商响应时间)`。厂商响应时间指厂商回复 InferenceX 核心维护者的问题、消息、PR、后续审核请求等所需的时间。我们很可能会比该公式给出的时限更早完成审核与合并,但这是我们力求达到的 SLO。 - -## 弃用政策 - -InferenceX-e2e 运行在固定的 GPU 池上,维护团队规模较小,因此不再值得占用集群时间的场景、精度和方案变体会被退役。下方的模型支持矩阵是当前启用与退役情况的记录;过去的设置保存在 git 历史和 `perf-changelog.yaml` 中。 - -- **待执行的 A/B 基线退役(尚未执行):** 仅为与投机解码对比而保留的独立非投机解码基线计划退役:`dsv4`、`qwen3.5` 和 `glm5.2` 的非 MTP,`minimaxm3` 的非 EAGLE3,`kimik3` 的非 DSpark。只有在受影响的模型、硬件和引擎已有替代覆盖时才可退役。存在投机解码对应配置本身不是删除某个配置的理由。 -- **新模型不再维护单独的 A/B 轨道:** [`infx/golden_al_distribution/`](../infx/golden_al_distribution) 会把投机解码 AgentX 运行固定到一条实测接受长度曲线上,因此投机解码结果本身即可比较。新模型(包括 Kimi-K3)从第一天起无需非投机解码基线。 -- **无论是否启用投机解码,都发布最佳帕累托点。** 当关闭 MTP、EAGLE/EAGLE3、DSpark 或其他 draft 方法能得到更好的工作点时,方案可以关闭它们。有效的非投机解码结果仍可依据[北极星帕累托策略](#北极星帕累托策略)发布,因此前沿可以同时包含两类点。 - -## 场景 - -| 场景 | ISL/OSL | 状态 | -|---|---|---| -| 智能体编码(agentic coding) | 长上下文、多轮真实流量的轨迹回放,含子智能体(sub agents) | 启用。此场景采用基于轨迹回放的智能体编码基准测试(见 [`benchmarks/single_node/srt-slurm-recipes/`](../benchmarks/single_node/srt-slurm-recipes) 下的 srt-slurm 配方与共享客户端 [`benchmarks/srt_agentic.sh`](../benchmarks/srt_agentic.sh))。今后新模型预计将仅以智能体编码场景接入。可开启或关闭投机解码以获得最优帕累托点;不要求独立的非投机解码 A/B 基线(见[弃用政策](#弃用政策))。 | -| 单轮 8k1k | 8192 / 1024 | 启用。当前主要的固定序列长度(fixed-seq-len)场景。 | -| 单轮 1k1k | 1024 / 1024 | 自 2026-07-17 起弃用([#2263](https://github.com/SemiAnalysisAI/InferenceX/pull/2263)),以便将 GPU 集群时间留给优先级更高的真实场景智能体编码基准测试与新的前沿模型。归档配置曾位于 `configs/deprecated/`,该目录已在 #3463 中删除,请查阅 Git 历史。后续由 [#2533](https://github.com/SemiAnalysisAI/InferenceX/pull/2533) 加入的 GLM-5.1 B200 TileRT 测试点是最后一个 1k1k 配置,已于 2026-10-01 退役([#3638](https://github.com/SemiAnalysisAI/InferenceX/pull/3638))。 | -| 单轮 1k8k | 1024 / 8192 | **对所有模型均已弃用**,自 2026-03-27 起([#911](https://github.com/SemiAnalysisAI/InferenceX/pull/911)),以便将 GPU 集群时间留给优先级更高的真实场景智能体编码基准测试与新的前沿模型。相关配置已删除,未归档。 | - -## AgentX 指南 - -### 端到端归一化交互性与帕累托前沿策略 - -端到端归一化交互性(E2E normalized interactivity)是 AgentX 轨迹回放结果的主要用户侧延迟指标,也是默认横轴。对于每个有效的性能分析请求 `i`,令 `OSL_i` 表示其正值输出序列长度,`E2EL_i` 表示其正值端到端延迟。E2EL 同时包含首 Token 延迟(TTFT)与生成时间。首先计算每个请求交付一个输出 Token 所需的时间: - -`r_i = E2EL_i / OSL_i`(秒/输出 Token) - -对于百分位数 `q`,端到端归一化交互性定义为: - -`端到端归一化交互性_q = 1 / percentile_q({r_i})`(输出 Token/s/user) - -仪表板默认使用 P90。先在“秒/输出 Token”上取百分位数,再求倒数,既保留了慢尾延迟的含义,又将结果表示为越高越好的速率。该指标并不是分别聚合 OSL 与 E2EL 的百分位数后再取两者之比。在单个请求层面,可将其近似理解为: - -`OSL / E2EL ≈ 1 / (TPOT + TTFT / OSL)` - -直观地说,可以将其理解为在解码交互性的基础上,对排队和预填充期间用户尚未收到任何输出 Token 的等待时间施加惩罚。 - -### 优势 - -- 它降低了 AgentX 输出长度波动对原始端到端延迟的直接影响:请求不会仅仅因为正确生成了更多输出而被视为更慢。 -- 它以一个用户侧交付速率同时衡量 TTFT 与解码节奏,避免配置只优化解码交互性,却任由 TTFT 或任务总完成时间退化。 -- 它使用熟悉的 Token/s/user 单位,提供越高越好的优化目标,同时覆盖完整的请求路径。 - -### 权衡与局限 - -- 它不等同于常规解码交互性(`1 / TPOT`),因此两者的绝对值不能直接比较。由于计入 TTFT,端到端归一化交互性通常更低。 -- TTFT 会按 OSL 摊薄,因此短输出受到的 TTFT 惩罚大于长输出。该指标仍与工作负载有关,只有使用相同轨迹分布和基准测试方法的结果才能比较。 -- 单一综合指标无法说明退化来自 TTFT 还是解码阶段。独立的端到端延迟、交互性和 TTFT 视图仍用于诊断。 -- 该指标依赖持久化的逐请求轨迹,并要求 E2EL 与 OSL 均为有效值。缺少这些轨迹的运行无法参与规范的帕累托前沿。 - -### 北极星帕累托策略 - -对于每个受支持的纵轴指标和对比组,以端到端归一化交互性为横轴计算出的帕累托前沿,是 AgentX 规范的**北极星(North Star)**前沿。其他所有 AgentX 横轴视图都必须受这一规范优胜点集合约束: - -- 端到端归一化交互性视图展示规范的北极星前沿。 -- 端到端延迟、常规交互性与 TTFT 视图展示“规范北极星前沿”与“当前坐标系中真实帕累托前沿”的交集。 - -因此,只有同时属于北极星优胜点、且在所选图表中不被其他点支配的数据点,才能出现在任一 AgentX 帕累托前沿上。该规则可防止某个配置以牺牲端到端用户体验为代价,只优化某一辅助延迟指标却仍进入发布的前沿。被支配的数据点仍保留在未过滤的散点视图中,供诊断使用。 - -### 引擎提交策略 - -根据 Tier 1 AI 实验室和更广泛的机器学习社区对 InferenceX AgentX 展示内容的反馈,InferenceX 采用明确的模型到框架映射。多家实验室反馈,TensorRT-LLM、ATOM 等专有或硬件专用引擎并不总能提供其 AgentX 工作负载所需的全部功能。 - -下表中的原生/上游(native/upstream)引擎是各模型的一级支持引擎。如果某一提供方将原生/上游 vLLM 引擎和原生/上游 SGLang 引擎均作为一级支持的 LLM 引擎,则必须先按照本映射提交指定的一个或多个引擎,之后才能提交 ATOM、TensorRT-LLM、TokenSpeed 等其他非 vLLM/SGLang 引擎。允许提交多个其他非 vLLM/SGLang 引擎。 - -该提交顺序指南有两项例外: - -1. 对于 MI455X UALoE72、VR200 NVL72、Rubin NVL8、TPUv8t、TPUv8i 等全新硬件 SKU,为实现初始支持,可先使用硬件专用引擎。预期相应的原生/上游 vLLM 或 SGLang 提交会在此后不久跟进。 -2. 对于新的模型架构,如果提供方无法将映射指定的原生/上游 vLLM 或 SGLang 引擎作为一级支持引擎,并能向核心维护者说明该框架尚不支持相应硬件与模型组合的根本性、第一性原理原因,则可先使用其他引擎。 - -InferenceX 支持 SGLang 和 vLLM 双方的维护者,并响应 AI 实验室和机器学习社区希望看到两个框架性能数据的反馈。在仅指定一个主要框架的模型中,映射会将任务均衡分配给 vLLM 和 SGLang。同时指定两个框架的模型则提供共享覆盖。这确保 InferenceX 对两个框架进行同等测试,不偏向任何一方。 - -表中还同时记录已达成一致的草稿模型规划(PoR)以及尚待合作伙伴对齐的提案。 - -| 模型 | 首选原生/上游引擎 | 已达成一致的草稿模型(PoR) | 待合作伙伴对齐的草稿模型提案 | 其他引擎 | -|---|---|---|---|---| -| DeepSeek-V4-Pro 1.6T(`dsv4`) | 原生/上游 vLLM 引擎和原生/上游 SGLang 引擎 | 原生 MTP(智能体编码 MTP 分支;此前亦用于单轮 8k1k,已于 2026-09-09 退役);`deepseek-ai/DeepSeek-V4-Pro-0813`(仅用于智能体编码,遵循与 Kimi-K3 DSpark PoR 相同的合成接受方法) | 无 | 按照上述提交顺序指南及例外处理的其他非 vLLM/SGLang 引擎 | -| Kimi-K3(`kimik3`) | 原生/上游 vLLM 引擎 | `Inferact/Kimi-K3-DSpark` | 无 | 按照上述提交顺序指南及例外处理的其他非 vLLM/SGLang 引擎 | -| MiniMax-M3(`minimaxm3`) | 原生/上游 vLLM 引擎 | `Inferact/MiniMax-M3-EAGLE3` 和/或 `Inferact/MiniMax-M3-EAGLE3-GQA` | 无 | 按照上述提交顺序指南及例外处理的其他非 vLLM/SGLang 引擎 | -| GLM-5.2(`glm5.2`) | 原生/上游 SGLang 引擎 | 原生 MTP | 无 | 按照上述提交顺序指南及例外处理的其他非 vLLM/SGLang 引擎 | -| Qwen3.5-397B-A17B(`qwen3.5`) | 原生/上游 SGLang 引擎 | 原生 MTP | 无 | 按照上述提交顺序指南及例外处理的其他非 vLLM/SGLang 引擎 | -| Qwen3.8-Flash-Next(`qwen3.8next`) | 原生/上游 SGLang 引擎 | 待定 | 原生 MTP(内置 4B 多步预测模块;黄金 AL 采集脚本:[`qwen3.8next_fp4_b300_vllm.sh`](../benchmarks/single_node/speedbench/qwen3.8next_fp4_b300_vllm.sh)) | 按照上述提交顺序指南及例外处理的其他非 vLLM/SGLang 引擎 | - -### KV 缓存卸载策略 - -为遵循“通过限制范围实现快速交付”的设计原则,AgentX 初始策略仅允许 CPU DRAM KV 缓存卸载,且该功能为可选项。支持的方案包括 vLLM Connector、LMCache、SGLang HiCache、Mooncake CPU DRAM Connector、Dynamo KVBM、CPU DRAM P2P 池化以及类似的 CPU 内存机制。供应商可自行决定是否为每项提交启用 CPU KV 缓存卸载。如果禁用后能得到更优的 Pareto 点,也可选择禁用。 - -用于 KV 缓存卸载的 CPU DDR5 容量必须与推理配置实际使用的服务器 GPU 比例成正比: - -`允许的 CPU DRAM = 每服务器 CPU DRAM 基准容量 ×(配置使用的 GPU 数 / 服务器 GPU 总数)` - -该规则按每台服务器独立计算。 - -| CPU DRAM 容量类别 | 示例 SKU | 每服务器基准与上限 | -|---|---|---| -| CPU DRAM 容量未标准化 | HGX B200、HGX B300、MI355X 机箱 | 每服务器最多 3 TB。因此,仅使用 8 块 GPU 中 4 块的配置最多可使用 1.5 TB CPU DRAM 进行 KV 缓存卸载。 | -| CPU DRAM 容量已标准化 | TPUv7、GB200 NVL72、GB300 NVL72 | 以该 SKU 标准安装的 CPU DRAM 容量为基准,不另设每服务器硬上限,但仍须遵守 GPU 比例规则。 | - -3 TB 上限旨在避免不现实的内存容量竞赛,即各硬件供应商要求云服务提供商(CSP)和原始设备制造商(OEM)安装尽可能多的高容量 DIMM,导致每服务器容量可能达到 6 TB。每颗加速器芯片的总体拥有成本(TCO)将按服务器 CPU DDR5 总容量的成本进行归一化。 - -其他卸载层级(包括 NVMe KV 缓存卸载)不属于初始范围,可在 InferenceX v3 发布后引入。NVMe KV 缓存卸载暂定在 InferenceX v3.5 中作为快速后续功能加入,或纳入 InferenceX v4。 - -## 模型支持矩阵 - -| 模型架构类别 | 前缀 | 加入日期 | 启用场景 | 已弃用场景 | -|---|---|---|---|---| -| DeepSeek-V4.1-Flash | `dsv41flash` | 2026-09-10 | 智能体编码(vLLM:DSpark、Engram UVA 卸载;SGLang:自 2026-09-17 起按 SKU 添加 DSpark 配置;ATOM:2026-09-23 添加 MI355X TP2/TP4 DSpark,后于 #3463 移除,2026-09-30 以 srt-slurm 恢复;GPU 待验证) | | -| GLM-5.3 | `glm5.3` | 2026-09-22([#3366](https://github.com/SemiAnalysisAI/InferenceX/pull/3366)) | 智能体编码(仅 MTP,见弃用政策) | 单轮 1k1k(在本模型加入前已对所有模型弃用,从未运行) | -| Qwen3.8-Flash-Next | `qwen3.8next` | 2026-08-26([#2742](https://github.com/SemiAnalysisAI/InferenceX/pull/2742)) | 智能体编码 | | -| Kimi-K3 | `kimik3` | 2026-07-27 ([#2391](https://github.com/SemiAnalysisAI/InferenceX/pull/2391)) | 智能体编码(可关闭 DSpark 以获得更优帕累托点) | 独立非 DSpark A/B 基线(自第 0 天起即不要求) | -| GLM-5.2 | `glm5.2` | 2026-07-18([#2268](https://github.com/SemiAnalysisAI/InferenceX/pull/2268)) | 智能体编码(非 MTP 数据点仍可按帕累托策略参与发布;见弃用政策) | | -| MiniMax-M3 | `minimaxm3` | 2026-06-12([#1724](https://github.com/SemiAnalysisAI/InferenceX/pull/1724)) | 智能体编码 | 单轮 1k1k、单轮 8k1k(2026-08-04 移除,[#2493](https://github.com/SemiAnalysisAI/InferenceX/pull/2493)) | -| DeepSeek-V4-Pro | `dsv4` | 2026-04-24([#1130](https://github.com/SemiAnalysisAI/InferenceX/pull/1130)) | 智能体编码(非投机解码数据点仍可按帕累托策略参与发布) | 单轮 1k1k、单轮 8k1k(已于 2026-09-09 移除,[#2921](https://github.com/SemiAnalysisAI/InferenceX/pull/2921)) | -| GLM-5 / GLM-5.1 | `glm5`、`glm5.1` | 2026-03-06([#762](https://github.com/SemiAnalysisAI/InferenceX/pull/762)),GLM-5.1 于 2026-04-21 加入([#1098](https://github.com/SemiAnalysisAI/InferenceX/pull/1098)) | 无(2026-10-01 完全退役,[#3638](https://github.com/SemiAnalysisAI/InferenceX/pull/3638)) | 此前的 GLM-5 / GLM-5.1 配方于 2026-07-18 退役([#2276](https://github.com/SemiAnalysisAI/InferenceX/pull/2276));GLM-5.1 B200 TileRT 的 1k1k 与 8k1k 测试点(2026-08-09 加入,[#2533](https://github.com/SemiAnalysisAI/InferenceX/pull/2533))于 2026-10-01 退役([#3638](https://github.com/SemiAnalysisAI/InferenceX/pull/3638)) | -| MiniMax-M2.5/2.7 | `minimaxm2.5` | 2026-02-18([#755](https://github.com/SemiAnalysisAI/InferenceX/pull/755)) | 无(2026-06-20 退役,[#1874](https://github.com/SemiAnalysisAI/InferenceX/pull/1874)) | 单轮 1k1k、单轮 1k8k、单轮 8k1k | -| Kimi-K2.5/2.6/2.7-Code | `kimik2.5` | 2026-02-17([#734](https://github.com/SemiAnalysisAI/InferenceX/pull/734)) | 无(2026-08-07 完全退役,[#2527](https://github.com/SemiAnalysisAI/InferenceX/pull/2527)) | 单轮 1k1k、单轮 1k8k、智能体编码(2026-08-04 移除,[#2493](https://github.com/SemiAnalysisAI/InferenceX/pull/2493))、单轮 8k1k(2026-08-07 移除,[#2527](https://github.com/SemiAnalysisAI/InferenceX/pull/2527)) | -| Qwen3.5-397B-A17B | `qwen3.5` | 2026-02-16([#704](https://github.com/SemiAnalysisAI/InferenceX/pull/704)) | 单轮 8k1k 与智能体编码,二者均仅限 fp8/fp4 | 单轮 1k1k、单轮 1k8k、全部 bf16 配方(2026-08-04 移除,[#2493](https://github.com/SemiAnalysisAI/InferenceX/pull/2493)) | -| gpt-oss-120b | `gptoss` | 2025-09-09 | 无(2026-07-06 退役,[#2101](https://github.com/SemiAnalysisAI/InferenceX/pull/2101)) | 单轮 1k1k、单轮 1k8k、单轮 8k1k | -| DeepSeek-R1-0528 | `dsr1` | 2025-08-13 | 单轮 8k1k | 单轮 1k1k、单轮 1k8k | -| Llama-3.1-70B-Instruct | `llama70b` | 2025-08-12 | 无(2025-10-29 退役,[#149](https://github.com/SemiAnalysisAI/InferenceX/pull/149)) | 单轮 1k1k、单轮 1k8k、单轮 8k1k [^1] | - -[^1]: `llama70b` 早于 master 配置体系。退役时其配置被直接删除,未归档到 `configs/deprecated/`。该模型最初以 workflow 模板形式随仓库首次导入(2025-08-12)。 - -## 说明 - -- 「前缀」列为 `configs/*-master.yaml` 中的规范 `model-prefix`,同时用于 `full-sweep` 子命令的 `--model-prefix` 筛选参数,例如 `python -m infx.matrix.generate full-sweep --config-files configs/nvidia-master.yaml --model-prefix dsr1`。 -- 「退役」指该模型已无任何启用场景。退役模型的配置直接从主配置中删除;原 `configs/deprecated/` 归档目录已在 #3463 中删除,历史设置保留在 Git 历史与 `perf-changelog.yaml` 中。 -- 弃用某一精度(如 Qwen3.5 bf16)或 A/B 对照中的某一分支(如非 MTP),只是收窄该模型的配方覆盖范围,并不等于模型退役;只要仍有一个场景在运行,该模型即继续列为启用状态。 -- Klaud Cold 冻结镜像更新基线时会读取英文版 [`MODELS.md`](MODELS.md) 的场景表和模型支持矩阵。已发布的单轮测试点仅在以下条件全部满足时才免于重新测量:配置族已不再运行任何具有其 ISL/OSL 的测试点;场景表中该 ISL/OSL 唯一的一行以 `Deprecated since YYYY-MM-DD ([#N](PR link))` 或 `**Deprecated for all models** since YYYY-MM-DD ([#N](PR link))` 开头,日期晚于基线日期,并链接本仓库的 PR;该模型所在行将此场景列为已弃用场景,且未列为启用场景。只移除部分拓扑或并发不会获得豁免。编辑这些表格时请保留该写法,每个 ISL/OSL 和每个模型各占一行,每列只占一个单元格;详见 [Klaud Cold 报告](klaud-reporting_zh.md)。 -- `dsr1` 最初以 DeepSeek-V3 workflow 模板的形式随仓库首次导入,2025-08-13 切换为 DeepSeek-R1 基准测试(2025-08-20 将 `dsv3` 重命名为 `dsr1`)。 -- 新增模型时,请查阅[配置参考](../configs/CONFIGS.md),并在同一 PR 中同时更新本文件与 [`MODELS.md`](MODELS.md) 的表格。 diff --git a/inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md b/inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md index 699a1f87f4..5ee85144c6 100644 --- a/inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md +++ b/inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md @@ -1,11 +1,5 @@ # PR Review Checklist -
- -**English** | [中文](PR_REVIEW_CHECKLIST_zh.md) - -
- When [CODEOWNER](https://github.com/SemiAnalysisAI/InferenceX/blob/main/.github/CODEOWNERS) from the respective hardware AI chip company is reviewing & approving their respective PRs, please fill in the following form in your approval comment before pinging an core maintainer for final approval **Only one eligible CODEOWNER reviewer needs to post the checklist for each PR.** Check for an existing checklist before posting; additional reviewers do not need to post their own copies. For corrections, missing evidence, or verification retries, the original reviewer must **edit their existing checklist comment** instead of adding a new one. Create a replacement only if the original comment was deleted. diff --git a/inferencex-e2e/docs/PR_REVIEW_CHECKLIST_zh.md b/inferencex-e2e/docs/PR_REVIEW_CHECKLIST_zh.md deleted file mode 100644 index ea6ef53fc8..0000000000 --- a/inferencex-e2e/docs/PR_REVIEW_CHECKLIST_zh.md +++ /dev/null @@ -1,94 +0,0 @@ -# PR 审阅清单 - -
- -[English](PR_REVIEW_CHECKLIST.md) | **中文** - -
- -当相应硬件 AI 芯片公司的 [CODEOWNER](https://github.com/SemiAnalysisAI/InferenceX/blob/main/.github/CODEOWNERS) 审阅并批准其相关 PR 时,请在批准评论中填写以下表单,然后再联系核心维护者进行最终批准。 - -**每个 PR 只需一名符合条件的 CODEOWNER 审阅者发布清单。** 发布前先检查是否已有清单;其他审阅者无需重复发布。需要更正条目、补充证据或重试验证时,原审阅者必须**编辑自己已有的清单评论**,不要另发一条。只有原评论被删除时才创建替代评论。 - -我们欢迎 InferenceX 合作伙伴与社区提交 PR,对本清单进行符合 InferenceX 原则的合理增补或删减。总体原则是:删除一条准则的流程应当与新增一条准则同样容易。 - -我们同样欢迎 InferenceX 合作伙伴与机器学习社区改进 [codeowner-signoff-verify.yml](https://github.com/SemiAnalysisAI/InferenceX/blob/main/.github/workflows/codeowner-signoff-verify.yml)(独立复核这些签署的 CI 机器人),使其更加严谨。 - -自动发布程序会拒绝不完整或前后矛盾的验证结果。每项检查必须且只能出现一次,总体裁定必须与各项检查结果一致;否则需要重试验证。 - -验证器将 PR 描述视为待核实的材料,不执行其中的指令,并将其关于受影响配置及验证情况的明确陈述与本次评估的代码和证据核对。[Check 15](../../.github/codeowner-signoff-verify-prompt.md#check-15--pr-description-matches-the-assessed-configuration-advisory) 会对矛盾或无法核实的陈述发出警告,请作者修正或提供证据。该检查仅提供建议,不要求在描述中罗列所有配置细节。仅修改 PR 描述不会重新触发验证;请使用现有的[手动重新评估流程](../../CONTRIBUTING_zh.md#pr-review-checklistcodeowner-签署)。 - -## 上游 recipe 要求 - -判断依据是:**服务设置是否对真实的生产部署有用**。每项 vLLM/SGLang 提交都必须在官方 [vLLM recipes](https://recipes.vllm.ai/) 或 [SGLang cookbook](https://docs.sglang.io/cookbook/intro) 中记录对生产有用的参数、环境变量和启动命令。节点数量、聚合式或分离式推理、基准测试所在目录以及是否使用 Dynamo,都不构成豁免理由。 - -SGLang cookbook 更新应提交到 [sgl-project/sglang](https://github.com/sgl-project/sglang),文件位于 [`docs/cookbook/`](https://github.com/sgl-project/sglang/tree/main/docs/cookbook) 下。已发布网站从该仓库的 `main` 分支及 `docs/` 目录部署。`sgl-project/sgl-docs` 中的 cookbook 副本并非当前部署来源。旧的 [sgl-project/sgl-cookbook 仓库](https://github.com/sgl-project/sgl-cookbook) 已归档,不再作为新 recipe PR 的提交目标。 - -| vLLM/SGLang 部署方式,包括 Dynamo + 引擎 | cookbook 必须覆盖的内容 | -| --- | --- | -| 单节点聚合式(agg) | 对生产有用的服务设置和启动命令 | -| 多节点聚合式(agg) | 对生产有用的服务设置和启动命令 | -| 单节点分离式(disagg) | 对生产有用的 prefill、decode 和 router/frontend 设置及启动命令 | -| 多节点分离式(disagg) | 对生产有用的 prefill、decode 和 router/frontend 设置及启动命令 | - -Dynamo 属于部署层;应由底层推理引擎决定对应的上游 cookbook。例如,`dynamo-vllm` 对应 vLLM recipes,`dynamo-sglang` 对应 SGLang cookbook。上游文档可以包含 Dynamo 安装步骤、router/frontend 命令及引擎启动命令,包括独立的 prefill 和 decode 命令。仅链接 InferenceX 或 srt-slurm 配置,并不能让生产用户从文档中获得这些命令。 - -混合提交须逐一核实受影响的生产服务变体。一个上游页面或 PR 可以覆盖多个变体,但只有聚合式示例的文档不足以覆盖分离式部署。多个变体共用一条仪表板曲线,也不免除各自的 recipe 文档要求。 - -仅用于 InferenceX 的测试框架衔接、结果收集及合成基准测试控制,无需提交到上游。应按实际作用判断参数或环境变量:即使 InferenceX 用某项优化调优基准测试,只要该优化对生产有用,就仍须在 cookbook 中记录。在 Additional detail section 中说明排除某项设置的理由;仅以节点数量或分离式推理为由填写 N/A 不成立。 - -若已有合并或发布的文档覆盖该生产配置,即可满足要求,无需重复创建上游 PR。否则,应更新对应的上游 cookbook,并确认该 PR **在 InferenceX PR 合并前已合并(MERGED)**。默认行为也可以满足文档覆盖要求,前提是审阅者已核实锁定上游版本中的等效行为并记录证据。 - -> **重要:模板请保持英文原文,原样复制粘贴,不要翻译。** CI 签署验证工作流 [`codeowner-signoff-verify.yml`](https://github.com/SemiAnalysisAI/InferenceX/blob/main/.github/workflows/codeowner-signoff-verify.yml) 通过开头语句 "As a PR reviewer and CODEOWNER, I have reviewed this and have" 触发;模板被改写或翻译后,签署验证 CI 将不会触发。 - -## 模板(请复制英文原文) -``` -As a PR reviewer and CODEOWNER, I have reviewed this and have: -- [ ] Verified that as of the moment of typing this, this is the latest version of [PR_REVIEW_CHECKLIST.md](https://github.com/SemiAnalysisAI/InferenceX/blob/main/inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md) -- [ ] Verified that the general code quality meets the InferenceX standard and does not make the code quality any worse. -- [ ] Verified that this PR has passed PR validation. Please link to GitHub Action workflow that shows this. -- [ ] Verified that this PR passes evals. Please link to GitHub Action workflow that shows this. -- [ ] Verified that speculative decoding PRs uses chat templates to align the AL distribution to real world -- [ ] Verified that every draft model and draft head is served as it ships: the draft that ships with the served checkpoint, at its stored precision, through the pinned upstream image's default handling, with the shipped and effective draft precision recorded in the additional detail section. No submission-side quantization, dtype override, checkpoint substitution, or patch may lower draft precision below that default, regardless of eval results or AL. Explicitly verified that `SGLANG_NVFP4_CKPT_FP8_NEXTN_MOE` is not enabled in the effective recipe, including inherited settings; enabling it is prohibited going forward, and historical runs do not grant an exception. See [Draft-model precision](https://github.com/SemiAnalysisAI/InferenceX/blob/main/CONTRIBUTING.md#draft-model-precision) for what counts as the default and the MLPerf comparison. -- [ ] For agentic workloads: verified that speculative-decoding configs (EAGLE / MTP / draft models) run with simulated synthetic acceptance, with the acceptance-length value taken from the committed golden AL curve in [infx/golden_al_distribution/](https://github.com/SemiAnalysisAI/InferenceX/tree/main/inferencex-e2e/infx/golden_al_distribution) for that model, thinking mode, and draft length. A submission may choose any supported draft length, but it may not substitute a different acceptance target. -- [ ] Verified against the current [MODELS.md](https://github.com/SemiAnalysisAI/InferenceX/blob/main/inferencex-e2e/docs/MODELS.md) that this PR does not submit a deprecated model, scenario, or model-scenario combination. -- [ ] Verified that the model architecture isn't changed with benchmark hacks like using --hf-overrides to skipping indexer for every x layers on models that don't natively support this. As a general rule, we won't accept optimizations that reduces the number of model architecture FLOPs. Anything that makes that same computation run faster is fair game; target/verifier FLOPs at lower precisions is fine, given that the config passes private evals, but this does not permit lowering draft-model or draft-head precision below what ships. As an general north star princple, we should only use optimizations which is used in production by customers that care about accuracy -- [ ] If an company claims that they support vLLM/SGLang as first class LLM inference engines on their hardware, I have verified that the respective vLLM submission made using upstream https://hub.docker.com/u/vllm docker repo, upstream SGLang https://hub.docker.com/u/lmsysorg docker repo. The only exceptions are for new hardware, such as MI455X UALoE72, Vera Rubin NVL72, Rubin NVL8, etc., and for new model architectures where there is an actual reason why vLLM/SGLang does not fundamentally support them yet as supported by vLLM/SGLang community maintainers -- [ ] If an company claims that they support vLLM/SGLang as first class upstream in-tree LLM inference engines on their hardware, I have have verified that the respective vLLM/SGLang submission has been made before additional frameworks (TRT-LLM, ATOM, etc.). The only exceptions are for new hardware, such as MI455X UALoE72, Vera Rubin NVL72, Rubin NVL8, etc., and for new model architectures where there is an actual reason why vLLM/SGLang does not fundamentally support them yet. -- [ ] Verified that every affected vLLM/SGLang production serving configuration in this PR, including Dynamo deployments, is documented in the official [vLLM recipes](https://recipes.vllm.ai/) and/or the [SGLang cookbook](https://docs.sglang.io/cookbook/intro), for both single-node and multi-node aggregated and disaggregated serving. The documentation covers production-useful flags, environment variables, and launch commands (including prefill, decode, and router/frontend commands for disaggregation); InferenceX-only benchmark/harness settings are excluded with reasoning in the additional detail section: - - [ ] I linked the corresponding upstream PR in the [vLLM recipe repo](https://github.com/vllm-project/recipes) or [SGLang cookbook source repo](https://github.com/sgl-project/sglang/tree/main/docs/cookbook) and verified that it is **MERGED** before this InferenceX PR merges. An opened, draft, or closed-without-merge upstream PR does not satisfy this requirement. If the matching recipe was already published, I linked the published recipe/cookbook page in the additional detail section below. -- [ ] Verified that this PR does not patch the inference engine or serving stack — the pinned image must run as shipped. This covers .patch files / git apply / patch, inline patches embedded in benchmark scripts (e.g. a python3/sed heredoc that rewrites installed engine sources before serving), in-place edits of site-packages, monkey-patching, overwriting container files, and installing forked/rebuilt engine wheels on top of the pinned image. The only exception is a patch covered by a filled-out waiver at [docs/waiver/](https://github.com/SemiAnalysisAI/InferenceX/tree/main/inferencex-e2e/docs/waiver)`.md` — named after the PR that introduces the patch and filed in that same PR, stating what is patched, why the unmodified upstream image cannot run this benchmark, the upstream PR/issue link, and the removal plan — which I have linked below in the additional detail section. -- [ ] If this PR uses `append-only: true`, verified that it only adds generated points or recipe variants inside a selected existing config/scenario and existing same-image visual curve: every previously generated point remains present with the same recipe, no prior point is removed or rerun, and every benchmark-affecting change in the complete diff can affect only the corresponding newly appended points (never an existing point), regardless of which file contains it. -- [ ] If any of the above criteria cannot reasonably be satisfied, I have provided additional reasoning below. -- [ ] Reported measured throughput/E2EL Pareto counts and evidence per affected curve (≥5 points strongly recommended). Below 5 or unverifiable: tag a core maintainer for review; recorded admin bypass required before merge. N/A if no curves are affected. [Details](https://github.com/SemiAnalysisAI/InferenceX/blob/main/.github/codeowner-signoff-verify-prompt.md#check-14--pareto-coverage-recommendation-with-admin-exception). - -### Additional detail section: -- insert any additional info here - -Signed: `FILL_IN_GITHUB_USERNAME` -``` -## 各条目中文对照说明 - -1. 已确认在填写此清单时,使用的是 [PR_REVIEW_CHECKLIST.md](https://github.com/SemiAnalysisAI/InferenceX/blob/main/inferencex-e2e/docs/PR_REVIEW_CHECKLIST.md) 的最新版本。 -2. 已确认整体代码质量达到 InferenceX 标准,且不会使代码质量变差。 -3. 已确认该 PR 通过了 PR 验证,并附上能证明这一点的 GitHub Action 工作流链接。 -4. 已确认该 PR 通过了 evals(准确性评测),并附上能证明这一点的 GitHub Action 工作流链接。 -5. 已确认投机解码(speculative decoding)PR 使用 chat template,使接受长度(AL)分布与真实场景对齐。 -6. 已确认所有 draft 模型和 draft head 均按其发布时的默认方式运行:使用随所服务 checkpoint 一同发布的 draft,保持其存储精度,并采用锁定上游镜像的默认加载处理;已在 Additional detail section 中记录 draft 的发布精度与实际运行精度。无论 eval 结果或 AL 如何,提交方不得通过量化、dtype 覆盖、替换 checkpoint 或打补丁将 draft 精度降到该默认值以下。关于"默认"的定义及 MLPerf 对照见[Draft 模型精度](../../CONTRIBUTING_zh.md#draft-模型精度)。 -7. 对 agentic 工作负载:已确认投机解码配置(EAGLE / MTP / draft 模型)启用了模拟合成接受(simulated synthetic acceptance),且接受长度(AL)取值来自 [infx/golden_al_distribution/](https://github.com/SemiAnalysisAI/InferenceX/tree/main/inferencex-e2e/infx/golden_al_distribution) 中该模型、thinking 模式与 draft 长度对应的已提交黄金 AL 曲线。提交可选择任意受支持的 draft 长度,但不得替换为其他接受目标。 -8. 已确认此 PR 对照最新版 [MODELS.md](https://github.com/SemiAnalysisAI/InferenceX/blob/main/inferencex-e2e/docs/MODELS.md),未提交已弃用的模型、场景或模型场景组合。 -9. 已确认模型架构未被基准测试 hack 更改,例如在不原生支持的模型上使用 `--hf-overrides` 每 x 层跳过 indexer。一般规则:不接受减少模型架构 FLOPs 的优化;让同样的计算跑得更快没有问题;target/verifier 的更低精度 FLOPs 也可以,前提是该配置通过私有 evals,但这不允许将 draft 模型或 draft head 的精度降到其发布默认值以下。北极星原则:只使用在意准确性的客户在生产中实际使用的优化。 -10. 如果公司声称在其硬件上将 vLLM/SGLang 作为一等 LLM 推理引擎支持,已确认相应 vLLM 提交使用上游 [vLLM docker 仓库](https://hub.docker.com/u/vllm)、SGLang 提交使用上游 [lmsysorg docker 仓库](https://hub.docker.com/u/lmsysorg)。唯一例外:新硬件(如 MI455X UALoE72、Vera Rubin NVL72、Rubin NVL8 等),以及经 vLLM/SGLang 社区维护者确认上游尚未从根本上支持的新模型架构。 -11. 如果公司声称在其硬件上将 vLLM/SGLang 作为一等上游 in-tree LLM 推理引擎支持,已确认相应 vLLM/SGLang 提交先于其他框架(TRT-LLM、ATOM 等)完成。例外情形同上。 -12. 已确认此 PR 中每个受影响的 vLLM/SGLang 生产服务配置(包括 Dynamo 部署)均已记录在官方 [vLLM recipes](https://recipes.vllm.ai/) 和/或 [SGLang cookbook](https://docs.sglang.io/cookbook/intro) 中,覆盖单节点及多节点的聚合式和分离式推理。文档须包含对生产有用的参数、环境变量和启动命令;分离式部署还须覆盖 prefill、decode 和 router/frontend 命令。仅用于 InferenceX 基准测试或测试框架的设置可以排除,但须在 Additional detail section 中说明理由。已链接对应的上游 PR,并确认其在本 InferenceX PR 合并前已**合并(MERGED)**。处于 open、draft 或未合并关闭状态的上游 PR 不满足此要求。若相应 recipe 已发布,已在 Additional detail section 中链接已发布的 recipe/cookbook 页面。 -13. 已确认该 PR 未对推理引擎或 serving 技术栈打补丁,锁定的镜像必须原样运行。涵盖:.patch 文件 / `git apply` / `patch`、内嵌在基准测试脚本中的行内补丁(例如在启动服务前用 python3/sed heredoc 改写已安装的引擎源码)、就地编辑 site-packages、monkey-patch、覆盖容器文件、以及在锁定镜像之上安装 fork 或重新构建的引擎 wheel。唯一例外:该补丁已由 [docs/waiver/](https://github.com/SemiAnalysisAI/InferenceX/tree/main/inferencex-e2e/docs/waiver)`.md`(以引入补丁的 PR 编号命名,并在同一 PR 中提交)中填写完整的豁免覆盖,写明补丁内容、为何未修改的上游镜像无法运行该基准测试、上游 PR/issue 链接及移除计划,并已在下方 Additional detail section 中给出链接。 -14. 如果 PR 使用 `append-only: true`,已确认它只在所选现有配置/场景和同镜像的现有可视化曲线内新增生成点或配方变体。所有已有点及其配方均保留,不删除或重跑旧点;完整 diff 中所有影响基准测试的改动,无论位于哪个文件,都只会作用于对应新增点,不能影响已有点。 -15. 如果上述任何条目无法合理满足,已在下方提供额外说明。 -16. 已报告每条受影响曲线的吞吐量/E2EL Pareto 实测点数及证据,强烈建议 ≥5 个点。少于 5 个或无法核实:提醒一位核心维护者审阅,合并前须记录管理员例外。无曲线受影响时可填 N/A。详见[验证器说明](../../.github/codeowner-signoff-verify-prompt.md#check-14--pareto-coverage-recommendation-with-admin-exception)。 - -## 示例 - -image - - -image diff --git a/inferencex-e2e/docs/agentx-standalone.md b/inferencex-e2e/docs/agentx-standalone.md index 758381ac39..7aa3ea423a 100644 --- a/inferencex-e2e/docs/agentx-standalone.md +++ b/inferencex-e2e/docs/agentx-standalone.md @@ -1,11 +1,5 @@ # Run AgentX-Harness Standalone -
- -**English** | [中文](agentx-standalone_zh.md) - -
- Run the AgentX client against an already-running OpenAI-compatible server. ## Install diff --git a/inferencex-e2e/docs/agentx-standalone_zh.md b/inferencex-e2e/docs/agentx-standalone_zh.md deleted file mode 100644 index 4c53dfdead..0000000000 --- a/inferencex-e2e/docs/agentx-standalone_zh.md +++ /dev/null @@ -1,71 +0,0 @@ -# 独立运行 AgentX-Harness - -
- -[English](agentx-standalone.md) | **中文** - -
- -对已运行的 OpenAI 兼容服务执行 AgentX 客户端。 - -## 安装 - -安装 Git 和 [uv](https://docs.astral.sh/uv/getting-started/installation/) 后, -克隆测试工具并检出锁定的 `agentx-v1.0.6` 发布提交。其 CLI 名为 `aiperf`。 - -```bash -git clone --filter=blob:none --no-checkout https://github.com/SemiAnalysisAI/agentx-harness.git -cd agentx-harness -git checkout --detach 89b21867872a5bbc4b0676bf5005c404da5e9f94 -uv venv --python 3.11 .venv-agentx -uv pip install --python .venv-agentx/bin/python -e . 'datasets>=4.7.0' -source .venv-agentx/bin/activate -``` - -## 运行 - -```bash -set -eo pipefail -SERVER_URL="http://127.0.0.1:8000" -SERVED_MODEL_NAME="moonshotai/Kimi-K3" -TOKENIZER="moonshotai/Kimi-K3" -DATASET="semianalysis_cc_traces_weka_062126" -CONC=8 -OUTPUT_DIR="$PWD/results/agentx-c${CONC}-$(date -u +%Y%m%dT%H%M%SZ)" - -mkdir -p "$OUTPUT_DIR" -aiperf profile \ - --scenario agentx \ - --url "$SERVER_URL" --endpoint /v1/chat/completions \ - --model "$SERVED_MODEL_NAME" --tokenizer "$TOKENIZER" \ - --tokenizer-trust-remote-code \ - --concurrency "$CONC" \ - --public-dataset "$DATASET" \ - --output-artifact-dir "$OUTPUT_DIR/aiperf_artifacts" \ - 2>&1 | tee "$OUTPUT_DIR/aiperf.log" -``` - -`agentx` 预设提供一小时测量窗口、每条 lane 十个预热请求,以及共享的报告和运行时设置。 -显式 CLI 参数和 `AIPERF_*` 环境变量优先于预设默认值。 -模型、tokenizer、数据集、并发和输出路径仍由调用方指定;只有 tokenizer 需要自定义代码时,才需使用 `--tokenizer-trust-remote-code`。 - -默认随机种子为 **42**。复现 AgentX 结果时请保留该种子;也可以传入 `--random-seed 123` 使用其他种子。 - -测量之外还需数据集准备、预热和请求排空时间。 -扫描并发时,每个 `CONC` 值都必须重启服务并使用新的输出目录。 -不要清空缓存或在不同并发点之间复用正在运行的服务。复现结果时,使用目标 recipe 的测量时长和预热设置。 - -服务提供指标端点时,可添加 `--server-metrics "${SERVER_URL}/metrics"`。 - -## 可选会话亲和性参数 - -DP-attention 运行需要路由器会话亲和性时,在 `aiperf profile` 前导出以下变量。 -它们添加请求头,不替换 `X-Correlation-ID`。 - -```bash -# Adds X-Dynamo-Session-ID; subagents also get X-Dynamo-Parent-Session-ID. -# Only this option sends the parent ID, preserving forked-agent lineage. -export AIPERF_HTTP_X_DYNAMO_SESSION_ID_FROM_CORRELATION_ID=true -# Also sends X-Session-ID, if a front-end router needs it. -export AIPERF_HTTP_X_SESSION_ID_FROM_CORRELATION_ID=true -``` diff --git a/inferencex-e2e/docs/architecture.md b/inferencex-e2e/docs/architecture.md index be1a0d71db..8e39bf2bf8 100644 --- a/inferencex-e2e/docs/architecture.md +++ b/inferencex-e2e/docs/architecture.md @@ -1,11 +1,5 @@ # Pipeline Architecture -
- -**English** | [中文](architecture_zh.md) - -
- This page explains how a declared benchmark becomes a validated job, a runtime result, a GitHub Actions artifact, and finally a row consumed by InferenceX-app. It describes boundaries and invariants. The linked implementation remains authoritative for field-level behavior. diff --git a/inferencex-e2e/docs/architecture_zh.md b/inferencex-e2e/docs/architecture_zh.md deleted file mode 100644 index e3b86c31eb..0000000000 --- a/inferencex-e2e/docs/architecture_zh.md +++ /dev/null @@ -1,424 +0,0 @@ -# 流水线架构 - -
- -[English](architecture.md) | **中文** - -
- -本页说明声明的基准测试如何转化为经过验证的作业、运行时结果、GitHub Actions 工件,并最终成为 InferenceX-app 使用的一行数据。本页描述各层边界和不变量。字段级行为仍以链接的实现为准。 - - -仓库按 `inferencex-e2e/`、`collectivex/`、`operatorx/`、`shared/` 和 `experimental/` 划分。本文中的路径和 shell 命令均相对 `inferencex-e2e/`;Python 打包元数据和 `.python-version` 位于该项目目录。GitHub 工作流仍位于仓库根目录。 - - -## 页面索引 - -1. [源码映射](#源码映射) -2. [端到端流程](#端到端流程) -3. [归属边界](#归属边界) -4. [阶段 1:配置与触发选择](#阶段-1配置与触发选择) -5. [阶段 2:验证与矩阵生成](#阶段-2验证与矩阵生成) -6. [阶段 3:工作流分派](#阶段-3工作流分派) -7. [阶段 4:启动器与运行时执行](#阶段-4启动器与运行时执行) -8. [阶段 5:基准测试与评测输出](#阶段-5基准测试与评测输出) -9. [阶段 6:工件收集与交接](#阶段-6工件收集与交接) -10. [阶段 7:InferenceX-app 摄取](#阶段-7inferencex-app-摄取) -11. [权威来源决策](#权威来源决策) -12. [追踪并验证一项结果](#追踪并验证一项结果) -13. [停止条件](#停止条件) - -## 源码映射 - -### InferenceX 生产方 - -| 权威来源 | 职责 | -| --- | --- | -| [`configs/CONFIGS.md`](../configs/CONFIGS.md) | 面向人员的主配置和运行器配置契约 | -| [`configs/nvidia-master.yaml`](../configs/nvidia-master.yaml)、[`configs/amd-master.yaml`](../configs/amd-master.yaml) | 声明式的模型、镜像、框架、场景、拓扑和搜索空间意图 | -| [`configs/runners.yaml`](../configs/runners.yaml) | 调度标签、具体运行器名称,以及生成过程和启动器读取的各集群记录(`clusters:`) | -| [`perf-changelog.yaml`](../perf-changelog.yaml) | 以仅追加方式选择要针对某项变更运行的配置键 | -| [`infx/matrix/validation.py`](../infx/matrix/validation.py) | 强制执行的 Pydantic 模式和跨字段不变量 | -| [`infx/matrix/generate.py`](../infx/matrix/generate.py) | 搜索空间展开、默认值、过滤器、派生元数据、运行器解析和评测选择 | -| [`infx/matrix/plan.py`](../infx/matrix/plan.py) | 变更日志选择、配置键展开、追加模式比较、矩阵分桶及最终验证;通过 `python -m infx.matrix.plan` 运行 | -| [`.github/workflows/run-sweep.yml`](../../.github/workflows/run-sweep.yml) | PR 触发策略、矩阵扇出和收集依赖 | -| [`.github/workflows/merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) | 合并时复用验证、变更日志元数据和跨仓库摄取分派 | -| [`.github/workflows/benchmark-tmpl.yml`](../../.github/workflows/benchmark-tmpl.yml)、[`.github/workflows/benchmark-multinode-tmpl.yml`](../../.github/workflows/benchmark-multinode-tmpl.yml) | 可复用作业输入契约、环境映射、启动器调用、结果检查和单作业上传 | -| [`infx/launch/`](../infx/launch) | `python -m infx.launch run`:根据运行器名称解析集群、选择启动路径(驱动)、工作负载策略、信号安全的清理以及工件暂存 | -| [`infx/clusters/`](../infx/clusters)、[`infx/launch/backends/`](../infx/launch/backends) | 类型化集群记录(每个调度器一个设置模型),以及运行容器、跟踪作业的调度器后端(目前为使用 Pyxis squash 镜像的 Slurm) | -| [`runners/srt-slurm/`](../runners/srt-slurm) | srt-slurm 主机设置 hook 和临时上游补丁 | -| [`infx/bench/`](../infx/bench) | 在容器内运行的 `python3 -m infx.bench` 命令(`wait`、`fixed-seq`、`agentic`、`eval`),负责服务器就绪检查、基准测试客户端、AgentX 重放和评估 | -| [`benchmarks/`](../benchmarks) | 特定于框架和拓扑的服务器与客户端命令 | -| [`infx/github.py`](../infx/github.py) | 工作流操作共用的 GitHub REST、分页和评论表态基础操作 | -| [`infx/workflows/`](../infx/workflows) | 复用命令解析、授权查找、源 Run 验证及表态反馈;现有复用 CLI 保持兼容 | -| [`infx/results/`](../infx/results) | 可导入的结果构建函数、组件元数据解析和功耗指标转换;通过 `python -m infx.results.fixed_sequence` 处理固定序列结果 | -| [`.github/workflows/collect-results.yml`](../../.github/workflows/collect-results.yml)、[`.github/workflows/collect-evals.yml`](../../.github/workflows/collect-evals.yml) | 运行级基准测试和评测工件聚合 | - -### InferenceX-app 使用方 - -这些是跨仓库链接,因为数据库和展示侧契约由 InferenceX-app 负责。 - -| 权威来源 | 职责 | -| --- | --- | -| [`.github/workflows/ingest-results.yml`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/.github/workflows/ingest-results.yml) | 接收 `ingest-results` 和 `ingest-agentic-results`,准备工件、执行迁移、摄取、验证并使缓存失效。智能体摄取使用更大的运行器和更长的超时时间 | -| [`packages/db/src/prepare-ci-artifacts.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/prepare-ci-artifacts.ts) | 选择并下载源运行工件,包括复用扫描元数据 | -| [`packages/db/src/ingest-ci-run.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/ingest-ci-run.ts) | 编排工作流运行、基准测试、评测、样本、追踪、统计、可用性和变更日志的摄取 | -| [`packages/db/src/etl/benchmark-mapper.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/etl/benchmark-mapper.ts) | 将基准测试工件行映射为面向数据库的规范形态 | -| [`packages/db/src/etl/eval-mapper.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/etl/eval-mapper.ts) | 映射聚合评测工件和按配置划分的评测工件 | -| [`packages/db/src/etl/normalizers.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/etl/normalizers.ts) | 解析规范模型、硬件、框架和精度 | -| [`packages/db/src/etl/skip-tracker.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/etl/skip-tracker.ts) | 记录未映射或被拒绝的输入,避免静默丢失 | -| [`packages/app/src/app/api/v1/invalidate/route.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/app/src/app/api/v1/invalidate/route.ts) | 在摄取通过验证后使应用缓存失效 | -| [`packages/app/src/app/api/v1/benchmarks/route.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/app/src/app/api/v1/benchmarks/route.ts) | 向仪表板提供持久化的基准测试行 | -| [InferenceX-app 架构](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/docs/architecture.md)、[数据流水线](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/docs/data-pipeline.md) | 使用方的设计理由、缓存策略、ETL 和前端转换 | - -## 端到端流程 - -```mermaid -flowchart LR - A[主 YAML 和 runners.yaml] --> B[Pydantic 验证] - P[perf-changelog 新增项] --> C[infx.matrix.plan] - B --> D[infx.matrix.generate] - C --> D - D --> E[经过验证的 JSON 矩阵] - E --> F[run-sweep.yml 扇出] - F --> G[可复用基准测试工作流] - G --> H[infx.launch 驱动] - H --> I[配方或脚本与 infx.bench 命令] - I --> J[基准测试、评测、日志、指标、追踪] - J --> K[单作业 GitHub 工件] - K --> L[运行级聚合工件] - L --> M[merge-ingest.yml 向 InferenceX-app 分派] - M --> N[准备并下载工件] - N --> O[映射、规范化并向上插入数据库行] - O --> Q[验证数据库并刷新最新基准测试] - Q --> R[使缓存失效] - R --> S[仪表板 API 和 UI] -``` - -关键交接点是具有 JSON 形态的契约。主 YAML 被读取到经过验证的 Python 模型中。生成器发出矩阵 JSON。可复用工作流将每一行矩阵映射为有类型的工作流输入和环境变量。运行时脚本写入 JSON 文件。GitHub 工件名称向下游 TypeScript 摄取过程标识这些文件。 - -没有任何单个文件负责整条流水线。正确性来自每个交接点上的一致性。 - -## 归属边界 - -| 层 | 负责 | 不负责 | -| --- | --- | --- | -| 主配置 | 所需的基准测试标识、镜像、框架、场景、支持的拓扑和搜索空间 | Shell 命令、物理挂载、工件解析或数据库规范化 | -| 验证 | 接受的字段名称、类型以及拓扑或作用域不变量 | 运行哪个变更日志条目、调度优先级或运行时功能支持 | -| 矩阵生成器 | 展开为可执行点、默认值、派生名称和长度、评测标记以及运行器解析 | 容器启动或基准测试实现 | -| 变更日志处理器 | 选择发生变更的配置键,并将其分组到工作流矩阵桶中 | 每项配置的定义或其运行时行为 | -| 扫描工作流 | PR 触发和标签策略、金丝雀与 PR 复用门控策略、矩阵扇出和依赖门控 | 特定于机群的启动细节、摄取分派或数据库映射 | -| 合并摄取工作流 | 合并时复用验证、变更日志元数据上传和唯一一次摄取分派 | 基准测试执行或数据库映射 | -| 可复用工作流 | 稳定的作业输入和环境契约、自托管调度、启动器调用、文件存在性检查和工件上传名称 | 模型路径选择或框架 CLI 标志 | -| 启动器(`infx.launch`) | 依据集群记录的物理运行器行为、模型暂存、挂载、容器、Slurm 分配,以及选择驱动、运行时脚本或外部方案 | 逻辑搜索空间策略或数据库模式 | -| 基准测试和评测代码 | 服务器标志、客户端负载、评分、可供聚合的文件和运行时清理 | 请求了哪些矩阵点或数据行如何在仪表板中显示 | -| 工件收集器 | 运行级打包和稳定的聚合工件名称 | 对基准测试结果进行语义重解释 | -| InferenceX-app ETL | 规范化、幂等持久化、跳过报告、可用性、追踪旁路文件和数据库验证 | 服务引擎如何启动或生产方应调度哪些点 | -| InferenceX-app API 和 UI | 缓存生命周期、查询行为、客户端转换和展示 | 生产方配置和基准测试执行 | - -跨越边界的字段不会自动在下一层中成为权威来源。例如,主条目中的 `framework` 是权威的生产方元数据。启动器仍然必须将该值路由到兼容的脚本。随后,InferenceX-app 会将其规范化为数据库中的规范键。这些是不同的职责,而不是同一功能的重复实现。 - -## 阶段 1:配置与触发选择 - -主 YAML 文件描述可能执行的工作。配置键将模型、镜像、模型前缀、精度、框架、运行器标签、场景定义以及一个或多个搜索空间条目绑定在一起。[`configs/runners.yaml`](../configs/runners.yaml) 解析调度标签,其中的 `clusters:` 记录提供生成时使用的节点形状,以及启动器使用的 Slurm、镜像、路径和模型信息。 - -主条目在被选中之前不会生效。在由变更日志驱动的路径上,[`perf-changelog.yaml`](../perf-changelog.yaml) 的新增内容会选择确切的配置键或键模式。[`infx.matrix.plan`](../infx/matrix/plan.py) 仅读取基础引用与头部引用之间新增的变更日志行。它会验证每个新增条目,针对已加载的主配置展开键模式,并为选中的键调用矩阵生成器。 - -这种拆分有两个结果。 - -1. 主文件是受支持工作的目录。变更日志是审计记录和触发选择,而不是配置内容的另一个副本。 -2. 如果编辑主条目时没有添加匹配的变更日志条目,则不会通过 `run-sweep.yml` 调度该变更,因为其路径触发器监视的是 `perf-changelog.yaml`。 - -`infx.matrix.plan` 会在发出的 JSON 中保留变更日志元数据。工作流随后将其作为 `changelog-metadata` 上传,使 InferenceX-app 能够将持久化的数据行与所选变更关联起来。 - -## 阶段 2:验证与矩阵生成 - -共享 Python 实现位于`inferencex-e2e/` 下的 `infx` 包中。`infx.matrix.generate` 负责矩阵生成,`infx.matrix.validation` 负责模式校验。Python 调用方应通过这些规范路径导入;后续领域模块可在需要时加入 `infx`。 - -其余 Python 工具按职责划分: - -| 包 | 职责 | -| --- | --- | -| `infx.workflows` | 优先级评分、变更日志验证及合并准备、复用验证、恢复和运行统计 | -| `infx.results` | 结果收集、比较、文件命名、功耗、绘图及 AgentX 产物处理 | -| `infx.evals` | 评测适配器、分数验证、任务 YAML、样例数据和运行时补丁 | -| `infx.bench_serving` | 基准测试客户端及其请求、编码和导出辅助函数 | -| `infx.datasets` | AgentX 轨迹采样、转换、数据集构建及分布图 | -| `infx.klaud` | Klaud 编排、生命周期、GitHub/API 适配器和模式 | - -从 `inferencex-e2e/`使用 `python -m infx..` 运行命令。依赖仍由各命令分别管理;导入 `infx` 不会加载基准测试客户端或评测依赖。`utils/` 下的 Python 兼容包装文件已删除。数据集工具、AgentX 聚合与分析、评测适配器与补丁,以及基准测试客户端辅助模块应使用规范的 `infx` 路径。评测文档位于 `infx/evals/EVALS.md`,评测测试位于 `infx/tests/evals/`。其他行为测试位于 `infx/tests/`。`utils/` 下仅保留运行器配置 Shell 脚本(`utils/runner_setup/`)及外部子模块 `aiperf` 和 `srt-slurm`。 - -复制到隔离环境中的评测适配器和补丁使用 `infx/evals` 下的实际文件,因此仍可独立运行。可信工作流辅助模块会明确选择工具代码所在的检出目录。固定序列处理、评测分数验证和单节点 AgentX 结果验证步骤使用单独检出的工作流修订版中的包,并以被测检出目录为工作目录。仅评测作业也会准备工具代码和 Python 3.12。因此,历史被测修订版无需包含这些辅助模块。分数阈值取自工作流修订版随包提供的 `infx/evals/thresholds.yaml`。 - -默认仓库路径定义在 [`infx/config.py`](../infx/config.py) 中。配置常量从 `infx.config` 导入,模式从 `infx.matrix.validation` 导入。包的 `__init__.py` 文件保持精简。 - -从 `inferencex-e2e/` 或安装好的包运行 `python -m infx.matrix.plan` 进行变更日志规划,运行 `python -m infx.workflows.validate_perf_changelog` 进行验证。矩阵生成使用 `python -m infx.matrix.generate` 入口,并指定 `full-sweep` 或 `test-config` 子命令。其他修订版的配置只由该修订版自身的工具解释,绝不由当前代码解析,因此配置格式变化不会破坏读取历史修订版的流程:[`infx.matrix.revision`](../infx/matrix/revision.py) 通过 Git 快照中该修订版自身的生成器处理 append-only 基准修订版和 Klaud 基线产出者,并通过被测检出目录自身的规划器处理摄取恢复和可信变更日志调度。 - -使用当前工具代码的工作流直接调用 `infx` 模块,测试也导入规范模块。可信调度和结果处理通过 `PYTHONPATH` 和 Python 的 `-P` 选项明确指定工具代码所在的检出目录,同时仍以目标检出目录作为工作目录读取输入。每个修订版工具子进程都会将 `INFERENCEX_REPOSITORY_ROOT` 设为该修订版的目录树,确保配方数据来自同一修订版;其他调用方仍默认使用源码检出目录。 - -`infx.matrix.revision` 选择修订版的生成器或规划器(其 `infx` 模块,或该模块取代的遗留脚本),运行时将该修订版的目录树置于 `PYTHONPATH` 中继承路径之前,必要时也包含遗留脚本所在目录,因此启用 `PYTHONSAFEPATH` 时也不会误用其他已安装检出版本的代码。手动和可信 e2e 调度以 `python -m infx.matrix.revision {generate,plan} CHECKOUT ARGS...` 的形式调用它;性能分析和 OperatorX 枚举仍各自保留一份生成器选择逻辑。 - -`infx.matrix.plan.build_plan(changelog_data, base_ref=..., head_ref=...)` 返回完整扫描的已验证 `ChangelogMatrixEntry`,统一负责条目优先级、基准测试与评测各自的场景覆盖、裁剪、指纹及输出分桶。当前主配置文件只加载一次,运行器元数据在首次生成时加载一次;每组选中的配置直接调用 `infx.matrix.generate.generate_config_matrix`。当前输入来自传入的路径(默认为检出目录中的路径),`head_ref` 仍用作来源元数据。规划过程假设这些文件在本次操作期间保持稳定。 - -`generate_config_matrix` 接受已验证的配置和运行器字典,以及明确的评测模式(`default`、`none`、`subset`、`all` 或 `smoke`),与生成器 CLI 共用展开和评测选择逻辑,包括读取仓库中已提交的配方以确定物理节点数。Smoke 保留最低并发吞吐量测试,并单独保留规范选出的代表性评测。其 JSON 规范化保留旧有值转换和拒绝语义,并防止不同生成批次共享嵌套结果对象。规划失败时不会发布不完整矩阵;CLI 保留拒绝状态和诊断消息,堆栈帧则反映新的模块位置。 - -`expand_full_sweep(master_config, runner_data, options=FullSweepOptions(...))` 提供无需构造 `argparse` 命名空间的完整扫描展开接口。两个命令共用配置和场景遍历及数据行构造逻辑,同时明确保留各自的选择规则。完整扫描过滤具体运行器节点;按配置键展开还接受匹配的调度标签,并对节点去重。固定序列的单节点并发范围先按上下界裁剪再展开,多节点范围和显式列表则先展开再过滤。智能体场景的上下界仅过滤已有并发点。展开接口返回尚未选择评测的数据行;评测或裁剪策略由 `select_matrix_evals` 应用。现有 CLI 命令及接受命名空间的 Python 兼容入口保持不变。 - -对 append-only 基准修订版和 Klaud 基线产出者,`infx.matrix.revision.snapshot` 从同一个 Git 修订提取配置(位于 `configs/`,迁移到项目根目录之前位于 `.github/configs/`)、多节点配方、旧入口及 `infx` 包(若该修订包含它)。包迁移前的修订运行其原有独立生成器;迁移后的修订使用自身的包代码。当前工作区中的源码和配置绝不替代已提交的输入,规划器只将基准修订版条目作为原始 YAML 读取,用于限定 append-only 范围。快照子进程保持隔离,提取的输入在操作结束时删除,包括失败路径。 - -[`validation.py`](../infx/matrix/validation.py) 在生成之前验证主文件和运行器数据。其严格模型负责接受的别名和跨字段规则。例如,互斥的并发形式、单节点与多节点形态、组件元数据作用域、预填充与解码硬件配对,以及智能体场景的集群标签要求。 - -随后,[`infx.matrix.generate`](../infx/matrix/generate.py) 将经过验证的意图展开为数据行。它负责以下决策: - -- 从范围或列表生成具体并发点; -- 默认并行度值; -- 派生实验名称和序列长度字段; -- 单节点和多节点工作节点形态; -- 智能体时长和 KV 卸载元数据; -- 运行器节点过滤和硬件派生值; -- 常规评测子集、`--all-evals`、`--evals-only` 和 `--no-evals` 行为。 - -`infx.matrix.plan` 将生成的数据行放入不同的 JSON 桶中。当前桶包括按序列族划分的 `single_node`、按序列族划分的 `multi_node`、`evals`、`agentic_evals`、`multinode_evals`、`multinode_agentic_evals` 和 `changelog_metadata`。它会在打印最终对象之前使用 `ChangelogMatrixEntry` 对其进行验证。 - -发出的矩阵是可执行的 CI 契约,但不是可供编辑的持久化来源。应修改上游主配置、验证器或生成器,然后重新生成矩阵。 - -## 阶段 3:工作流分派 - -[`.github/workflows/run-sweep.yml`](../../.github/workflows/run-sweep.yml) 是 PR 扫描的编排边界。 - -1. 它仅由修改 `perf-changelog.yaml` 的符合条件的拉取请求事件触发。推送到 `main` 时改为运行 [`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml);参见[阶段 6](#阶段-6工件收集与交接)。 -2. 它验证新增的变更日志内容并应用 PR 标签策略。 -3. 其设置作业运行 `python -m infx.matrix.plan`,然后通过 [`infx/workflows/ci_priority.py`](../infx/workflows/ci_priority.py) 应用 CI 优先级元数据。 -4. 它将整个矩阵作为 `search-space-config` 作业输出公开。 -5. 矩阵作业使用相应的桶,并调用 `benchmark-tmpl.yml` 或 `benchmark-multinode-tmpl.yml`。 -6. 基准测试、评测和智能体数据行使用独立的扇出作业,因为它们所需的输入形态不同。 -7. 收集过程会等待相关作业。PR 运行只上传工件,从不分派摄取;合并后由 `merge-ingest.yml` 分派对被复用运行工件的摄取。 - -可复用工作流在矩阵键与运行时环境变量之间构成显式适配器。单节点和多节点调用方通过一个 JSON `config` 输入传递已验证的 `infx.matrix` 数据行;`benchmark-tmpl.yml` 和 `benchmark-multinode-tmpl.yml` 负责将其映射为 `MODEL_PREFIX`、`DCP_SIZE`、`SPEC_DECODING` 等变量。因此,新增配方字段时,只需修改模式/生成器及使用该字段的模板/运行时代码,无需在每个调用方重复添加转发字段。模板显式读取已知字段,不会将任意 JSON 键导出为环境变量。 - -[`infx/workflows/benchmark_schema.py`](../infx/workflows/benchmark_schema.py) 通过扩展已有矩阵模型定义单节点和多节点工作流模式。Sweep 和手动运行的准备作业在添加优先级信息和发布作业输出之前验证数据行,因此非法输入会在 GPU 扇出前失败。验证会拒绝缺失的必填字段、未知键、错误的 JSON 类型、无效的元数据或拓扑、空并发批次或非正并发值,以及计划分组中的场景或拓扑错配。计划中的基准分组使用 `agentic`,数据行仍使用 `scenario-type: agentic-coding`;验证以工作流实际读取的分组为准。合法 JSON 原样通过。作业输出仅包含每条配方数据行的一份副本;模板在使用时生成名称和环境变量,不扩大矩阵载荷。仅用于验证的默认值允许旧数据行省略 `pp`、`dcp-size` 和 `pcp-size`,不会将这些默认值写入工作流输入。即使被测 checkout 较旧,手动运行也使用工作流工具 checkout 中的验证器。新增调用方也必须执行此预检;可复用模板本身只负责解析 JSON。 - -调度、checkout 选择和执行覆盖选项仍使用显式工作流输入。单节点 `dp-attn` 也保留为布尔输入,以维持 GitHub 的类型检查。AgentX 的序列长度仍为零,旧版本缺失字段仍保留原有的空字符串行为。JSON 由 GitHub Actions 在 checkout 前解析,因此被测旧提交无需新增辅助程序。多节点保留显式的 `node-count`、并发批次/评测覆盖和 CPU DRAM 覆盖输入;手动 AgentX 运行保留原有的内存默认值。性能分析工作流继续使用现有接口。 - -矩阵中的 `runner` 值也会驱动 `runs-on`。分配自托管运行器后,模板会把具体的 `${{ runner.name }}` 导出为 `RUNNER_NAME`,并在被测项目根目录运行: - -```bash -"$INFERENCEX_LAUNCH_PYTHON" -m infx.launch run -``` - -`infx.launch` 会把运行器解析到 `configs/runners.yaml` 中恰好一个 `cluster:` 标签;不在任何集群标签中或同时出现在多个标签中的运行器会在分配资源前失败。`INFERENCEX_LAUNCH_PYTHON` 是一个未激活、只含包依赖的 Python 3.12 环境,因此被启动的作业会继承运行器的 `PATH`,且不带 `VIRTUAL_ENV`。 - -第一个清理步骤在 checkout 之前运行:用普通的 `scancel` 取消该运行器的 Slurm 作业,并等待 `squeue` 不再列出它们。这样,失效运行器遗留的作业不会写入新的 workspace,而且这一步不依赖 Python。作业结束后它会再运行一次。启动器 Python 就绪后,工作流会从工作流版本的工具 checkout 中运行 `python -m infx.launch cleanup` 作为第二遍清理,在启动前和作业结束后各一次:取消该用户名为 `RUNNER_NAME` 或 `inferencex-RUNNER_NAME` 的 Slurm 作业,并等待它们离开队列。两遍清理都会取消这两种名称的作业。srtctl 以 `inferencex-RUNNER_NAME` 提交作业,因为其他仓库共用这些物理运行器名称,并会取消以其命名的作业。 - -`infx.github` 负责共享 REST、分页及评论表态基础操作。`infx.workflows.reuse` 负责复用选择和验证,`infx.workflows.reuse_comment` 负责评论表态反馈。两者均可作为包模块执行。这些辅助模块仅依赖标准库。 - -## 阶段 4:启动器与运行时执行 - -[`infx.launch`](../infx/launch) 将逻辑作业元数据适配到某个物理集群。它解析工作流环境([`LaunchRequest`](../infx/launch/request.py))和集群记录,再由 [`launch_path`](../infx/launch/policy.py) 决定运行哪个驱动。记录中的 `scheduler` 指定后端([`infx/launch/backends/`](../infx/launch/backends),接口见 `base.py`);后端在首次使用时才导入,因此读取记录不会导入任何启动代码。需要特定调度器的驱动在其他调度器的集群上会在开始任何工作前失败: - -| 驱动 | 运行内容 | -| --- | --- | -| [`drivers/srt/`](../infx/launch/drivers/srt) | 单节点和多节点 srt-slurm 方案(`SRT_RECIPE`、`CONFIG_FILE`),包括集群维护的 B200 Nscale 通道;仅限 Slurm | -| [`drivers/script.py`](../infx/launch/drivers/script.py) | 带显式 `BENCH_SCRIPT_OVERRIDE` 的单节点运行,例如 SPEED-Bench 采集脚本:通过后端接口运行一个容器,适用于任何后端;其他调度器上的集群只运行这个驱动 | - -根据驱动不同,启动器可能会: - -- 将可移植模型 ID 解析为集群某个卷中已暂存的检查点(`clusters..models` 和调度器的 `volumes`); -- 按后端的方式暂存容器镜像(在 Slurm 上为 `clusters..slurm.squash` 中的 Pyxis squash 缓存;集群没有该缓存时直接使用镜像仓库镜像); -- 分配 Slurm 节点并生成作业本地的 srt-slurm 配置; -- 选择单节点脚本、多节点包装器或已签入的外部方案; -- 将工作流环境传入运行时容器或分配环境; -- 跟踪作业日志、核验分配的最终状态并暂存结果。 - -srt-slurm 配方和 [`benchmarks/`](../benchmarks) 下的脚本负责实际的引擎命令。各通道共用的客户端逻辑以 `python3 -m infx.bench ` 的形式在服务容器内运行,代码位于 [`infx/bench/`](../infx/bench)。其命令包括 `wait`(服务器就绪检查)、`fixed-seq`(服务基准测试客户端)、`agentic`(AgentX 重放)和 `eval`(lm-eval 与厂商评估运行器)。这些命令只依赖标准库并兼容 Python 3.10,从环境变量或命令行参数读取输入,并写出收集器读取的产物文件名。配方通过薄封装脚本调用它们,例如 [`benchmarks/srt_agentic.sh`](../benchmarks/srt_agentic.sh),以及 `benchmarks/single_node/` 和 `benchmarks/multi_node/` 下的 `srt_fixed_sequence.sh` 与 `srt_eval.sh`。Bash 调用方使用 [`benchmarks/check_env.sh`](../benchmarks/check_env.sh) 中的 `check_env_vars` 校验必需输入。 - -这一边界是有意设计的:主配置保持可移植且便于审查,启动机制保存在集群记录中(见[下文](#启动机制保存在集群记录中)),框架标志保持靠近基准测试方案,以便针对相应引擎进行测试。收到 `SIGINT`、`SIGTERM` 或 `SIGHUP` 时,启动器会先运行已注册的清理(例如取消分配),再以 128 加信号编号退出;第一个非零的工作负载退出码优先于清理失败。 - -不要将 YAML 被接受视为能够执行的证明。某个字段可能有效且已发出,但如果工作流适配器、启动器或基准测试脚本未使用它,该字段仍可能被忽略。 - -## 阶段 5:基准测试与评测输出 - -单节点模板根据实验标识、精度、框架、拓扑、解聚、推测解码、并发度和具体运行器计算稳定的 `RESULT_FILENAME`。启动器和基准测试代码必须以该标识写入预期文件。 - -对于固定序列吞吐量作业,工作流要求存在 `.json`,随后运行 [`infx/results/fixed_sequence.py`](../infx/results/fixed_sequence.py),并将 `agg_.json` 作为 `bmk_` 上传。 - -### 复用与扩展结果处理 - -[`infx.results.fixed_sequence.build_result`](../infx/results/fixed_sequence.py) 接收已加载的基准测试映射和显式传入的环境变量映射,返回聚合结果字典,不读取进程环境,也不执行文件 I/O。库调用方无需提供 `RESULT_FILENAME`。现有 CLI 会验证环境变量、读取原始工件、调用构建函数、写入聚合结果,并对多节点结果按照原有的尽力处理或 `REQUIRE_POWER` 策略执行功耗聚合。 - -```python -from infx.results.fixed_sequence import build_result - -result = build_result(raw_benchmark, runtime_env) -``` - -新增格式应在 `infx/results/` 下提供带类型标注的构建函数,接收该格式所需的输入并返回字典。通过普通函数调用组合共享转换;文件查找、环境默认值、错误呈现和序列化由该格式的 CLI 适配器负责。现有 AgentX 拓扑及请求和服务器指标处理保留各自的策略。 - -[`infx.results.agentic.build_result`](../infx/results/agentic/__init__.py) 负责构建 AgentX 聚合结果,包括请求指标、后端选择、服务器指标和每 GPU 吞吐量。它接收已加载的 AIPerf 请求记录、profile 和服务器指标映射,以及显式传入的环境变量映射。可选的 `traces` 提供声明数据集中的原始轨迹对象,`server_logs` 的每个元素对应一个已解码的日志文件头。构建函数不打开文件,也不读取进程环境;返回的指标未经舍入,输入不会被修改,但结果中的数据集和请求统计映射仍与输入共享。 - -```python -from infx.results.agentic import build_result - -result = build_result(records, profile, server_metrics, runtime_env, - traces=trace_objects, server_logs=log_texts) -``` - -现有的 `python -m infx.results.agentic.process_agentic_result` 命令继续负责工件查找、请求过滤与统计、轨迹缓存查找、有大小上限的日志读取、舍入、诊断信息和输出文件写入。它以惰性迭代器提供轨迹和日志,确保元数据校验仍先于轨迹读取,且后端只读取自身需要的日志。请求与服务器指标算法及后端优先级由包内代码统一负责。数据集匹配、缓存优先级和快照歧义处理保留在 CLI 的共享工件加载器中,功耗适配器也使用该加载器。内部 Python 导入改用 `infx.results.agentic`;命令路径、环境变量和工件模式保持不变。 - -当前处理路径共享以下辅助工具: - -- [`parse_component_metadata`](../infx/results/metadata.py) 接收原始 JSON 值和诊断标签。调用方选择 `version` 是否可省略,以及无效输入应抛出 `ValueError` 还是 `SystemExit`,从而保留现有契约。 -- [`Parallelism`](../infx/results/topology.py) 共享 GPU 数量计算、并行度结果字段,以及没有独立解码 GPU 时的字段规范化。固定序列结果继续使用显式分配的 GPU 数量,AgentX 则根据 worker 拓扑推导数量。各调用方保留自己的环境默认值、验证顺序、错误处理和吞吐量分母。 -- [`with_power_metrics`](../infx/results/power/__init__.py) 返回替换了指定指标族的副本,移除旧的有效性原因,并验证、舍入新指标。调用方提供指标键和模式版本,再自行写入工件及验证附属文件。其他指标族因此可以直接复用该转换,无需修改其实现。 - -功耗遥测处理引擎也位于 [`infx.results.power`](../infx/results/power):`multinode.run` 验证 srt-slurm 工件包。其基准窗口解析、单设备能量积分、聚合结果替换及审计序列化位于 `common.py`。固定序列及 AgentX 适配器直接导入该引擎;新结果格式可以将其基准窗口和 token 计数提供给它。在 srt-slurm 遥测覆盖单节点任务之前,单节点结果不包含功耗。 - -`infx` 包无需安装步骤或新增运行时依赖。从 `inferencex-e2e/` 运行 `python -m infx.results.power.multinode` 来调用引擎。 - -构建函数测试应使用独立计算预期结果的小样例和只读输入。修改现有适配器时,还应与旧实现比较 CLI 退出状态、诊断信息和生成工件,覆盖无效输入以及严格模式和尽力处理模式下的功耗失败。 - -### 评测与 AgentX 输出 - -对于仅评测作业,不要求吞吐量输出。工作流改为要求至少存在一个 `results*.json`。对于标记为运行评测的作业,上传内容可能包含 `meta_env.json`、`results*.json`、`sample*.jsonl`,以及厂商评估的原生报告、详细结果和归档。[`infx/evals/validate_scores.py`](../infx/evals/validate_scores.py) 会检查生成的评测分数。 - -[`infx.results.evals`](../infx/results/evals.py) 提供 `extract_metrics`,用于解析已加载的评测 JSON,并提供 `build_rows`,用于构建收集器输出。两者均接收显式输入,不执行文件 I/O,也不修改输入。构建函数应用元数据默认值和主分数优先级,并将失败评测保留为诊断行。CLI 负责文件查找、并发数资格筛选、报告输出和工件写入。 - -```python -from infx.results.evals import build_rows - -rows = build_rows(raw_eval, metadata, source="eval_job/results.json") -``` - -收集器和可复用工件验证器共享格式识别、并发数后缀解析、结果选择、指标族分类及数值有效性规则。`select_latest_result` 从全部候选中或指定并发数的候选中选择最新结果;`select_latest_results` 还支持为每个并发数选择一个候选,并按并发数的数值顺序返回。这些辅助函数接收候选路径,调用方仍保留各自的文件查找和资格筛选规则。文件名时间戳和旧格式文件的修改时间统一使用 Unix 纪元纳秒数,时间相同时按文件名排序。复用验证保留更严格的结构检查,并验证所有适用的主指标;收集器则保留每个指标族中最后配置的值用于报告。识别出格式并不意味着结果有效或可复用。 - -智能体吞吐量作业采用不同的契约。它们使用 [`infx/results/agentic/validate_agentic_result.py`](../infx/results/agentic/validate_agentic_result.py) 验证 AIPerf 输出,上传聚合的 `bmk_agentic_` 工件,并上传包含追踪重放材料的原始 `agentic_` 同级工件。InferenceX-app 通过它们共享的后缀对这些同级工件进行配对。智能体仅评测作业改为遵循评测输出契约,不要求吞吐量结果。 - -服务器日志是诊断辅助工件。它们通过 `always()` 上传,因此失败的运行仍可供调查。它们的存在不会将失败的基准测试转变为有效结果。srt 驱动的 [`collect.py`](../infx/launch/drivers/srt/collect.py) 通过调度器后端获取作业输出,并在清理输出前暂存多节点日志树和 `multinode_server_logs.tar.gz`。 - -## 阶段 6:工件收集与交接 - -单作业工件对于诊断和详细摄取仍然有用。两个收集器还会创建稳定的运行级聚合。 - -- [`collect-results.yml`](../../.github/workflows/collect-results.yml) 下载 `bmk_*`,运行 [`infx/results/collect_results.py`](../infx/results/collect_results.py),并上传 `results_bmk/agg_bmk.json`。 -- [`collect-evals.yml`](../../.github/workflows/collect-evals.yml) 下载 `eval_*`,运行 [`infx/results/collect_eval_results.py`](../infx/results/collect_eval_results.py),并上传 `eval_results_all/agg_eval_all.json`。 -- `run-sweep.yml` 还会在适用时单独上传 `changelog-metadata/changelog_metadata.json` 和 `run-stats/run_stats.json`。合并时,`merge-ingest.yml` 会上传自己的合并时 `changelog-metadata`。 - -工件名称是跨仓库接口的一部分。InferenceX-app 的 `ingest-ci-run.ts` 会明确指定 `results_bmk`、`run-stats`、`eval_results_all` 和 `changelog-metadata`。它还会发现单作业 `bmk_*`、`eval_*`、日志和智能体同级目录。 - -对于符合条件的 `main` 推送,[`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) 的 `ingest` 作业会验证已合并 PR 的复用授权,并向 `SemiAnalysisAI/InferenceX-app` 发送且仅发送一次 GitHub `repository_dispatch`。没有有效授权时,该作业会失败,不发送任何分派。`run-sweep.yml` 从不分派摄取。 - -- 不含智能体条目的变更日志增量使用 `event_type: ingest-results`。 -- 包含智能体条目的增量使用 `event_type: ingest-agentic-results` 并携带 `database-target: production`,由同一个工作流在更大的运行器上以更长的超时时间处理。 -- 负载携带 `source-run-id` 和 `merge-run-id`。源运行始终是提供工件的被复用 PR `run-sweep.yml` 运行,Merge Ingest 运行则提供当前变更日志上下文。 - -成功上传基准测试工件并不等同于成功摄取。仓库分派、工件准备、ETL、数据库验证和缓存失效都属于后续边界。 - -## 阶段 7:InferenceX-app 摄取 - -接收工作流首先运行 [`prepare-ci-artifacts.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/prepare-ci-artifacts.ts)。它会验证数字运行 ID,获取源运行和合并运行元数据,列出工件,构建选择计划,将内容下载到空目录,并在源运行与合并运行不同时写入复用元数据。 - -迁移完成后,[`ingest-ci-run.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/packages/db/src/ingest-ci-run.ts) 执行语义交接。 - -1. 它加载工作流元数据,并创建或复用工作流运行行。 -2. 它预加载配置缓存,以避免逐行查找配置产生的开销。 -3. 它读取基准测试聚合及单作业工件,通过 `benchmark-mapper.ts` 对其进行映射,并向上插入基准测试行、可用性、服务器日志、统计信息和智能体追踪旁路文件。 -4. 它读取 `eval_results_all/agg_eval_all.json` 以获取聚合评测行。 -5. 它读取每个按配置划分的 `eval_*` 目录中的元数据、任务结果和样本 JSONL,然后将样本附加到规范评测行。 -6. 它摄取变更日志元数据并保留复用运行的归属信息。 -7. 它会记录未映射的模型、硬件、精度和缺失的数据集,以便通知操作人员,而不是静默地将它们视为有效。 -8. 它在摄取后刷新 `latest_benchmarks`。 - -随后,工作流应用持久化运行覆盖值,执行数据库验证,并调用应用的失效端点。只有在完成持久化和缓存失效之后,仪表板 API 才能可靠地公开新状态。 - -摄取过程被特意设计为幂等。自然键冲突会更新或保留现有行,因此重新运行部分完成或重复的摄取时,无需先删除数据库状态。请参阅 [InferenceX-app 数据流水线设计理由](https://github.com/SemiAnalysisAI/InferenceX-app/blob/main/docs/data-pipeline.md#why-idempotent-ingestion)。 - -## 权威来源决策 - -### 配置意图位于主 YAML 中 - -使用主条目回答应该对什么进行基准测试。使用运行器配置回答可在何处调度。使用基准测试脚本和启动器回答如何执行。不要仅仅因为物理主机细节会影响某个机群,就将其编码到主 YAML 中。 - -### 验证行为位于代码中 - -`configs/CONFIGS.md` 解释契约,但由 `validation.py` 决定接受什么。当说明文字与强制行为不一致时,应同时修复两者。不要通过添加临时工作流解析来绕过验证。 - -### 矩阵派生只有一套实现 - -派生并发点、评测选择、拓扑默认值、名称和运行器派生信息属于 `infx.matrix.generate`。工作流应转发矩阵字段,而不应在表达式或 Shell 中重新实现生成器策略。 - -`full-sweep` 和 `test-config` 命令共用固定序列与 AgentX 的矩阵行构建逻辑。各命令的选择规则仍由调用方负责;AgentX 构建逻辑负责 worker 默认值、卸载预算、实验名称、节点数和验证。它在过滤并发度前验证拓扑与卸载预算,保留并发点和运行器的原有顺序,并仅按上下限过滤 AgentX 并发点,不会额外生成截断到上限的并发点。 - -### 触发选择与配置彼此独立 - -`perf-changelog.yaml` 选择工作并记录原因。它不会重新定义主条目。这样既可以复用配置目录,又能保留可供审查的历史记录,说明每次扫描打算运行什么。 - -### 启动机制保存在集群记录中 - -模型根目录、Slurm 分区、squash 缓存和挂载属于 `configs/runners.yaml` 中该集群的 `clusters:` 记录([模式](../configs/CONFIGS.md#runners));与模型、框架或方案相关的启动规则属于 `infx/launch/policy.py` 和 `infx/launch/drivers/srt/` 中的具名表。框架服务器和客户端标志属于基准测试脚本或外部方案。驱动中不出现按集群的分支。 - -- 集群事实(节点形态、工作负载 `env`、已暂存模型以及调度器自身设置;Slurm 下为 `slurm:` 中的分区、账户、卷、squash 缓存和 srt-slurm profile)属于集群记录,不属于驱动代码。 -- 按模型、框架、精度或方案区分的工作负载规则(模型别名、`/ix` 工作区、功耗资格、时间延长、TileRT UCX 设置)属于具名表:共享规则位于 `infx/launch/policy.py`,单个驱动使用的规则放在该驱动旁边(srt-slurm 为 `drivers/srt/lanes.py`、`models.py`、`power.py`)。 -- 永远不要在驱动中按集群 ID 分支。驱动只能通过集群的后端(`infx/launch/backends/`)访问调度器。 -- 新调度器由新文件加两个注册项组成:其设置模型(带自身的卷类型)放在 `infx/clusters/` 下并注册到 `infx.clusters.SCHEDULERS`,其后端放在 `infx/launch/backends/` 下并注册到 `BACKENDS`。该调度器上的集群只运行 script 驱动点(`BENCH_SCRIPT_OVERRIDE`,例如 SPEED-Bench);srt-slurm 点需要 Slurm,会在开始任何工作前失败。 -- 每个版本都通过 `python -m infx.launch` 启动,不存在 shell 启动器回退;不要新增 shell 启动器。 -- 退役集群时,在同一 PR 中删除其 `cluster:` 标签、`clusters:` 记录以及按其 ID 键控的所有策略行。 - -#### srt-slurm 主机初始化钩子 - -- 可复用的主机检查函数放在 `runners/srt-slurm/hooks/common.sh`。source 该文件只定义函数,不得运行检查、修改环境变量或初始化基准测试。仅供单个集群使用的辅助函数放在其 setup 脚本旁边。 -- 集群特定的主机前置条件放在 `runners/srt-slurm/hooks//setup.sh`,由 `configs/runners.yaml` 中该集群的 `srt-slurm.host-setup` 记录显式调用,在分配之后、服务和 worker 启动之前运行。 -- 钩子只用于该集群主机或网络所需的检查与初始化。保持小巧、与工作负载无关、可重复运行。只要原生 srt-slurm 配置能表达需求,就优先使用原生配置。 -- 钩子中不得包含基准测试执行、模型选择、引擎标志、并发调优、评测、结果收集或作业编排,也不得给引擎或容器打补丁、绕过失败的检查,或用重试掩盖运行时缺陷。应在负责该问题的组件中修复。 -- 设置通过 `srt-slurm.host-setup.env` 显式传入。变更范围限定在已分配节点,保留其他作业的资源,并为需要恢复的临时状态注册 teardown。 - -### 工件 JSON 是仓库边界 - -InferenceX 负责生成标识正确的工件。InferenceX-app 负责将这些工件解释为规范数据库记录。绝不要让 InferenceX-app 抓取工作流日志来恢复本应在 JSON 中发出的字段。 - -### 应用数据库是公共数据源 - -GitHub 工件是传输和恢复输入,而不是实时仪表板数据库。InferenceX-app 负责规范化、幂等持久化、读取模型、缓存失效和展示转换。 - -## 追踪并验证一项结果 - -当某一行缺失、标签错误或不符合预期时,请使用此流程。 - -1. **配置:** 在 `configs/nvidia-master.yaml` 或 `configs/amd-master.yaml` 中查找确切键。记录 `model-prefix`、`framework`、`precision`、运行器、场景、拓扑和并发度。 -2. **选择:** 确认新增的 `perf-changelog.yaml` 条目选择了该键和场景。如果这是 PR,请检查 `run-sweep.yml` 中的扫描标签以及跳过或复用策略。 -3. **验证:** 仅生成该确切键并检查 JSON,不要只查看退出码。 - - ```bash - uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.matrix.generate test-config \ - --config-files configs/nvidia-master.yaml configs/amd-master.yaml \ - --runner-config configs/runners.yaml \ - --config-keys - ``` - -4. **矩阵交接:** 在 `setup` 作业中,验证该行位于预期的 `single_node`、`multi_node`、`evals`、`agentic_evals`、`multinode_evals` 或 `multinode_agentic_evals` 桶中。确认匹配的扇出作业转发了每个必需字段。 -5. **调度:** 验证模板的 `runs-on` 值与预期运行器匹配。确认具体运行器名称恰好出现在 `configs/runners.yaml` 的一个 `cluster:` 标签中。 -6. **运行时:** 沿 `launch_path` 及所选驱动追踪到确切的基准测试脚本或外部方案。确认每个关键矩阵字段均到达实际被使用的环境变量或命令参数。 -7. **输出:** 验证工作流要求的原始结果存在。然后验证预期的 `bmk_*`、`eval_*`、`agentic_*`、日志或指标工件已上传。 -8. **收集:** 对于固定序列吞吐量,检查 `results_bmk/agg_bmk.json`。对于评测,检查 `eval_results_all/agg_eval_all.json` 和按配置划分的评测工件。还要确认 `changelog-metadata` 存在。 -9. **分派:** 在合并提交对应的 `merge-ingest.yml` 运行中,验证 `ingest` 作业发送了正确的事件类型,并且其 `source-run-id` 和 `merge-run-id` 标识预期运行。 -10. **摄取:** 在 InferenceX-app 中,验证工件准备过程选择了预期名称,ETL 报告的是已映射行而非跳过项,数据库验证已通过,并且已尝试使缓存失效。 -11. **使用方:** 仅在摄取完成后查询仪表板。如果该行不存在,请先使用 ETL 跳过和未映射实体输出,再修改前端代码。 - -对于仅检查矩阵的情况,在第 4 步后停止。对于端到端生产声明,必须完成全部十一项步骤。 - -## 停止条件 - -存在以下任何情况时,请勿启动或批准扫描。 - -- 主键未通过严格验证或定向生成。 -- 生成的拓扑、并发度、评测标记、镜像或运行器与预期声明不同。 -- 必需字段在矩阵 JSON、可复用工作流输入、环境、启动器和运行时命令之间传递时消失。 -- 具体运行器不在任何 `cluster:` 标签中,或者没有支持该模型、精度、框架和拓扑的启动路径。 -- 基准测试或评测路径无法说明其预期结果文件名和工件名称。 -- 生产方工件名称不再与 InferenceX-app 使用的名称匹配。 -- `merge-ingest.yml` 运行在缺少已验证且具备未过期结果工件的复用源运行时,或在其变更日志元数据上传之前,就进入分派阶段。 -- 摄取针对正在调查的数据行报告了未映射的模型、硬件、精度或必需数据集。 -- 数据库验证失败,或者最新基准测试刷新未完成。 -- 仪表板声明仅基于成功的基准测试作业,没有成功摄取和缓存失效的证据。 - -只有当声明的配置、生成的矩阵、调度的作业、运行时命令、工件标识、规范数据库行和仪表板视图描述同一个基准测试点时,流水线才算完整。 diff --git a/inferencex-e2e/docs/ci-procedures.md b/inferencex-e2e/docs/ci-procedures.md index d71e56fc1f..206b37370e 100644 --- a/inferencex-e2e/docs/ci-procedures.md +++ b/inferencex-e2e/docs/ci-procedures.md @@ -1,12 +1,6 @@ # CI Procedures -
- -**English** | [中文](ci-procedures_zh.md) - -
- -Use this page for matrix generation, CI dispatch, PR sweeps, result staging, artifact reuse, and post-merge publication. English is the source version. Keep the Chinese page structurally synchronized with it. Record the repository, commit SHA, workflow run ID, run attempt, and artifact name whenever CI output is used as evidence. +Use this page for matrix generation, CI dispatch, PR sweeps, result staging, artifact reuse, and post-merge publication. Record the repository, commit SHA, workflow run ID, run attempt, and artifact name whenever CI output is used as evidence. ## Procedure index @@ -582,4 +576,3 @@ four-GPU Arm nodes; the other pools use eight-GPU x86 nodes. GEMM and attention use one GPU per measurement. AMD attention supports both torch and AITER. See [OperatorX GitHub Actions](../../operatorx/CI.md) for dispatch, coverage, artifacts, cancellation, and validation. - diff --git a/inferencex-e2e/docs/ci-procedures_zh.md b/inferencex-e2e/docs/ci-procedures_zh.md deleted file mode 100644 index 75feb885db..0000000000 --- a/inferencex-e2e/docs/ci-procedures_zh.md +++ /dev/null @@ -1,563 +0,0 @@ -# CI 操作流程 - -
- -[English](ci-procedures.md) | **中文** - -
- -本页用于矩阵生成、CI 派发、PR 扫描、结果预发布、产物复用与合并后发布。英文页是源版本;中文页必须在结构上与其保持同步。凡将 CI 输出作为证据,均应记录仓库、Commit SHA、Workflow Run ID、Run Attempt 与 Artifact 名称。 - -## 流程索引 - -| 任务 | 前往 | -| --- | --- | -| 确定权威实现 | [源码映射](#源码映射) | -| 避免套用错误分支的 Workflow 契约 | [源码快照警告](#源码快照警告) | -| 在本地生成并检查矩阵 | [本地矩阵生成](#本地矩阵生成) | -| 验证 YAML 与 `perf-changelog.yaml` | [YAML 与 Changelog 验证](#yaml-与-changelog-验证) | -| 启动定向 GPU 任务 | [手动端到端派发](#手动端到端派发) | -| 选择 PR 扫描标签 | [PR 主标签与修饰标签](#pr-主标签与修饰标签) | -| 理解提前取消行为 | [Canary 与 Fail-fast 语义](#canary-与-fail-fast-语义) | -| 诊断或重跑 Workflow | [监控与重跑](#监控与重跑) | -| 检查特权 Workflow 的访问权限 | [基于仓库角色的授权](#基于仓库角色的授权) | -| 管理 CI Python 依赖 | [CI Python 环境](#ci-python-环境) | -| 将 PR Run 发布到预发布环境 | [暂存结果](#暂存结果) | -| 合并时不重复已批准的扫描 | [产物复用与 merge-with-reuse](#产物复用与-merge-with-reuse) | -| 恢复仅追加 Changelog 的冲突 | [Changelog 冲突恢复](#changelog-冲突恢复) | -| 不加载全部内容地检查结果 JSON | [产物下载与解析](#产物下载与解析) | -| 合并后验证发布 | [合并后预期](#合并后预期) | - -## 源码映射 - -以下文件就是契约。应遵循目标 Ref 的源码,而不是从旧 Run 复制命令: - -| 关注点 | 准确源码 | -| --- | --- | -| 生成器 CLI、过滤与 Eval 标记 | [`infx.matrix.generate`](../infx/matrix/generate.py) | -| 严格的 Master Config 与矩阵 Schema | [`infx.matrix.validation`](../infx/matrix/validation.py) | -| 生成器示例与复用策略 | [`.github/workflows/README.md`](../../.github/workflows/README.md) | -| 手动端到端输入与矩阵扇出 | [`.github/workflows/e2e-tests.yml`](../../.github/workflows/e2e-tests.yml) | -| PR 扫描 Gate、Canary 与收集 | [`.github/workflows/run-sweep.yml`](../../.github/workflows/run-sweep.yml) | -| 合并时复用检查、Changelog Metadata 与入库派发 | [`.github/workflows/merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) | -| 单节点与多节点产物上传 | [`.github/workflows/benchmark-tmpl.yml`](../../.github/workflows/benchmark-tmpl.yml)、[`.github/workflows/benchmark-multinode-tmpl.yml`](../../.github/workflows/benchmark-multinode-tmpl.yml) | -| 吞吐量与 Eval 聚合 | [`.github/workflows/collect-results.yml`](../../.github/workflows/collect-results.yml)、[`.github/workflows/collect-evals.yml`](../../.github/workflows/collect-evals.yml)、[`infx/results/collect_results.py`](../infx/results/collect_results.py)、[`infx/results/collect_eval_results.py`](../infx/results/collect_eval_results.py) | -| Changelog 字节、Diff 与矩阵 Gate | [`infx/workflows/validate_perf_changelog.py`](../infx/workflows/validate_perf_changelog.py)、[`infx.matrix.plan`](../infx/matrix/plan.py) | -| 复用授权与源 Run 选择 | [`infx/workflows/reuse.py`](../infx/workflows/reuse.py) | -| 受支持的复用合并与冲突准备 | [`infx/workflows/merge_with_reuse.py`](../infx/workflows/merge_with_reuse.py)、[`infx/workflows/prepare_perf_changelog_merge.py`](../infx/workflows/prepare_perf_changelog_merge.py) | -| 预发布请求与回调 | [`infx/workflows/stage_results.py`](../infx/workflows/stage_results.py)、[`.github/workflows/stage-results.yml`](../../.github/workflows/stage-results.yml)、[`.github/workflows/stage-results-callback.yml`](../../.github/workflows/stage-results-callback.yml) | -| 复用 Agentic 入库的重新派发 | [`.github/workflows/recover-reused-ingest.yml`](../../.github/workflows/recover-reused-ingest.yml) | -| 合并后责任提醒 | [`.github/workflows/pr-recipe-reminder.yml`](../../.github/workflows/pr-recipe-reminder.yml) | - -## 源码快照警告 - -`workflow_dispatch` 请求使用其派发 `--ref` 中的 Workflow 定义;单独的 `inputs.ref` 控制 Job Checkout 的内容。在使用下方公共示例以外的输入前,应检查已部署定义: - -```bash -gh workflow view e2e-tests.yml --repo SemiAnalysisAI/InferenceX --ref main --yaml -``` - -以目标 Ref 的 Workflow 和脚本源码为准。不要猜测某个分支本地输入或 Fork 策略已经部署。 - -## 本地矩阵生成 - -生成器会加载所有指定的 Master Config 与 `configs/runners.yaml`,使用 Pydantic 验证输入,生成条目,验证输出结构,应用 Eval 策略,并输出一个 JSON 数组。退出码为零只能证明生成与 Schema 验证成功,不能证明容器、模型或 GPU Runner 能工作。 - -### 生成一个准确配置 - -对准确 Key 或带引号的 `*`/`?` 模式使用 `test-config`。`--conc` 必须存在于配置的并发范围/列表内,`--seq-lens` 必须匹配实际存在的 Scenario。 - -```bash -MATRIX=/tmp/inferencex-matrix.json -uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.matrix.generate test-config \ - --config-files configs/nvidia-master.yaml \ - --config-keys dsr1-fp8-h200-sglang \ - --seq-lens 8k1k \ - --conc 4 \ - --no-evals > "$MATRIX" -python3 -m json.tool "$MATRIX" >/dev/null -``` - -多个 Key 应逐个放在 `--config-keys` 之后。通配模式必须加引号,防止 Shell 展开: - -```bash -uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.matrix.generate test-config \ - --config-files configs/nvidia-master.yaml \ - --config-keys '*-b200-*' \ - --conc 4 \ - --no-evals > /tmp/inferencex-b200.json -``` - -### 生成过滤后的扫描 - -`full-sweep` 不一定表示所有配置。可按模型、精度、框架、Runner、序列长度、拓扑、并发、TP/EP 或 Scenario 类型缩小范围: - -```bash -uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.matrix.generate full-sweep \ - --config-files configs/nvidia-master.yaml \ - --single-node \ - --model-prefix dsr1 \ - --framework sglang \ - --runner-type h200 \ - --seq-lens 8k1k \ - --min-conc 4 \ - --max-conc 4 \ - --no-evals > /tmp/inferencex-filtered.json -``` - -如果既未提供 `--single-node` 也未提供 `--multi-node`,两种类型都会生成。`--step-size` 必须大于 1;如果同时提供并发上下界,`--min-conc` 不能大于 `--max-conc`。 - -### 检查而非倾倒 - -检查数量与执行关键字段,不要把完整 JSON 加载进上下文: - -```bash -jq 'length' "$MATRIX" -jq -r ' - .[] | - [.["model-prefix"], .framework, .precision, .runner, - .isl, .osl, (.conc | tostring), (.tp // "-"), (.ep // "-"), - (.prefill.hardware // "-"), (.decode.hardware // "-"), - (.["run-eval"] // false), (.["eval-only"] // false)] | - @tsv -' "$MATRIX" -``` - -确认预期的镜像、模型、硬件/Cluster 标签、单节点或多节点拓扑、输入/输出长度、并发、TP/EP、解码模式与 Eval 标记。空输出不算成功的预检。 - -每个生成的多节点行都必须包含严格校验的正整数 `node-count`。启用节点槽位调度时,可复用 Workflow 会将该值发布为 `nodes:N` 请求标签;需求缺失或无效会导致矩阵验证失败,而不会静默进入单节点队列。不使用 Master Config 生成器、直接接入优先级调度的 Workflow 必须自行发布准确需求(例如 CollectiveX 使用每个分片生成的 `nodes` 值)。 - -对于仓库内的解耦式 srt-slurm Recipe,节点需求包括 Worker 节点、已启用的 Service Pool,以及 Frontend、服务发现或 Benchmark 的专用节点。专用组件默认共用一个额外节点;设置 `benchmark.colocate_with_frontend: false` 后,每个专用组件分别占用一个节点(etcd 和 NATS 仍共用服务发现节点)。计数前先解析命名 Override。此变更只修正租约大小,不改变 Benchmark 拓扑。 - -Eval 开关语义是明确的: - -- 默认:吞吐量条目加选定的默认固定序列 Eval 子集。 -- `--no-evals`:仅吞吐量;不能与 `--all-evals` 组合。 -- `--evals-only`:仅选定的 Eval 子集。 -- `--all-evals`:扩展到每个已生成的固定序列配置;单独使用时也等同于 Eval-only。 -- `--evals-only --all-evals`:所有扩展后的 Eval,且无吞吐量。 - -## YAML 与 Changelog 验证 - -### 解析修改过的 YAML - -对每个修改过的 YAML 文件执行语法解析。它能发现畸形 YAML,但不能验证 GitHub 表达式或 Workflow 依赖连线: - -```bash -uv run --no-project --exclude-newer PT12H --python 3.12 --with pyyaml \ - python -c 'import sys, yaml; [yaml.safe_load(open(path, encoding="utf-8")) for path in sys.argv[1:]]' \ - configs/nvidia-master.yaml perf-changelog.yaml .github/workflows/e2e-tests.yml -``` - -对 Master Config 而言,矩阵生成就是严格验证:[`validation.py`](../infx/matrix/validation.py) 禁止未知字段,并同时验证 Master 条目和输出矩阵条目。运行能覆盖改动的最小准确 `test-config` 或过滤后的 `full-sweep`。 - -### 验证仅追加 Changelog 契约 - -`perf-changelog.yaml` 不是普通 YAML。除经过严格验证的 PR Link 修正外,历史字节不可修改。新条目必须追加到末尾,以恰好一个空行分隔,以一个换行结束,不得含 CR、Tab 或 NUL 字节,并且必须通过 Changelog Schema 且能生成有效矩阵。 - -验证器读取 Git 对象,而非未提交的 Working Tree 字节。先提交候选改动,再与真实 Base 比较: - -```bash -git fetch origin main -uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.workflows.validate_perf_changelog \ - --changelog-file perf-changelog.yaml \ - --base-ref origin/main \ - --head-ref HEAD -``` - -当 PR 将启用对应修饰标签时,加入 `--all-evals` 和/或 `--evals-only`;[`run-sweep.yml`](../../.github/workflows/run-sweep.yml) 会传递相同参数。绝不使用 Formatter 重写 `perf-changelog.yaml`,也绝不能把单独通过 `yaml.safe_load` 当作充分的 Changelog 验证。 - -## 手动端到端派发 - -仅在完全相同的生成器命令已于本地成功后,才使用 [`e2e-tests.yml`](../../.github/workflows/e2e-tests.yml) 执行受限的一次性 Run。测试名称必须唯一。在通用模式中,`--ref main` 选择已部署的 Workflow 定义,输入 `ref` 则选择要测量的 Branch 或 SHA。Setup 只解析一次该 ref,并将 checkout SHA 传给全部八条基准测试和评测路径,覆盖单节点、多节点、固定序列和 AgentX Job。即使分支在排队期间前进,后续 Job 仍使用该 SHA。未提供输入 `ref` 时,仍使用 `github.sha`。 - -```bash -REPO=SemiAnalysisAI/InferenceX -TEST_NAME="manual-dsr1-h200-$(date -u +%Y%m%dT%H%M%SZ)" -TARGET_REF='' - -gh workflow run e2e-tests.yml \ - --repo "$REPO" \ - --ref main \ - -f ref="$TARGET_REF" \ - -f test-name="$TEST_NAME" \ - -f generate-cli-command='full-sweep --config-files configs/nvidia-master.yaml --single-node --model-prefix dsr1 --framework sglang --runner-type h200 --seq-lens 8k1k --min-conc 4 --max-conc 4 --no-evals' \ - -f duration-override='' -``` - -只使用 `gh workflow view ... --ref main --yaml` 展示的输入。不同派发 Ref 的输入可能不同,不得凭假设传入目标 Ref 特有的选项。 - -派发是异步的,Run 可能不会立刻出现。应按准确 Display Title 查找,而不是假定最新 Run 属于自己: - -```bash -gh run list \ - --repo "$REPO" \ - --workflow e2e-tests.yml \ - --event workflow_dispatch \ - --limit 30 \ - --json databaseId,displayTitle,headBranch,headSha,status,conclusion,url - -RUN_ID=$(gh run list \ - --repo "$REPO" \ - --workflow e2e-tests.yml \ - --event workflow_dispatch \ - --limit 30 \ - --json databaseId,displayTitle \ - | jq -r --arg title "e2e Test - $TEST_NAME" \ - '[.[] | select(.displayTitle == $title)][0].databaseId // empty') -``` - -如果 `RUN_ID` 为空,不得继续。Run Metadata 描述派发 Workflow 的 Ref,可能不等于输入 `ref`。解释 GPU 结果前,必须在 `get-jobs` 中确认唯一标题、生成器命令与 Checkout Ref。 - -## PR 主标签与修饰标签 - -同仓库 PR 无论处于草稿还是 ready 状态,都由 sweep 标签授权 GPU 运行。草稿状态控制是否开始审阅,不决定 sweep 资格;fork PR 仍使用受信任调度路径。添加 sweep 标签或在保留标签时推送提交可以启动 sweep。标记为 ready 不会调度或重复运行。已带标签但尚无运行的草稿,可先移除再重新添加对应 sweep 标签来启动。 - -同仓库检查既在 changelog 验证检出 PR 代码前执行,也在 GPU setup 前执行。验证明确使用只读 token,checkout 不持久保存凭据。外部 PR 仍须经单独的受信任调度器:具有写权限的维护者为打开且 ready 的 PR 添加标签,批准精确 head;后续外部提交需重新批准。仅添加标签不会使 fork 进入普通 sweep 流程。 - -[`run-sweep.yml`](../../.github/workflows/run-sweep.yml) 会拒绝多个主标签。必须且只能应用一个: - -| 主标签 | 矩阵范围 | Canary | 矩阵 Fail-fast | -| --- | --- | --- | --- | -| `full-sweep-fail-fast` | 完整 Changelog 矩阵 | 有 | 有;推荐的完整扫描默认值 | -| `full-sweep-enabled` | 完整 Changelog 矩阵 | 有 | 无;需要每个矩阵点继续运行时使用 | -| `non-canary-full-sweep-enabled` | 完整 Changelog 矩阵 | 无 | 无 | - -可选修饰标签不能替代主标签: - -| 修饰标签 | 效果 | 合并后可复用? | -| --- | --- | --- | -| `all-evals` | 将 Eval 选择扩展至所有符合条件的 Eval,吞吐量仍会运行。与 `evals-only` 组合即只运行所有 Eval | 可以,前提是 Run 满足其他完整扫描复用规则 | -| `evals-only` | 禁用吞吐量,仅运行选定 Eval 条目;与 `all-evals` 组合即只运行所有 Eval | 不可以 | -| `agentx-fast` | 对 AgentX 吞吐量 Lane,在强制 Primer 后只加一次额外 Warmup Request,并使用 20 分钟 Profile;固定序列与 Eval 设置仍为规范值 | 不可以 | - -仅有修饰标签不会启动 GPU 扫描,但仍会运行 `check-changelog`。当变更日志新增条目包含 `append-only: true` 或 `no-evals: true` 时,`all-evals` 和 `evals-only` 会使 `check-changelog` 失败。 - -每个主标签都会运行完整的并发扫描,任何标签都不会裁剪并发。需要最低并发冒烟测试时,请按[手动端到端派发](#手动端到端派发)运行 `e2e-tests.yml`,并设置 `trim-conc: true`。 - -修改被识别的主标签或修饰标签会共享活动扫描的 Concurrency Group,并取消当前 Run。只有仍保留主标签时才会启动新的扫描。Head Commit 含 `[skip-sweep]` 只会跳过 PR 基准 Setup;Changelog/复用检查仍会运行,推送到 `main` 时运行的 `merge-ingest.yml` 会忽略该标记。 - -队列优先级来自 PR Diff,不存在优先级标签。启用优先级调度器时,`run-sweep.yml` 的 Setup 会对 Diff 分类,再由 [`ci_priority.py`](../infx/workflows/ci_priority.py) 依据 [`configs/ci-priority.yaml`](../configs/ci-priority.yaml) 按这些条件为每个 Job 评分。PR 清单已满足(`checklist-complete`)会提高分数。修改上游引擎或运行时源码(`patchwork`)的 Diff 获得最低分,分类失败时同样按 `patchwork` 处理。人工优先级调整通过 InferenceX Dash 优先级调度器进行。 - -## Canary 与 Fail-fast 语义 - -Canary 和 Fail-fast 解决不同问题: - -1. 只有使用 `full-sweep-enabled` 或 `full-sweep-fail-fast` 的同仓库 PR 才创建 Canary。`non-canary-full-sweep-enabled` 会跳过它。对于 fork PR,[`trusted-external-sweep.yml`](../../.github/workflows/trusted-external-sweep.yml) 改为派发 `e2e-tests.yml`,任何标签都不运行 Canary;在该路径下,只有 `full-sweep-fail-fast` 会启用 Fail-fast。 -2. Canary 首先检查单节点固定序列 `1k1k`、`8k1k` 和单节点 AgentX 条目;若没有合格条目,再检查多节点 AgentX 条目。它排除 Eval 条目,选取最低并发候选,使用对应的单节点或多节点工作流运行,并从后续矩阵移除该条目。 -3. 如果没有合格候选,Canary 会被跳过。否则所有 Benchmark/Eval 矩阵都要求 Canary 成功;Canary 失败会阻止其扇出。 -4. `full-sweep-fail-fast` 会分别为每个矩阵 Job Family 设置 `strategy.fail-fast: true`。首个失败点会取消同一矩阵 Family 中排队或运行中的兄弟项;它不是跨所有独立 Family 的全局 Kill Switch。 -5. 非 Fail-fast 标签会保持矩阵 Fail-fast 为 false,使其他点继续运行并保留更广泛的诊断覆盖。 -6. Fail-fast Run 可能因失败后兄弟项被取消而最终显示 `cancelled`。将取消归类为基础设施事件前,必须先识别第一个真实失败。 - -手动 `e2e-tests.yml` 没有 Canary。它的 `fail-fast` 输入默认为 false,并传递给每个矩阵 Job Family。始终使用派发 Ref 对应的定义。 - -## 监控与重跑 - -PR 扫描维护一条机器人评论,包含 `View unofficial run (performance)` 和 `View unofficial run (accuracy)` 链接。每个更新的 Run 都会编辑该评论;重跑旧 Run 不会覆盖更新的链接。已有 PR 会复用最新的旧格式可视化评论,更早的历史评论保持不变。 - -### 监控选定 Run - -```bash -gh run watch "$RUN_ID" --repo SemiAnalysisAI/InferenceX --exit-status -gh run view "$RUN_ID" --repo SemiAnalysisAI/InferenceX --log-failed -gh api "/repos/SemiAnalysisAI/InferenceX/actions/runs/$RUN_ID" \ - --jq '[.id, .run_attempt, .event, .head_sha, .status, .conclusion, .html_url] | @tsv' -``` - -监控第一个 Canary 或矩阵失败,并在重跑前完成分类: - -- **配置/运行时失败:** 可复现的 Launcher、验证、模型、镜像、就绪、OOM 或结果错误。修复源码并生成新 Run。 -- **Runner/基础设施抖动:** Runner 离线、临时网络/存储/服务故障或无关取消。保留日志,确认改动本身无责后再重跑。 -- **策略/Gate 失败:** 标签冲突、Changelog 无效、缺少授权、合并冲突或产物不合格。修正 Gate;重跑 GPU 无法解决。 -- **已被取代的 Run:** 后续 Commit 或被识别的标签变更通过 Workflow Concurrency 将其取消。应监控替代 Run,不要复活过期证据。 - -[`Claude Code` 工作流](../../.github/workflows/claude.yml) 包含审阅和编码两个独立任务。审阅任务保留原有的 `ready_for_review` 及授权 `@pr-claude` 触发条件,只读访问仓库内容,并具有发布 PR 反馈的权限;编码任务使用原有写权限处理 `@claude` 和 `@Klaud-Cold` 请求。只有评论或 Issue 作者的 `author_association` 为 `OWNER`、`MEMBER` 或 `COLLABORATOR` 时,编码任务才会启动;它不接受任何机器人触发者(`allowed_bots: ''`),因此即使 `github-actions[bot]`、`claude[bot]` 等 App 机器人的评论提及 `@claude` 或 `@Klaud-Cold`,也无法启动该任务。同一 PR 的审阅请求串行执行,不取消正在运行的审阅;编码请求仍独立运行。两个任务均通过固定到提交 SHA 的官方 action 安装其支持的 Claude Code CLI。安装或启动失败表示审阅没有执行,既不是代码审阅发现的问题,也不代表审阅通过。重试前应先检查 action 的安装日志。 - -### 安全重跑 - -CODEOWNER 验证会在合格的人类用户为打开且非草稿的 PR 提交或编辑清单时触发,也可通过 `pr-number` 和该清单的 `comment_url` 手动分发。它仅适用于可信目标分支 CODEOWNERS 中存在非管理员、非 core owner 的改动;其他改动跳过验证。归属、重命名及权限规则见[贡献指南](../../CONTRIBUTING_zh.md#pr-review-checklistcodeowner-签署)。 - -验证使用可信默认分支代码,并按 PR 串行执行。启动 Claude 要求触发者的基础 `permission` 为 `write` 或 `admin`,且 `role_name` 为 `write`、`maintain` 或 `admin`。未知或自定义角色、字段缺失、机器人触发和查询失败均不能启动验证。手动分发的 `pr-number` 和 `comment_url` 必须指向同一 PR。 - -验证器为每个签署资源关联一条供审阅参考的评论,并注明实际评估的 SHA。编辑同一清单时只更新与其关联的裁定;不同清单会获得独立裁定,因此旧签署的裁定不会被覆盖。后续推送不会延续该评估,也不会触发新运行。需要重新评估时,请手动分发;合并冲突期间遗漏的 Review 事件也按此方式重试。验证器不发布提交状态,GitHub 单独设置的人工批准要求仍然适用。 - -不要盲目重跑仍在执行的 Run。已结束的失败 Run 可以只重跑失败 Job 及其依赖项: - -```bash -gh run rerun --failed --repo SemiAnalysisAI/InferenceX -``` - -对已结束且为 `cancelled` 的 Fail-fast Run,应重跑整个 Attempt,从而重新创建被取消的矩阵点: - -```bash -gh run rerun --repo SemiAnalysisAI/InferenceX -``` - -重跑沿用同一个 Workflow Run ID,但 Attempt 会增加。Artifact API 可能包含多个 Attempt 上传的产物;必须保留 `run_attempt` 并检查 Artifact 时间戳。`run-stats` 会有意统计所有 Attempt 的 Job。如果源码需要变化,不应重跑旧代码:推送修复并监控新 Run。移除再重新添加主扫描标签会强制创建新的 Labeled Run;后续 Commit 也可能使复用资格失效。 - -## CI Python 环境 - -需要 Python 包的托管 Job 使用固定 Commit 的 `astral-sh/setup-uv` Action, -并通过 `uv run --no-project --exclude-newer PT12H --python 3.12` 运行命令。 -使用 `--with` 声明依赖,或通过 `--with-requirements` 复用已有的依赖文件; -通常无需单独的依赖安装步骤。 -选项统一按以下顺序排列:`--no-project`、`--exclude-newer`、`--python`、 -`--with`、`--with-requirements`,最后是要执行的命令及其参数。 - -12 小时冷却期同时适用于包索引中的直接依赖和传递依赖。缺少上传时间戳的 -分发文件不可用;不得为了通过依赖解析而关闭冷却期。CollectiveX 使用全新的 -虚拟环境和 `uv pip install --exclude-newer PT12H --torch-backend cpu`:仅从 -CPU 索引获取 PyTorch 包,其他依赖从 PyPI 获取,因为 CPU 索引中的这些依赖 -镜像缺少上传时间戳。该 Job 确认安装的 Wheel 不包含 CUDA 或 ROCm 后端。 - -矩阵和 CollectiveX 单元测试现在也会在草稿 PR 上运行, -以便在请求审阅前验证 CI 环境变更。 - -仅依赖标准库的辅助程序继续使用 Runner 自带的 Python。基准容器及其框架 -环境仍由现有启动器管理;此次 CI 依赖迁移不会修改这些环境。 - -自托管的启动步骤使用 `INFERENCEX_LAUNCH_PYTHON` 运行 `python -m infx.launch`。它是 -“Prepare launcher Python”步骤在 `$RUNNER_TEMP` 中依据工具 checkout 的 `inferencex-e2e/pyproject.toml` -(`uv pip install --exclude-newer PT12H`)构建的未激活 venv。不使用 `uv run`:它对 `VIRTUAL_ENV` -和 `PATH` 的修改会泄漏进 `srun --export=ALL` 作业。Python 准备步骤把 uv 缓存和托管的 Python -按 runner 放在其 workspace 旁(`.infx-uv-cache`、`.infx-uv-python`),因为有些 runner 的 home -目录无法容纳 uv 的默认位置。 - -## 基于仓库角色的授权 - -结果暂存和可信外部扫描派发均使用 `GITHUB_TOKEN` 检查仓库权限。暂存通过 -`infx.workflows.stage_results` 执行,外部派发使用 `actions/github-script`。两项操作都要求 Write、Maintain 或 -Admin 权限;Read、Triage 以及没有仓库访问权限的用户不能执行这些操作。 - -授权要求原有基础 `permission` 和有效 `role_name` 均为 `admin`、`maintain` 或 -`write`。字段缺失或格式无效会终止 Workflow;未知角色和自定义角色会被拒绝, -绝不回退到旧版权限字段来放行。API 错误也会终止 Workflow。这些更严格的拒绝 -行为属于有意变更;标准 Write 权限仍然足够。GitHub 的基础 `permission` 字段 -会将 Maintain 报告为 Write。拒绝消息会同时显示两个字段。组织成员身份和 -`author_association` 不会通过这些检查赋予访问权限,也无需查询团队成员身份的额外 Token。 - -结果暂存检查评论作者;外部批准检查原始 `github.actor`,重跑时也不改用重跑者 -身份。暂存检出评论事件记录的默认分支提交,并运行依赖已锁定的 `infx` 包, -绝不加载 PR 代码;外部派发保留内联授权检查。现有 PR、SHA、标签历史、Source Run、Artifact 和 CODEOWNER 检查 -保持不变。其他 Workflow(包括恢复流程)保留原有的授权和派发行为。 -执行凭据和 GitHub 保护措施仍在 Workflow 中明确配置。 - -Python 工作流、Klaud 和恢复工具通过 `infx.github` 调用 `gh api`。 -运行环境必须安装 GitHub CLI;GitHub 托管 Runner 已预装。工作流 Token 仅通过该子进程的 -`GH_TOKEN` 传入,并固定访问 `github.com`;显式传入空 Token 会失败,不会回退到本地凭据。 -Klaud 和恢复工具继续使用现有的 `gh` 认证。GitHub CLI 跟随分页链接;页面格式错误、 -计数无效或列表不完整时会停止操作。Klaud 的公开错误继续过滤敏感数据。 -每次请求(包括全部分页)的超时为 60 秒。 - -## 暂存结果 - -[`stage-results.yml`](../../.github/workflows/stage-results.yml) 允许具有 Write、Maintain 或 Admin 权限的用户将 PR 结果发布到预发布环境。它不会执行合并或生产入库。 - -请求只有在全部满足下列条件时才可暂存: - -- 评论者具有仓库 `write`、`maintain` 或 `admin` 权限。 -- PR 当前具有三个完整扫描标签之一(`full-sweep-enabled`、`non-canary-full-sweep-enabled` 或 `full-sweep-fail-fast`)。 -- 候选是已结束的 PR `run-sweep.yml` Run,创建时完整扫描标签处于活动状态,结论为 `success`、`failure` 或 `cancelled`。 -- 候选按照 Workflow 当前 Head/历史 Pin 规则与该 PR 关联。 -- 存在未过期的 `changelog-metadata`,并且至少存在 `results_bmk`、`eval_results_all` 或 `bmk_agentic_*` 之一。因此失败/取消的 Run 可以暂存有用的部分数据,但空 Run 或仅有 Metadata 的 Run 不行。 - -授权维护者准确评论以下一条: - -```text -/stage-results -/stage-results -``` - -不提供 ID 时,Workflow 会选择 PR Branch 上最新的可暂存已结束 Run,并要求其 Head SHA 仍在 PR Commit 列表中。指定 ID 时允许使用明确关联的历史 Run。Workflow 会确认所选 Run,向 InferenceX-app 派发 `stage-results` 事件,并由 [`stage-results-callback.yml`](../../.github/workflows/stage-results-callback.yml) 用成功图表或失败链接替换确认评论。 - -格式正确的 `/use ` 复用请求也会触发此 Workflow,并按相同规则暂存所指定的 Run,同时保留正常的复用处理。格式错误的 `/use` 评论交由复用 Workflow 处理,不会触发暂存。 - -预发布会保留之前已暂存的 Run。再次暂存同一个 Run ID 会更新该 Run 的预发布数据。必须保留源 Run ID 与下游 App Workflow 链接;预发布成功不证明生产复用资格或合并后入库成功。 - -## 产物复用与 merge-with-reuse - -复用是已批准 PR 扫描进入正式入库的唯一路径:`main` 从不重跑扫描,[`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) 只发布经有效复用的源 Run;它不能绕过 Changelog 验证。 - -### 资格与授权 - -`infx.github` 提供仓库范围的 REST 调用、分页及评论表态基础操作,不包含扫描策略。`infx.workflows.sweep_runs` 为暂存和复用共享 PR 提交查询、已完成 Run 列表及未过期结果工件查找;各调用方保留自身的资格规则。`infx.workflows.reuse` 负责命令解析、授权查找及源 Run 的选择和验证。`infx.workflows.reuse_comment` 使用相同规则提供表态反馈。工作流通过 `python3 -m` 调用这些模块。这些辅助程序使用 Python 标准库和 GitHub CLI;从检出目录运行时无需安装 Python 包。 - -1. 复用不要求扫描标签。标签用于选择新的 GPU 工作;移除主标签不会使已有源 Run 失效。Changelog 验证和合并辅助脚本仍会拒绝冲突的主标签。 -2. PR 当前带有 `evals-only` 或 `agentx-fast` 时,复用会被拒绝。验证 `/use` 评论时、合并辅助脚本中以及合并时检查的是 PR 当前标签,而不是源 Run 的标签历史,因此只能指定在没有这些标签时产生的 Run。向 PR 推送时,带有这些标签会跳过复用 Gate,因此只要存在主标签就会启动新的扫描。默认完整扫描以及带 `all-evals` 的完整扫描仍可复用。 -3. 源 Run 必须是已结束的 PR `run-sweep.yml` Run,其 Head SHA 仍在 PR Commit 列表中,并拥有未过期的 `results_bmk`、`eval_results_all` 或 `bmk_agentic_*` 结果产物。 -4. `OWNER`、`MEMBER` 或 `COLLABORATOR` 通过 `/use ` 授权复用。必须提供 Run ID,并与命令放在同一行。原有的 `/reuse-sweep-run ` 仍然等效;不带 ID 的 `/reuse-sweep-run` 会自动选择源 Run。两种命令使用相同的授权、验证和表态规则,并以两者中最新的合格授权命令为准。 -5. 不指定 ID 时,自动选择要求最新的合格源 Run 成功。指定 Run 是维护者的明确决定,允许结论为 `success`、`failure` 或 `cancelled`;下游入库只保留存在且有效的行,因此应将其报告为部分数据,而不是绿色 Run。 - -复用验证检查源 Run 的身份和可用产物,不检查完整矩阵覆盖范围。请求被接受不代表已通过完整扫描,也不能代替评审中的完整扫描要求。如需复用某次完整扫描,请先确认其覆盖范围,再固定该 Run ID。 - -评论会触发轻量验证工作流,使用默认分支代码和 `GITHUB_TOKEN`。接受后在原评论上添加 👍,拒绝时添加 👎;拒绝原因显示在 Actions 运行摘要中。不发布额外评论,也不启动 GPU 工作。编辑命令时会清除机器人的旧表态并检查新请求。用户的表态保持不变,仍以最新的合格授权命令为准。 - -接受表示验证当时存在合格的源 Run;表态本身不构成复用授权。PR 同步及合并时仍会重新验证源 Run,产物缺失、过期或源 Commit 无效时仍会 Fail Closed。不指定 Run ID 的请求保持现有规则,每次选择最新成功 Run;如需指定某次运行,请固定 Run ID。 - -在之后的 PR `synchronize` 事件上,复用 Gate 只有在 Changelog 和源 Run 验证均通过后才会跳过另一轮 PR 扫描。合并时,`merge-ingest.yml` 会对映射不明确、指向无效 Run 或与标签冲突的授权 Fail Closed。没有授权时,Merge Ingest Run 会失败,既不会运行 Benchmark,也不会入库。 - -### 受支持的合并路径 - -在设置了 `GH_TOKEN` 或 `GITHUB_TOKEN`(或 `gh` 已认证)的干净 Checkout 中运行: - -```bash -uv run --extra workflows python -m infx.workflows.merge_with_reuse -``` - -[`merge_with_reuse.py`](../infx/workflows/merge_with_reuse.py) 会验证合格的成功源产物、发布固定到该 Run 的授权、把 `origin/main` 合并进 PR Branch、只解决 `perf-changelog.yaml` 冲突、规范化追加条目中的 `XXX` Link、按需创建并推送 Synchronization Commit、等待 `check-changelog` 和全部 PR Check、再次确认 Head 未移动,最后执行 Admin Squash Merge。它会拒绝 Fork、脏 Working Tree、多个主标签、不兼容修饰标签、意外冲突、缺少产物、失败 Check 或移动过的 PR Head。 - -不要只手工复制该序列的一半。尤其是,只发表评论后直接 Squash Merge、却不执行 Synchronization/Check 阶段,可能导致 Merge Run 无法选择预期源 Run。 - -合并时,[`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) 的 `ingest` Job 会向 InferenceX-app 发送两个不同 ID: - -- `source-run-id`:包含 Benchmark/Eval Artifact 的被复用 PR `run-sweep.yml` Run。 -- `merge-run-id`:`main` 上包含合并时 `changelog-metadata` 的 Merge Ingest Run。 - -公开数据行和链接保留源 Run 溯源。源产物覆盖范围是权威依据;后续矩阵策略变化不会凭空补出缺失点。 - -## Changelog 冲突恢复 - -每个 PR 都会在文件末尾追加,因此 `perf-changelog.yaml` 经常冲突。绝不能只接受 `ours` 或 `theirs`,也不能重新格式化或手工三方合并历史区块。 - -普通 PR 同步时,先记录 PR 编号,Fetch `main` 并合并: - -```bash -PR= -git fetch origin main -git merge origin/main -``` - -当且仅当 `perf-changelog.yaml` 是未解决文件时,在三个冲突 Stage 仍存在的情况下使用字节保留 Helper: - -```bash -python3 -m infx.workflows.prepare_perf_changelog_merge resolve-conflict \ - --changelog-file perf-changelog.yaml \ - --pr-number "$PR" \ - --repo SemiAnalysisAI/InferenceX -git add perf-changelog.yaml -git commit --no-edit -``` - -Helper 会从 Index Stage 1/2/3 读取 Merge Base、PR 与 Main 字节,验证 PR 侧 Delta,以当前 `main` 字节为起点,只重新追加唯一的 PR 贡献,规范化 PR Link,并验证最终原始字节契约。如果 Helper 拒绝,应停止:意外历史编辑、冲突的 PR Link 修正、贡献缺失或非 Changelog 冲突都需要维护者审查。不得猜测三方合并结果。 - -提交后,对 `origin/main` 运行准确 Gate: - -```bash -uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.workflows.validate_perf_changelog \ - --changelog-file perf-changelog.yaml \ - --base-ref origin/main \ - --head-ref HEAD -``` - -复用已获授权时,优先使用 [`uv run --extra workflows python -m infx.workflows.merge_with_reuse`](../infx/workflows/merge_with_reuse.py);它会一次完成冲突准备以及所需的 Synchronization/Check 序列。 - -## 产物下载与解析 - -### 下载前列出溯源 - -使用 REST Endpoint,以便跨所有分页查看过期状态、大小与时间戳: - -```bash -REPO=SemiAnalysisAI/InferenceX -RUN_ID= -gh api --paginate "/repos/$REPO/actions/runs/$RUN_ID/artifacts?per_page=100" \ - --jq '.artifacts[] | [.name, .expired, .size_in_bytes, .created_at, .updated_at] | @tsv' -gh api "/repos/$REPO/actions/runs/$RUN_ID" \ - --jq '[.id, .run_attempt, .event, .head_sha, .status, .conclusion, .html_url] | @tsv' -``` - -只下载回答当前问题所需的命名 Artifact: - -```bash -OUT="/tmp/inferencex-run-$RUN_ID" -mkdir -p "$OUT" -gh run download "$RUN_ID" --repo "$REPO" -n results_bmk -D "$OUT/results_bmk" -gh run download "$RUN_ID" --repo "$REPO" -n eval_results_all -D "$OUT/eval_results_all" -gh run download "$RUN_ID" --repo "$REPO" -n run-stats -D "$OUT/run-stats" -gh run download "$RUN_ID" --repo "$REPO" -n changelog-metadata -D "$OUT/changelog-metadata" -``` - -不要假设每个 Run 都有每个 Artifact。重要契约如下: - -| Artifact | 典型文件 | 来源 | -| --- | --- | --- | -| `results_bmk` | `agg_bmk.json` | Result Collector 找到的 `bmk_*` 吞吐量/Agentic JSON | -| `eval_results_all` | `agg_eval_all.json` | Eval Collector 汇总的 `eval_*` Artifact | -| `run-stats` | `run_stats.json` | 跨所有 Attempt 的硬件成功计数 | -| `changelog-metadata` | `changelog_metadata.json` | 扫描 Setup 的 Search-space Metadata | -| `bmk_agentic_*` | 单 Job JSON | Agentic 入库/预发布使用的原始 AgentX Result Upload | -| `server_logs_*`、`multinode_server_logs_*`、`agentic_*` | Log、Metric 或诊断 Payload | `always()`/诊断上传;名称随 Template 与模式变化 | - -### 解析有限字段 - -吞吐量聚合字段来自 [`infx/results/fixed_sequence.py`](../infx/results/fixed_sequence.py): - -```bash -jq -r ' - .[] | - [.hw, .infmax_model_prefix, .framework, .precision, - "\(.isl)/\(.osl)", .tp, .conc, - (if .tput_per_gpu == null then "" else ((.tput_per_gpu * 100 | round) / 100) end)] | - @tsv -' "$OUT/results_bmk/agg_bmk.json" -``` - -Eval 聚合字段来自 [`infx/results/collect_eval_results.py`](../infx/results/collect_eval_results.py): - -```bash -jq -r ' - .[] | - [.hw, .model_prefix, .framework, .precision, - .tp, .conc, .task, .score_name, - (if .score == null then "" else ((.score * 10000 | round) / 10000) end)] | - @tsv -' "$OUT/eval_results_all/agg_eval_all.json" -``` - -检查 Run Statistics 时,不要把 Skipped Job 与实际尝试的 Job 混为一谈。GitHub 请求失败或响应格式无效时,收集会报错;只有读取所有 Job 分页后才会写入统计结果: - -```bash -jq -r 'to_entries[] | [.key, .value.n_success, .value.total] | @tsv' \ - "$OUT/run-stats/run_stats.json" -``` - -面对不熟悉或原始 Agentic Artifact,应从 `jq 'type, keys'` 开始,并在选择字段前阅读其生产脚本。绝不能为了回答狭窄问题而加载或粘贴数 MB 的 Artifact。报告提取值时,同时给出 Run ID、Attempt、准确 Artifact 名称与过滤条件。 - -## 合并后预期 - -在 `main` 发布路径和下游入库均得到验证前,合并在运维层面并未完成。 - -1. 只有 `perf-changelog.yaml` 发生变化时,推送到 `main` 才会触发 [`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml)(Merge Ingest)。[`run-sweep.yml`](../../.github/workflows/run-sweep.yml) 仅用于 PR,从不在 `main` 上运行。确认 Merge Commit 确实产生了 Merge Ingest Run;不要假设无关合并也会触发它。 -2. 没有有效复用授权时,Merge Ingest Run 会在复用检查处失败。`main` 从不运行扫描,因此不会启动 GPU Job,不会上传 Changelog Metadata,也不会派发任何事件。合并消息中的 `[skip-sweep]` 不会改变这一点。 -3. 使用复用时,`ingest` Job 通过 `infx.workflows.reuse` 解析已合并 PR 及其源 Run。应确认 Step Output 与 Run Summary 标识了预期的 PR 与源 Run。 -4. `ingest` Job 必须先上传 `changelog-metadata` 再派发。它只发送一个事件:Changelog Delta 不含 Agentic 条目时派发 `ingest-results`;包含 Agentic 条目时携带 `database-target: production` 派发 `ingest-agentic-results`。 -5. 绿色 Dispatch Step 只证明 GitHub 接受了发往 InferenceX-app 的 Repository Dispatch。必须继续追踪下游 InferenceX-app Run,并验证预期数据行/链接和源 Run 溯源;其入库实现在本 Checkout 之外。 -6. 检查最终 Merge Ingest Run 结论、每次重跑 Attempt、源 Run 的聚合 Artifact、合并时 Metadata 与发布结果。PR 作者仍负责确保全部合并后 Actions Job 通过,包括需要有依据地重跑的偶发抖动。 -7. 如果有效 Artifact 已存在,不能仅因下游入库失败就重跑 GPU Benchmark。对于失败的复用 **Agentic** 入库,授权维护者可使用 [`recover-reused-ingest.yml`](../../.github/workflows/recover-reused-ingest.yml),传入原始 Source 与 Merge ID;该 Workflow 只派发 `ingest-agentic-results`,不是通用固定序列恢复工具: - - ```bash - gh workflow run recover-reused-ingest.yml \ - --repo SemiAnalysisAI/InferenceX \ - --ref main \ - -f source-run-id='' \ - -f merge-run-id='' - ``` - -当源 Run、Merge Run、Artifact 覆盖、Changelog Metadata 或下游 Event 含糊不清时,应停止并升级处理。绝不能替换成方便的 Run ID,也不能仅凭 Actions Dispatch 就宣称发布成功。 - - -## OperatorX 微基准 - -OperatorX 手动工作流支持 H100、H200、B200、B300、GB200、GB300、MI300X、MI325X -和 MI355X,每个分片使用一个物理 Slurm 节点。GB200/GB300 使用四卡 Arm 节点,其余 -运行器池使用八卡 x86 节点。GEMM 和 attention 每次测量只使用一张 GPU;AMD -attention 支持 torch 和 AITER。 -触发方式、覆盖范围、产物、取消及验证说明见 -[OperatorX GitHub Actions](../../operatorx/CI_zh.md)。 - diff --git a/inferencex-e2e/docs/eval-agentx-procedures.md b/inferencex-e2e/docs/eval-agentx-procedures.md index def8c75a05..965536af3a 100644 --- a/inferencex-e2e/docs/eval-agentx-procedures.md +++ b/inferencex-e2e/docs/eval-agentx-procedures.md @@ -1,11 +1,5 @@ # Evaluation and AgentX Procedures -
- -**English** | [中文](eval-agentx-procedures_zh.md) - -
- Use this page to add and run graded evals, operate AgentX trace replays, preserve evidence, and decide whether a long run should continue. Commands assume `inferencex-e2e/` as the working directory and replace values in ``. diff --git a/inferencex-e2e/docs/eval-agentx-procedures_zh.md b/inferencex-e2e/docs/eval-agentx-procedures_zh.md deleted file mode 100644 index fc5a363c29..0000000000 --- a/inferencex-e2e/docs/eval-agentx-procedures_zh.md +++ /dev/null @@ -1,354 +0,0 @@ -# 评估与 AgentX 操作流程 - -
- -[English](eval-agentx-procedures.md) | **中文** - -
- - -使用本页添加和运行评分 eval、操作 AgentX trace replay、保留证据,并判断长时间运行是否应继续。命令均假定当前目录为 `inferencex-e2e/`;请替换 `` 中的值。 - -若只需对已有服务运行回放客户端,请参阅[独立运行 AgentX-Harness](agentx-standalone_zh.md)。 -该指南包含安装步骤和直接执行的 `aiperf profile` 命令,无需 CI 或 Slurm。 - -## 1. 选择正确的执行模式 - -若 PR sweep 只需测试吞吐量,请在相应的 `perf-changelog.yaml` 条目中设置 -`no-evals: true`,并使用一个主要 sweep label(通常为 `full-sweep-fail-fast`)。这会跳过 -这些条目的所有 eval 作业,不改变 benchmark 时长或 Prometheus 产物。 -该选项默认为 false,且保留在 changelog 元数据中。其他条目仍可为同一配置 -选择 eval;若需完全禁用,请在所有相关条目中设置该选项。设置 `no-evals` 的条目 -不能同时设置 `all-evals`、`evals-only` 或 `eval-min-prefill-ep`,PR 也不能带有任一 -eval modifier,这些组合都会被拒绝。这类运行提供吞吐量证据,不提供模型评估证据。 - -这里有两个不同层次:矩阵生成器决定**存在哪些作业**,运行时变量决定**已启动作业执行什么操作**。 - -| 需求 | 生成器参数(`infx.matrix.generate`)或工作流变量 | 运行时行为 | -|---|---|---| -| 常规 sweep | 不加 eval 选项 | 吞吐量作业,加上选定的 8k/1k eval 子集和 agentic GSM8K 子集 | -| 仅吞吐量 | `--no-evals` | 不生成 eval 作业 | -| 仅选定的 eval 子集 | `--evals-only` | 作业带有 `RUN_EVAL=true`、`EVAL_ONLY=true` | -| 仅运行所有符合条件的 eval | `--all-evals` | 等价于 `--evals-only --all-evals`;包含全部定长序列 8k/1k 行,以及单节点和多节点 agentic GSM8K 行 | -| 在一个 recipe 中先跑吞吐量再跑 eval | `RUN_EVAL=true`、`EVAL_ONLY=false` | 启动服务,运行吞吐量,然后执行 `python3 -m infx.bench eval` | -| 对新启动的服务仅运行 eval | `RUN_EVAL=true`、`EVAL_ONLY=true` | 启动器应用仅评估模式的服务设置,跳过吞吐量并运行评估 | - -PR 上的 `all-evals` 标签则通过 [`infx.matrix.plan`](../infx/matrix/plan.py) 生成矩阵,会扩大 eval 选择范围并保留吞吐量作业。 - -默认选择会区分场景。单节点定长序列 eval 对每个 8k/1k 的模型/runner/framework/precision/并行配置分组选取符合条件的中位和最高并发;多节点 eval 对每种拓扑选取符合条件的最高并发。定长序列中低于 16 的并发不会被选中。所有 AgentX 模型(包括 Kimi K3 和 MiniMax M3)默认都会运行 GSM8K。单节点 agentic 行按模型/runner/framework/precision/spec-decoding/dp-attn/镜像分组,并在每组最高并发处评估:MTP、DP attention 和镜像不同的变体各自单独评估,而 TP/EP 和 KV offloading 不同的变体共用一次评估。多节点 agentic 行对每种拓扑选取符合条件的最高并发;若某个部署没有任何并发不低于 16 的拓扑,则在其最高并发处评估一次。Kimi K3 和 MiniMax M3 的行还会在每个生成的测试点(包括低并发测试点)额外运行厂商评估,因此它们的 GSM8K 是一条额外的 eval-only 行。所有评估都作为独立的 eval-only 作业运行,因此 agentic 吞吐量覆盖范围不变。参见 [`mark_eval_entries()` 和 `mark_all_eval_entries()`](../infx/matrix/generate.py)。 - -Kimi K3 在 AMD 和 NVIDIA 的单节点及多节点 recipe 上自动运行 `kimi-vendor` / `kimi_tool_call_schema_full`。完整套件对 204 个独立 schema 用例分别执行流式和非流式请求,共产生 408 项检查。快速诊断时,仍可显式设置工作流输入 `eval-framework=kimi-vendor` 和 `eval-suite=kimi_tool_call_schema`,运行一个用例、两项检查的冒烟评估。`--trim-conc` 只裁剪部署测试点,不缩减套件用例数。MiniMax M3 在两家硬件厂商上自动运行 `minimax-vendor` / `minimax_m3_full`,覆盖全部 102 个厂商用例;仍可通过显式覆盖选择单用例 `minimax_m3_smoke`。定长序列的 GSM8K 选择策略保持不变。 - -解读分数时应同时查看任务名和 `n_eff`:`kimi_tool_call_schema = 1.0, n_eff = 2` 表示一个 schema 用例在两种模式下均通过,不能视为完整套件结果或 GSM8K 分数。历史冒烟产物保留原有标识。Kimi 完整套件仍采用 `0.0` 的质量阈值,仅报告诊断分数;检查项缺失、准备失败和集成错误仍会使作业失败。参见[套件定义与产物约定](../infx/evals/EVALS.md#how)。 - -Kimi 厂商完整套件不再设置适配器层面的整进程超时。原生验证器的请求超时、引擎就绪等待上限,以及工作流和调度器的资源分配时限仍然生效。冒烟评估保留 900 秒超时;直接调用 Python 适配器时,可通过正数 `--timeout-seconds` 参数为任一套件显式设置超时。 - -在 PR 上,应将一个主要 sweep label(通常为 `full-sweep-fail-fast`)与 eval modifier 组合使用。`all-evals` 在不抑制吞吐量的情况下扩大覆盖范围;`evals-only` 会抑制吞吐量;两者一起使用时只运行所有符合条件的 eval。带有 `evals-only` 的运行不可复用,而常规 full sweep 和 `all-evals` full sweep 可以复用。添加或移除 modifier 会重启当前 sweep([label 策略](ci-procedures_zh.md#pr-主标签与修饰标签))。 - -```bash -# Selected eval subset only -gh pr edit --repo SemiAnalysisAI/InferenceX \ - --add-label full-sweep-fail-fast --add-label evals-only - -# Every eligible eval only -gh pr edit --repo SemiAnalysisAI/InferenceX \ - --add-label full-sweep-fail-fast --add-label all-evals --add-label evals-only -``` - -在占用 runner 前预览准确矩阵: - -```bash -uv run --no-project --exclude-newer PT12H --python 3.12 --with pydantic --with pyyaml \ - python -m infx.matrix.generate \ - test-config \ - --config-keys qwen3.5-fp8-b200-sglang-agentic \ - --conc 1 \ - --evals-only \ - --config-files configs/nvidia-master.yaml | jq . -``` - -正确的 AgentX eval 行包含 `"scenario-type": "agentic-coding"`、`"run-eval": true` 和 `"eval-only": true`。工作流会在 [`.github/workflows/e2e-tests.yml`](../../.github/workflows/e2e-tests.yml#L328-L335) 中将生成的行拆分到吞吐量、定长序列 eval 和 agentic eval 作业。 - -## 2. 添加评分 eval - -1. 按照 lm-evaluation-harness task 格式添加 `infx/evals/.yaml`。固定 dataset/split、确定性生成设置、prompt 约定、filter 和主指标。可参考仓库内的 [`gsm8k.yaml`](../infx/evals/gsm8k.yaml) 或 [`gpqa_diamond.yaml`](../infx/evals/gpqa_diamond.yaml)。 -2. 为 `task:` 指定稳定名称。分数阈值以该精确名称为键,收集后的行中也会出现该名称。 -3. 在 [`infx/evals/thresholds.yaml`](../infx/evals/thresholds.yaml) 中添加最低可接受分数。通用下限放在 `default`;只有在确有依据需要模型专用下限时,才添加 `models..`。 -4. 如果 task 的主结果与 collector 的 strict/extract/accuracy 规则不兼容,请扩展 [`infx.results.evals`](../infx/results/evals.py) 中的 `extract_metrics()`。该函数接收已加载的 JSON 和显式来源信息;`build_rows()` 应用收集器的分数验证及元数据转换规则。发布为成功结果的行必须具有非 null 的 `score`。 -5. 先运行一个显式的小切片并检查样本,再运行完整 split。`EVAL_LIMIT` 是 smoke test 控制项,不是可发布分数的运行设置。 - -对已经健康的 OpenAI-compatible 服务执行: - -```bash -export MODEL='' -export MODEL_NAME='' -export MODEL_PREFIX='' -export PORT='' -export EVAL_ONLY=false IS_MULTINODE=false OPENAI_API_KEY=EMPTY -export EVAL_TASKS_DIR='infx/evals/.yaml' -export EVAL_LIMIT='10' -EVAL_DIR="$(mktemp -d /tmp/eval_out-XXXXXX)" -PYTHONSAFEPATH=1 PYTHONPATH="$PWD${PYTHONPATH:+:$PYTHONPATH}" python3 -m infx.bench eval \ - --endpoint "http://localhost:$PORT" --concurrency 16 --stage-to "$EVAL_DIR" -python3 -m infx.evals.validate_scores \ - --model-prefix "$MODEL_PREFIX" \ - --meta-env "$EVAL_DIR/meta_env.json" \ - --results-glob "$EVAL_DIR/results*.json" -``` - -完整 eval 需要取消 limit,并在干净且配置正确的服务上重复执行: - -```bash -unset EVAL_LIMIT -EVAL_DIR="$(mktemp -d /tmp/eval_out-XXXXXX)" -PYTHONSAFEPATH=1 PYTHONPATH="$PWD${PYTHONPATH:+:$PYTHONPATH}" python3 -m infx.bench eval \ - --endpoint "http://localhost:$PORT" --concurrency 16 --stage-to "$EVAL_DIR" -python3 -m infx.evals.validate_scores --model-prefix "$MODEL_PREFIX" \ - --meta-env "$EVAL_DIR/meta_env.json" --results-glob "$EVAL_DIR/results*.json" -``` - -请使用 Python 3.10 或更高版本运行这些命令,通常在服务容器内执行,因为 lm-eval 会通过 `uv pip` 把固定版本的 harness 安装到该 `python3` 中。该命令会把允许列表中的产物复制到 `--stage-to`,并在该目录写入 `meta_env.json`。并发取自 `--concurrency`,lm-eval 通过 `--model_args` 中的 `num_concurrent` 接收该值。命令不再读取 `EVAL_CONCURRENT_REQUESTS`。准确调用见 [`infx.bench.eval.lm_eval.run`](../infx/bench/eval/lm_eval.py#L121-L150)。 - -## 3. `EVAL_ONLY` 是 launcher 约定 - -必须在**启动服务前**设置 `EVAL_ONLY=true`。它不仅是评估命令内部的开关: - -1. 对单节点定长序列作业,srt binder 会把服务上下文设为矩阵中的 `MAX_MODEL_LEN`(`isl + osl + 256`),SGLang 使用 `context-length`,TRT-LLM 使用 `max_seq_len` 和 `max_num_tokens`,vLLM 与 ATOM 使用 `max-model-len`。AgentX 测试点和多节点作业保留配方自身的上下文,多节点作业还可选择用于真实验证的 `EVAL_CONFIG_FILE`。 -2. 仍会运行健康检查。在仅评估作业中,厂商评估框架还会在 `EVAL_ENDPOINT_READY_TIMEOUT_SECONDS` 内等待服务模型出现在 OpenAI chat 路由上。 -3. 跳过吞吐量测试。 -4. `python3 -m infx.bench eval` 按 `EVAL_MAX_MODEL_LEN` 确定每个 lm-eval 请求的预算。未设置时使用 `MAX_MODEL_LEN`,并以模型原生上限为界。 -5. 同一命令会暂存产物并写入 `meta_env.json`,无论评估成功还是失败。 - -相关实现:[服务上下文](../infx/srt_slurm/single_node.py#L183-L194)、[请求预算](../infx/bench/eval/lm_eval.py#L77-L98)、[评估分派与失败策略](../infx/bench/eval/__init__.py#L74-L173) 和[工作流输入](../../.github/workflows/benchmark-tmpl.yml#L36-L53)。 - -原生多节点 post-eval 从 `/model` 读取挂载的检查点,并仅在评估进程中启用数据集下载,不改变工作进程环境。上下文查询先读取本地 `config.json` 中的数值上限,再回退到 Transformers;显式设置的 `EVAL_MAX_MODEL_LEN` 仍优先。 - -不要在吞吐量规格的服务已经运行后才切换 `EVAL_ONLY`,并假定 context 会随之变化。应通过 recipe 重启。Eval-only 模式会在暂存已有 artifact 后返回 eval 失败;在工作流中,上传步骤使用 `always()`,并位于分数校验前,因此失败证据仍会保留([单节点上传与 gate](../../.github/workflows/benchmark-tmpl.yml#L449-L472)、[多节点上传与 gate](../../.github/workflows/benchmark-multinode-tmpl.yml#L477-L503))。 - -## 4. 批量 eval 并发 - -空格分隔的 `--concurrency` 值会让多个并发点在**同一个存活的 engine 上依次执行**。多节点作业以这种方式传入 `EVAL_CONC`。它不会同时运行多个 harness。每个并发点内部,harness 最多发出该并发数的请求。 - -```bash -export MODEL='' MODEL_NAME='' MODEL_PREFIX='' -export PORT='' EVAL_TASKS_DIR='infx/evals/gsm8k.yaml' -export EVAL_ONLY=false IS_MULTINODE=false OPENAI_API_KEY=EMPTY -EVAL_DIR="$(mktemp -d /tmp/eval_out-XXXXXX)" -PYTHONSAFEPATH=1 PYTHONPATH="$PWD${PYTHONPATH:+:$PYTHONPATH}" python3 -m infx.bench eval \ - --endpoint "http://localhost:$PORT" --concurrency '16 32 64' --stage-to "$EVAL_DIR" -python3 -m infx.evals.validate_scores --expected-concs '16 32 64' \ - --meta-env "$EVAL_DIR/meta_env.json" --results-glob "$EVAL_DIR/results*.json" -``` - -批量 runner 会为每个点创建新的临时输出目录,用 `_conc` 后缀暂存文件,并向 `meta_env.json` 写入以下数组: - -- `eval_concs`:请求的点; -- `completed_eval_concs`:评估成功且至少暂存了一个产物的点; -- `failed_eval_concs`:评估或其暂存失败,或未暂存任何产物的点。 - -失败点会延迟报错,使所有已尝试点的 artifact 都能上传;随后 post-upload validator 会使作业失败。批量模式只接受正整数,且仅支持 `lm-eval`。参见[批量执行](../infx/bench/eval/__init__.py#L176-L211)、[产物后缀处理](../infx/bench/eval/stage.py#L20-L43) 和[manifest 校验](../infx/evals/validate_scores.py#L119-L216)。 - -对于多节点 `all-evals`,工作流通过连接拓扑的并发列表构造 `EVAL_CONC`([分派](../../.github/workflows/e2e-tests.yml#L390-L392))。如果缺少某点的 `_conc` 结果或 completed manifest 条目,绝不能比较该点。 - -## 5. 校验分数,而不只是检查文件存在 - -运行: - -```bash -python3 -m infx.evals.validate_scores \ - --thresholds infx/evals/thresholds.yaml \ - --meta-env meta_env.json \ - --results-glob 'results*.json' -``` - -批量运行还应加入独立确认的预期点: - -```bash -python3 -m infx.evals.validate_scores \ - --expected-concs '16 32 64' \ - --thresholds infx/evals/thresholds.yaml -``` - -阈值按以下顺序解析:`models..`、`default.`,最后是 `--min-score`(默认 `0.85`)。默认检查名称以 `exact_match,` 开头、数值类型且非 stderr 的指标。当分数低于阈值、没有匹配指标、缺少请求的并发、metadata 有重复或无效值、任何点被标记为失败,或结果后缀与 manifest 不一致时,校验都会失败。当前权威下限位于 [`thresholds.yaml`](../infx/evals/thresholds.yaml)。参见[阈值解析](../infx/evals/validate_scores.py#L63-L73)与[校验流程](../infx/evals/validate_scores.py#L219-L373)。 - -手动的吞吐量+eval 组合 recipe 会上传 eval 输出,但模板的自动分数 gate 专用于 eval-only 作业。对手动或组合运行必须显式执行 validator。 - -## 6. 收集并检查 eval artifact - -收集工作流会下载 `eval_*`,用 `infx/results/collect_eval_results.py` 聚合原始集合,上传 `eval_results_all/agg_eval_all.json`,并将表格写入 step summary([`collect-evals.yml`](../../.github/workflows/collect-evals.yml))。 - -```bash -RUN_ID='' -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --name eval_results_all --dir ./evals -jq -r '.[] | [.hw, .framework, .precision, .tp, .conc, .task, - (.score * 100 | round | . / 100)] | @tsv' \ - ./evals/agg_eval_all.json | column -t -jq '[.[] | select(.hw == "B200")]' ./evals/agg_eval_all.json -``` - -当 aggregate 缺失或可疑时,下载原始证据: - -```bash -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --pattern 'eval_*' --dir ./evals/raw -``` - -保留 `meta_env.json`、`results*.json` 和 `sample*.jsonl`。Aggregate 是导航工具,不能替代原始样本与 batch 完整性证据。 - -## 7. 运行 AgentX:快速反馈与 canonical 证据 - -`python3 -m infx.bench agentic` 会用 uv 自行构建客户端运行时([`infx/bench/agentic/venv.py`](../infx/bench/agentic/venv.py))。它在 `AIPERF_RUNTIME_DIR` 下新建 Python 3.11 venv(默认 `/inferencex-agentic-`),以可编辑模式安装 `utils/aiperf` 及其声明的依赖,并安装 AIPerf 未声明的 client 依赖([`requirements.txt`](../infx/bench/agentic/requirements.txt))。随后它会在该 venv 的 Python 下重新运行自身。Recipe 通过 [`benchmarks/srt_agentic.sh`](../benchmarks/srt_agentic.sh) 调用它。 - -AgentX 是 AIPerf `agentx` trace replay,不是固定 token 的合成 benchmark。`agentx` scenario 负责 replay 默认值:每条 trajectory lane 额外执行十个 warmup 请求、warmup 排空上限为 1,800 秒、实时失败阈值为 0.10、trace 空闲上限为 300 秒。Recipe 可以用 `AGENTIC_WARMUP_GRACE_PERIOD` 提高排空上限,或用 `AIPERF_LIVE_FAILED_REQUEST_THRESHOLD` 放宽实时中止阈值;完成后的 profile 错误率超过 0.10 时仍会校验失败([运行后校验](../infx/bench/agentic/run.py#L33-L35))。Profile 使用配置的时长。`agentx-fast` 强制每条 lane 只运行一个 warmup 请求,并将 profile 设为 1,200 秒。它只影响单节点和多节点 AgentX 吞吐量;定长序列吞吐量与 eval 保持 canonical。Fast 运行不符合 artifact reuse 条件([工作流策略](ci-procedures_zh.md#pr-主标签与修饰标签)、[fast replay 设置](../infx/bench/agentic/replay.py#L64-L65))。 - -每个 AgentX 吞吐量并发点都必须使用新启动的服务。矩阵为每个点生成独立作业。`infx.launch` 会拒绝 `CONC_LIST` 不恰好等于其唯一正整数 `CONC` 的多节点 AgentX 吞吐量作业,replay client 也会拒绝与 `CONC` 不同的 `CONC_LIST`。AgentX 不清空缓存,也不复用正在运行的服务来测试另一个并发点。同一测试点的预热和正式测量共用服务。此规则不改变定长序列 sweep 或评分 eval 的批量执行行为。 - -对于多节点 srt-slurm 作业,benchmark client 与 frontend 可能运行在不同主机上。只要设置了 `SRT_FRONTEND_HOST`,replay 就以 `http://$SRT_FRONTEND_HOST:$SRT_FRONTEND_PORT` 为目标,否则使用显式提供的 `AIPERF_SERVER_URL`,两者都没有时才回退到 `http://localhost:$PORT`([`_server_url`](../infx/bench/agentic/replay.py#L115-L122))。 - -对于未发布到 package index 的 engine 或 router wheel,必须保证构建可复现且 artifact 不可变:在 launcher 旁签入源码 patch 与构建器,打 patch 前校验上游 wheel 的 digest,分配明确的 local version,并通过带 SHA256 fragment 的精确 URL 安装已发布 artifact。本地 backport 不得冒用尚未发布的上游版本号。 - -目标 canonical 运行(使用配置的 duration 和 warmup;不要加 fast 或 duration override): - -```bash -REF='' -gh workflow run e2e-tests.yml --repo SemiAnalysisAI/InferenceX --ref "$REF" \ - -f generate-cli-command='test-config --config-keys qwen3.5-fp8-b200-sglang-agentic --conc 1 --config-files configs/nvidia-master.yaml' \ - -f test-name='agentx-canonical-qwen35-c1' -``` - -快速诊断运行: - -```bash -gh workflow run e2e-tests.yml --repo SemiAnalysisAI/InferenceX --ref "$REF" \ - -f generate-cli-command='test-config --config-keys qwen3.5-fp8-b200-sglang-agentic --conc 1 --config-files configs/nvidia-master.yaml' \ - -f test-name='agentx-fast-qwen35-c1' \ - -f agentx-fast=true -``` - -Fast 结果只能作为 bring-up 证据,绝不能替代 canonical candidate。小于 900 秒的 duration 会添加 AIPerf 的 `--unsafe-override` 并将 submission 标记为无效;只能用于 smoke 诊断([源码](../infx/bench/agentic/replay.py#L105))。Fast 运行健康后,必须对完全相同的 candidate 进行 canonical 运行,才能宣称 benchmark 成功。 - -## 8. 保留 trace 与运行 provenance - -AgentX 默认 replay 已记录的 assistant response。实时服务输出会被测量,但构造后续 turn 时会丢弃。除非用 `WEKA_LOADER_OVERRIDE` 固定为 `semianalysis_cc_traces_weka_062126` 或 `semianalysis_cc_traces_weka_062126_256k`,否则所选 trace corpus 依赖模型 family;resolver 会同时记录 loader 与 Hugging Face dataset([trace 解析](../infx/bench/agentic/traces.py#L20-L25)、[replay 语义](../infx/bench/agentic/replay.py#L150-L185))。Replay 保留模型的原生上下文。客户端忽略 `MAX_MODEL_LEN`,只有显式设置的 `AIPERF_MAX_CONTEXT_LENGTH` 才会添加 AIPerf 的 `--max-context-length`。 - -立即记录 orchestration provenance: - -```bash -RUN_ID='' -gh run view "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --json url,headSha,headBranch,event,status,conclusion,createdAt,updatedAt,jobs \ - > run-provenance.json -``` - -下载 AgentX 证据: - -```bash -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --pattern 'bmk_agentic_*' --dir ./agentx/aggregate -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --pattern 'agentic_*' --dir ./agentx/raw -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --pattern '*server_logs_*' --dir ./agentx/server-logs -``` - -每个并发点都应保留: - -- `benchmark_command.txt`(准确 AIPerf 命令)和 `benchmark.log`; -- AIPerf `profile_export*`、`server_metrics_export.json`、plot 和 distribution analysis; -- aggregate JSON 及其 `dataset` 对象(`source_type`、loader、HF dataset/split、entry count); -- server/frontend 日志以及所代表的每个 metrics endpoint; -- run URL/ID、attempt、head SHA、recipe/config 标识、image、topology、fast 标志和所有 override。 - -Runner 会在 replay 前写入命令,并在聚合后校验原始结果([执行路径](../infx/bench/agentic/run.py#L122-L197))。聚合会保留 dataset provenance 以及硬件/模型/拓扑字段([aggregate 构造](../infx/results/agentic/__init__.py))。工作流的 raw upload 会有意排除体积很大的 `inputs.json` 和 `profile_export_raw.jsonl`;如果调查需要这些文件,应在清理前从实时 allocation 保存([单节点 artifact 约定](../../.github/workflows/benchmark-tmpl.yml#L382-L391)、[多节点约定](../../.github/workflows/benchmark-multinode-tmpl.yml#L466-L475))。 - -## 9. 用实时证据调试长时间 AgentX 运行 - -GitHub Actions 是 orchestration/最终状态视图;cluster 是实时诊断来源。从 InferenceX Clusters canvas 获取 SSH alias、runner user 和受访问控制的路径。绝不要猜测或公开私有基础设施坐标。 - -解析准确的矩阵作业: - -```bash -gh run view --repo SemiAnalysisAI/InferenceX --json jobs \ - --jq '.jobs[] | select(.name | test("agentic|AgentX"; "i")) | - [.databaseId, .status, .conclusion, .name] | @tsv' -``` - -在 controller 上识别并核实 allocation: - -```bash -squeue -u -o "%.8i %.8T %.10M %.20N %.100j" -scontrol show job -o | tr " " "\n" | \ - grep -E '^(JobId|JobState|RunTime|TimeLimit|NodeList|WorkDir)=' -``` - -根据 `WorkDir` 推导 ``;srt-slurm 通常使用 `/outputs//logs/`。先清点,再选择文件: - -```bash -find "" -maxdepth 1 -type f -print | sort -``` - -始终从头包含 custom benchmark 日志,然后加入所有与拓扑相关的 backend 和 frontend/router 日志: - -```bash -ssh 'tail -f -n+1 "/benchmark.out"' -tail -F -n+1 -rg -n -i 'Phase |warmup|profiling|returned=|in_flight=|queue=|kv_usage=|prefix_cache_hit=|tput_|ERROR|Traceback|OOM|NCCL|RCCL|timeout|connection refused' -``` - -拓扑规则: - -- Aggregated:检查每个 aggregate backend;attention DP 可能暴露多个 metrics source,但它不是 disaggregation。 -- Disaggregated:检查每个 prefill backend、每个 decode backend 以及 frontend/router。Decode pool 健康不能证明 prefill/KV transfer 健康。 -- 确认 AIPerf 命令包含所有 `AIPERF_SERVER_METRICS_URLS`;缺少 endpoint 会产生片面而虚假的健康证据。 - -Summary 不明确时直接读取每个 endpoint: - -```bash -curl -fsS '' | \ - rg -i 'request|queue|cache|token|prefill|decode|error|fail' -``` - -通过重复 sample 跟踪趋势:running/waiting request、KV usage、prefix hit、input/output token rate、completed/cancelled/errored request、frontend routing balance,以及 disaggregated KV transfer。AIPerf 会为每条 server series 记录 endpoint identity([metrics 接线](../infx/bench/agentic/replay.py#L125-L147))。未设置 `AIPERF_SERVER_METRICS_URLS` 且 `SRTCTL_FRONTEND_TYPE` 不是 `dynamo` 时,replay 会从 `SRT_AGG_ENDPOINTS`,或从 `SRT_PREFILL_ENDPOINTS` 加 `SRT_DECODE_ENDPOINTS`,抓取每个 worker 的 `/metrics`。 - -应使用 phase marker,而不是 Slurm 总运行时间: - -```bash -grep -E 'Phase warmup progress|WARMUP cache pressure|Phase warmup complete|Phase profiling started|Phase profiling complete|process_agentic_result' \ - "/benchmark.out" -date -u -``` - -报告 phase 已用/剩余时间、最后日志更新时间、错误数、request/queue/KV 趋势、已检查的文件和 metric source,并分别给出预计 benchmark 完成时间与预计 GitHub 完成时间。在必需 artifact 上传且工作流接受它们之前,运行不能算 green。 - -## 10. 提前终止规则 - -当直接证据已经足以判定配置不合格时,应建议提前停止: - -- 确定性 OOM、NCCL/RCCL 失败、parser crash 或 worker 缺失; -- 多次重复 sample 中 counter 与日志时间戳均没有前进; -- KV usage 长期接近 100%,queue 持续增长且 latency 已不可用; -- 吞吐量已经平台化,而更高并发只会恶化 TTFT/TPOT; -- 任意 disaggregated pool 或必需 metrics source 始终未注册; -- AIPerf 校验显示 completed request 为零,或错误率超过配置的 `0.10` 上限([validator](../infx/results/agentic/validate_agentic_result.py#L48-L88))。 - -如果 completion 持续增加且 queue 稳定,不要仅因模型加载、dataset 配置、warmup、cutoff drain 或 profiling 较慢而停止。任何取消前,都要捕获时间戳、准确拓扑、相关日志行、至少两个体现趋势的 metric sample、当前 phase 和诊断结论。 - -取消操作会修改共享基础设施。除非当前任务已明确授权,否则必须先询问。优先从 GitHub 取消,以便工作流执行 cleanup: - -```bash -gh run cancel --repo SemiAnalysisAI/InferenceX -``` - -只有在获得明确批准且有具体理由时才使用 `scancel` 或终止进程;否则可能绕过 cleanup 或使 runner 残留。修复 recipe 后,先分派一个目标 fast e2e 点并实时检查,只有通过检查的 candidate 才值得进行 canonical 运行/完整 sweep。 - -## 完成检查清单 - -- 矩阵预览符合预期 scenario、topology、eval mode 与 concurrency。 -- 完整 eval 未设置 `EVAL_LIMIT`;每个预期 batch 点都已完成且有带后缀的结果。 -- `validate_scores.py` 针对预期 task/model 阈值通过。 -- Aggregate 与 raw eval/AgentX artifact 均已下载且内部一致。 -- 已记录 AgentX corpus、replay mode、准确命令、commit、image、recipe、topology 以及 fast/override 状态。 -- 每个 backend/frontend 与 metrics source 都在实时证据中有所体现。 -- Fast/smoke 结果明确标为诊断用途;只有 canonical candidate 用于最终比较。 -- 在报告成功前,工作流与 artifact collection 均已得出 green 结论。 diff --git a/inferencex-e2e/docs/index.md b/inferencex-e2e/docs/index.md index 49e2ad0b41..18cccedf2e 100644 --- a/inferencex-e2e/docs/index.md +++ b/inferencex-e2e/docs/index.md @@ -1,11 +1,5 @@ # InferenceX Documentation -
- -**English** | [中文](index_zh.md) - -
- This is the mandatory low-context router for InferenceX work. Pick the one page that owns the task, then follow only its source links. Repository source files and workflows remain authoritative. Paths and shell commands in these guides are relative to `inferencex-e2e/` unless stated otherwise. The Python manifest, lockfile, and `.python-version` live in that project directory. Repository-wide policy and GitHub workflows remain at the repository root. @@ -33,17 +27,17 @@ Paths and shell commands in these guides are relative to `inferencex-e2e/` unles | Page | Open it for | | --- | --- | -| [`index.md`](index.md) / [`index_zh.md`](index_zh.md) | This task router and its Chinese counterpart | -| [`architecture.md`](architecture.md) / [`architecture_zh.md`](architecture_zh.md) | Config-to-result flow, ownership boundaries, artifacts, and InferenceX-app handoff | +| [`index.md`](index.md) | This task router | +| [`architecture.md`](architecture.md) | Config-to-result flow, ownership boundaries, artifacts, and InferenceX-app handoff | | [`power_model` README](../../power_model/README.md) | Installation, CLI usage, supported systems, and power-model assumptions | -| [`ci-procedures.md`](ci-procedures.md) / [`ci-procedures_zh.md`](ci-procedures_zh.md) | Matrix generation, validation, dispatch, PR sweeps, reuse, staging, and artifact downloads | -| [`eval-agentx-procedures.md`](eval-agentx-procedures.md) / [`eval-agentx-procedures_zh.md`](eval-agentx-procedures_zh.md) | Eval and AgentX selection, execution, scoring, evidence, and live-run diagnosis | -| [`agentx-standalone.md`](agentx-standalone.md) / [`agentx-standalone_zh.md`](agentx-standalone_zh.md) | Install the pinned AgentX client and replay traces against an existing server without CI or Slurm | -| [`results-and-ingestion.md`](results-and-ingestion.md) / [`results-and-ingestion_zh.md`](results-and-ingestion_zh.md) | Published-result lookup, artifact identities and schemas, app ingestion, dedupe, and provenance | -| [`recovery-results-procedures.md`](recovery-results-procedures.md) / [`recovery-results-procedures_zh.md`](recovery-results-procedures_zh.md) | Result processing, ingest verification and recovery, runner cleanup, and failure classification | -| [`testing.md`](testing.md) / [`testing_zh.md`](testing_zh.md) | Local checks, smoke runs, evidence standards, and review gates | -| [`troubleshooting.md`](troubleshooting.md) / [`troubleshooting_zh.md`](troubleshooting_zh.md) | Failure-layer diagnosis, known cases, safe remediation, and stop conditions | -| [`PR_REVIEW_CHECKLIST.md`](PR_REVIEW_CHECKLIST.md) / [`PR_REVIEW_CHECKLIST_zh.md`](PR_REVIEW_CHECKLIST_zh.md) | CODEOWNER review and exact sign-off requirements | +| [`ci-procedures.md`](ci-procedures.md) | Matrix generation, validation, dispatch, PR sweeps, reuse, staging, and artifact downloads | +| [`eval-agentx-procedures.md`](eval-agentx-procedures.md) | Eval and AgentX selection, execution, scoring, evidence, and live-run diagnosis | +| [`agentx-standalone.md`](agentx-standalone.md) | Install the pinned AgentX client and replay traces against an existing server without CI or Slurm | +| [`results-and-ingestion.md`](results-and-ingestion.md) | Published-result lookup, artifact identities and schemas, app ingestion, dedupe, and provenance | +| [`recovery-results-procedures.md`](recovery-results-procedures.md) | Result processing, ingest verification and recovery, runner cleanup, and failure classification | +| [`testing.md`](testing.md) | Local checks, smoke runs, evidence standards, and review gates | +| [`troubleshooting.md`](troubleshooting.md) | Failure-layer diagnosis, known cases, safe remediation, and stop conditions | +| [`PR_REVIEW_CHECKLIST.md`](PR_REVIEW_CHECKLIST.md) | CODEOWNER review and exact sign-off requirements | ## Authoritative references @@ -58,8 +52,8 @@ Paths and shell commands in these guides are relative to `inferencex-e2e/` unles | [`benchmarks/multi_node/srt-slurm-recipes/RECIPES.md`](../benchmarks/multi_node/srt-slurm-recipes/RECIPES.md) | Disaggregated recipe registration and master-config coupling | | [`utils/runner_setup/RUNNER_SETUP.md`](../utils/runner_setup/RUNNER_SETUP.md) | Runner provisioning and setup | | [`MODELS.md`](MODELS.md) | Supported models, hardware coverage, and naming | -| [`klaud.md`](klaud.md) / [`klaud_zh.md`](klaud_zh.md) | Klaud Cold selection, ownership, validation and recovery | -| [`klaud-reporting.md`](klaud-reporting.md) / [`klaud-reporting_zh.md`](klaud-reporting_zh.md) | Klaud PR body, progress comments, numeric comparisons and final preflight | +| [`klaud.md`](klaud.md) | Klaud Cold selection, ownership, validation and recovery | +| [`klaud-reporting.md`](klaud-reporting.md) | Klaud PR body, progress comments, numeric comparisons and final preflight | | [`benchmarks/srt_agentic.sh`](../benchmarks/srt_agentic.sh) | AgentX trace replay client shared by single- and multi-node srt-slurm recipes | ## Context rules @@ -67,4 +61,4 @@ Paths and shell commands in these guides are relative to `inferencex-e2e/` unles 1. Open only the focused page and source sections needed for the task. 2. Do not load large YAML, JSON, logs, generated matrices, or whole reference files when a filtered view answers the question. 3. Source code, workflow YAML, schemas, launchers, and collectors win over explanatory docs. -4. When behavior changes, update the nearest English guide first and its `_zh.md` counterpart in the same change. +4. When behavior changes, update the nearest English guide. Only READMEs retain Chinese translations; update an existing `README_zh.md` alongside its English README, and do not create Chinese counterparts for other docs. diff --git a/inferencex-e2e/docs/index_zh.md b/inferencex-e2e/docs/index_zh.md deleted file mode 100644 index 0019efa9b0..0000000000 --- a/inferencex-e2e/docs/index_zh.md +++ /dev/null @@ -1,69 +0,0 @@ -# InferenceX 文档 - -
- -[English](index.md) | **中文** - -
- -这是 InferenceX 工作的必读低上下文路由页。只选择负责当前任务的一份页面,再按需打开其中链接的源文件。仓库源文件与 Workflow 仍是行为的权威来源。 - -除非另有说明,这些指南中的路径和 shell 命令均相对 `inferencex-e2e/`。Python 项目清单、锁文件和 `.python-version` 位于该项目目录。仓库级规范和 GitHub 工作流仍位于仓库根目录。 - -## 任务路由 - -| 任务 | 首先打开 | 然后检查 | -| --- | --- | --- | -| 新增模型或 GPU 基准测试 | [配置参考](../configs/CONFIGS.md) | 最近的基准测试脚本、启动器、主 YAML、变更日志 | -| 修改已有配置 | [配置参考](../configs/CONFIGS.md) | 校验 Schema、生成器、运行时消费者 | -| 新增 Runner | [Runner 初始化](../utils/runner_setup/RUNNER_SETUP.md) | `configs/runners.yaml`、启动器 | -| 修改 srt-slurm 或 llm-d | [Recipe 参考](../benchmarks/multi_node/srt-slurm-recipes/RECIPES.md) | Recipe YAML、主配置、`srtctl` 映射、启动器 | -| 修改 MTP | [Draft model 精度](../../CONTRIBUTING.md#draft-model-precision) | MTP 同类实现、draft model、聊天模板路径 | -| 校验矩阵 | [CI 流程](ci-procedures_zh.md#本地矩阵生成) | 生成器 CLI 与 Pydantic 校验 | -| 派发或监控任务 | [CI 流程](ci-procedures_zh.md#手动端到端派发) | `e2e-tests.yml`、运行日志、产物 | -| 准备 PR 扫描 | [CI 流程](ci-procedures_zh.md#pr-主标签与修饰标签) | `run-sweep.yml`、标签、变更日志差异 | -| 复用绿色扫描 | [CI 流程](ci-procedures_zh.md#产物复用与-merge-with-reuse) | 复用门禁、源产物、合并工具 | -| 新增或调试评估 | [评估与 AgentX 流程](eval-agentx-procedures_zh.md#2-添加评分-eval) | `EVALS.md`、评估模板、分数校验器 | -| 运行 AgentX | [评估与 AgentX 流程](eval-agentx-procedures_zh.md#7-运行-agentx快速反馈与-canonical-证据) | Agentic 配置、Trace 来源、实时运行 Skill | -| 检查结果或入库 | [恢复与结果流程](recovery-results-procedures_zh.md#结果流水线先明确应当存在什么) | 产物 Schema、收集器、App 入库 Workflow | -| 恢复失败入库 | [恢复与结果流程](recovery-results-procedures_zh.md#失败摄取恢复) | 恢复工具、源 Run 产物、祖先关系规则 | -| 调试 Runner 或 Workspace | [恢复与结果流程](recovery-results-procedures_zh.md#amd-root-owned-工作区的预防与恢复) | 启动器清理、`.claude/commands/` 集群 playbook、集群日志 | - -## 任务与页面索引 - -| 页面 | 适用场景 | -| --- | --- | -| [`index.md`](index.md) / [`index_zh.md`](index_zh.md) | 本任务路由页及其中文对应页面 | -| [`architecture.md`](architecture.md) / [`architecture_zh.md`](architecture_zh.md) | 配置到结果的流程、所有权边界、产物与 InferenceX-app 交接 | -| [`ci-procedures.md`](ci-procedures.md) / [`ci-procedures_zh.md`](ci-procedures_zh.md) | 矩阵生成、校验、派发、PR 扫描、复用、暂存与产物下载 | -| [`eval-agentx-procedures.md`](eval-agentx-procedures.md) / [`eval-agentx-procedures_zh.md`](eval-agentx-procedures_zh.md) | Eval 与 AgentX 选择、执行、打分、证据与实时运行诊断 | -| [`agentx-standalone.md`](agentx-standalone.md) / [`agentx-standalone_zh.md`](agentx-standalone_zh.md) | 安装锁定版本的 AgentX 客户端,对已有服务回放轨迹,无需 CI 或 Slurm | -| [`results-and-ingestion.md`](results-and-ingestion.md) / [`results-and-ingestion_zh.md`](results-and-ingestion_zh.md) | 已发布结果查询、产物身份与 Schema、App 入库、去重与溯源 | -| [`recovery-results-procedures.md`](recovery-results-procedures.md) / [`recovery-results-procedures_zh.md`](recovery-results-procedures_zh.md) | 结果处理、入库验证与恢复、Runner 清理和故障分类 | -| [`testing.md`](testing.md) / [`testing_zh.md`](testing_zh.md) | 本地检查、冒烟运行、证据标准与评审门禁 | -| [`troubleshooting.md`](troubleshooting.md) / [`troubleshooting_zh.md`](troubleshooting_zh.md) | 故障层级诊断、已知案例、安全修复与停止条件 | -| [`PR_REVIEW_CHECKLIST.md`](PR_REVIEW_CHECKLIST.md) / [`PR_REVIEW_CHECKLIST_zh.md`](PR_REVIEW_CHECKLIST_zh.md) | CODEOWNER 审阅与精确签署要求 | - -## 权威参考 - -| 参考 | 负责内容 | -| --- | --- | -| [`AGENTS.md`](../../AGENTS.md) | 必读的低上下文 Agent 政策与基准测试约束 | -| [`CONTRIBUTING_zh.md`](../../CONTRIBUTING_zh.md) | PR 审阅、CODEOWNER 签署、扫描复用、合并与合并后职责 | -| [`.github/AGENT_OPERATIONS.md`](../../.github/AGENT_OPERATIONS.md) | 翻译术语、扫描标签、派发、Eval 选择、功耗、指标与产物 | -| [`configs/CONFIGS.md`](../configs/CONFIGS.md) | 主配置 Schema、搜索空间、Runner 与拓扑字段 | -| [`.github/workflows/README.md`](../../.github/workflows/README.md) | 生成器示例、Workflow 操作与复用政策 | -| [`infx/evals/EVALS.md`](../infx/evals/EVALS.md) | Eval 任务、执行、收集与校验契约 | -| [`benchmarks/multi_node/srt-slurm-recipes/RECIPES.md`](../benchmarks/multi_node/srt-slurm-recipes/RECIPES.md) | 分离式 Recipe 注册与主配置耦合 | -| [`utils/runner_setup/RUNNER_SETUP.md`](../utils/runner_setup/RUNNER_SETUP.md) | Runner 部署与初始化 | -| [`MODELS_zh.md`](MODELS_zh.md) | 支持的模型、硬件覆盖与命名 | -| [`klaud.md`](klaud.md) / [`klaud_zh.md`](klaud_zh.md) | Klaud Cold 候选选择、所有权、验证与恢复 | -| [`klaud-reporting.md`](klaud-reporting.md) / [`klaud-reporting_zh.md`](klaud-reporting_zh.md) | Klaud PR 正文、进度评论、数值对比与最终预检 | -| [`benchmarks/srt_agentic.sh`](../benchmarks/srt_agentic.sh) | 单节点与多节点 srt-slurm 配方共用的 AgentX Trace 回放客户端 | - -## 上下文规则 - -1. 只打开当前任务所需的聚焦页面与源文件片段。 -2. 如果过滤后的内容足以回答问题,不要加载大型 YAML、JSON、日志、生成矩阵或完整参考文件。 -3. 源代码、Workflow YAML、Schema、启动器与收集器优先于说明文档。 -4. 行为变化时,先更新最近的英文指南,再在同一变更中更新其 `_zh.md` 对应页面。 diff --git a/inferencex-e2e/docs/klaud-reporting.md b/inferencex-e2e/docs/klaud-reporting.md index 3f2c68dbc2..914fd10461 100644 --- a/inferencex-e2e/docs/klaud-reporting.md +++ b/inferencex-e2e/docs/klaud-reporting.md @@ -1,11 +1,5 @@ # Klaud Cold reports -
- -**English** | [中文](klaud-reporting_zh.md) - -
- [`infx/klaud/reporting.py`](../infx/klaud/reporting.py) owns the schemas, arithmetic and rendering. The agent supplies concise observations and verified evidence, not hand-calculated deltas. The PR body contains only the goal and baseline. Comments own attempts; the lifecycle receipt owns verified completion. Keep English visible and put Simplified Chinese in one collapsed `
中文` section. Numeric tables appear once; Chinese prose refers to those tables. Apply this layout to lifecycle comments too. No mentions, review requests, raw logs, private telemetry or limitations section. ## Commands diff --git a/inferencex-e2e/docs/klaud-reporting_zh.md b/inferencex-e2e/docs/klaud-reporting_zh.md deleted file mode 100644 index 5d36f16ad9..0000000000 --- a/inferencex-e2e/docs/klaud-reporting_zh.md +++ /dev/null @@ -1,119 +0,0 @@ -# Klaud Cold 报告 - -
- -[English](klaud-reporting.md) | **中文** - -
- -[`infx/klaud/reporting.py`](../infx/klaud/reporting.py) 统一管理数据结构、差值计算和渲染。agent 只提供简短观察和经过核实的证据,不手算差值。PR 正文仅包含目标和基线;评论记录尝试;生命周期完成记录证明收尾已验证。英文默认展开,简体中文放入一个默认折叠的 `
中文` 区块。数值表格只展示一次,中文引用共用表格;生命周期评论也使用这一布局。不提及用户、不请求审查、不发布原始日志或私有遥测,也不添加 limitations 章节。 - -## 命令 - -在工作流提供候选环境的 checkout 中运行: - -```bash -KLAUD=(uv run --no-project --exclude-newer PT12H --python 3.12 \ - --with 'pydantic>=2.10,<3' --with pyyaml python -m infx.klaud) - -# goal.json:{"en":"Update ENGINE image from `OLD` to `NEW`.","zh":"将 ENGINE 镜像从 `OLD` 更新为 `NEW`。"} -# 先通过公开 OpenAPI 确认模型显示名称。 -"${KLAUD[@]}" prepare-baseline --model 'DISPLAY MODEL NAME' \ - --goal-file "$KLAUD_EVIDENCE/goal.json" --output "$KLAUD_EVIDENCE/baseline.json" - -# 创建包含实际变更的草稿 PR 后,在 GPU 工作开始前将基线发布到正文。 -"${KLAUD[@]}" report --kind baseline --file "$KLAUD_EVIDENCE/baseline.json" - -# 数据结构只需读取一次;后续复用本地记录更新尝试状态。 -"${KLAUD[@]}" report-schema --kind attempt > "$KLAUD_EVIDENCE/attempt-schema.json" -"${KLAUD[@]}" report --kind attempt --file "$KLAUD_EVIDENCE/attempt.json" -``` - -`prepare-baseline` 核对规划阶段 `baseline-preflight.json` 中候选、基准 SHA、来源和模型的绑定,并复用其公开 benchmark 测试点清单;文件缺失或无效时停止。规划阶段使用候选日期、`exact=true` 查询公开 `benchmarks` 来构建该清单,不使用 calculator view;通过 `workflow-info` 核实产出运行 ID、head 和运行次数。每个产出配置族均从产出 head 的 Git 快照运行该产出修订版自身的生成器重新生成(本地克隆缺少该提交时从仓库获取),因此之后的配置格式变化不会破坏或改变对基线的解释;历史 `.github/configs` 路径和平铺 runner 标签格式同样适用。产出 head 均为本仓库的正式运行,因此执行的是已审阅的仓库历史代码,绝不是候选代码。这一步仍只在规划阶段不持有凭据的 `regenerate-producers` 步骤中运行,重新生成的数据行写入 `producers.json`;持有凭据的 `select` 只读取该文件。早于生成器 `--no-evals` 选项的产出无法重新生成,相应候选会被推迟。匹配要求旧镜像及完整公开工作负载、拓扑、并发身份一致;存在 recipe fingerprint 时也必须匹配。没有指纹的旧数据必须唯一匹配,且产出运行的 changelog 必须选择该配置族。不属于重建配置族的数据行会被忽略,即使其产出运行元数据不完整。匹配当前或历史测试点的数据行若来源缺失,或存在身份歧义、重复点,会阻止准备,不发布不完整基线。首次发布前,按[公开 API 路由](klaud_zh.md#公开-api-调查)补充已验证的历史评测和数据集来源。`BenchmarkRow` 本身不含数据集身份;AgentX 数据集无法核实时,差值仍为 N/A。绝不通过运行旧镜像补齐基线。 - -基线文件仅创建一次,重试不重新获取。PR 正文通过压缩的隐藏标记冻结完整类型化记录,并只渲染一次完整基线;冲突替换会被拒绝。旧 PR 使用的基线评论格式仍可供恢复流程读取。确需修正时,由维护者检查证据并明确记录更正,不能在修复期间静默改变基线。 - -冻结**原始所选公开基线中的每一个测试点**。helper 合并当前配置族与原始产出配置族,不按所选观测的 ISL/OSL 过滤公开数据。因此,即使当前配置族只剩 8k/1k,历史 1k/1k 测试点仍保留在清单中,且除非有已记录的退役覆盖它们,否则仍为必需。缺少已发布指标的点保留为 N/A,不从清单删除。不得将基线缩减为交集或正文预览中的行。保留每个测试点的 recipe、工作负载、拓扑、并发数和数据集身份;总数相同或其他位置的额外测试点不能替代缺失点。 - -只有规划阶段会记录退役,依据是候选基准提交中英文版 [`MODELS.md`](MODELS.md) 的声明。冻结测试点只有在以下条件全部满足时才会记为退役:该点为 fixed-seq-len,且当前配置族已不再生成与其冻结标签中单轮 ISL/OSL 相同的任何测试点;Scenarios 表中该 ISL/OSL 唯一的一行以 `Deprecated since YYYY-MM-DD ([#N](PR link))`(或其加粗的 `**Deprecated for all models** since` 形式)开头,链接本仓库的 PR,且日期晚于基线日期;该模型在 Model support matrix 中的行把此场景列为已弃用而非启用场景。表格或模型行重复、同一 ISL/OSL 出现第二行(无论空格写法如何),或表格中任一行的单元格数量不符时,均不会退役任何测试点。仅从当前配置族中消失、删除配置的提交或 perf-changelog 条目都不构成退役;只移除部分拓扑或并发的变更没有此类声明,覆盖检查仍会失败。每个 `retirements` 条目记录场景、日期、PR 链接、模型前缀、ISL/OSL 和退役测试点的比较键。没有退役的记录不写该字段,因此早于该字段的代码仍可读取。退役测试点在清单中保留已发布数值,PR 正文和最终报告会附上上述证据加以说明。agent 可以修改已发布的记录和 preflight,因此 `check-final`、`finish` 和中断恢复从不直接信任记录中的退役:它们以记录中的测试点清单和基线日期,对照候选基准提交(而非 PR head)上的配置族和 `MODELS.md` 重新执行上述规则,只有推导结果与记录完全一致时才会通过。选择阶段、`check-final`、`finish` 和中断恢复只豁免这些测试点。agent 不得添加、修改或删除退役记录。 - -创建草稿时,正文使用 ``。辅助程序只替换此占位符一次,写入冻结记录和渲染后的基线,并保留其他机器人在其外部添加的内容。发布基线不会创建评论;重试同一记录具有幂等性,后续尝试报告也不改写正文。较大的尝试报告先写入以内容哈希命名的不可变评论分段,再更新索引,避免中断时混用不同版本。 - -比较键通过 `reporting.point_key()` 从规范生成的配置点计算,仅排除镜像、配置点名称、生产指纹和排队元数据。工作负载、拓扑、并发数及其他设置都必须保留。planner 冻结基线时,如果某个已发布配置点在生产修订版下的比较键不在当前配置族中,则改用当前配置族中公开基准身份(模型、硬件、框架、精度、投机解码方式、工作负载、拓扑、并发数和镜像)相同的唯一配置点的比较键。因此,生产运行之后新增的路由标签或 recipe 路径不会把同一个配置点拆成两个。若当前配置族有两个匹配点,则视为身份不明确并延后该候选。没有当前匹配的配置点保留生产修订版的比较键,配置族缩小时覆盖检查仍会失败,除非已有记录的退役覆盖该点。`reporting.values()` 读取 collector/API 指标,将秒换算为毫秒。不能为使结果匹配而编造别名或比较键。AgentX 还须独立匹配数据集。基线缺失或为零、配置失败、数据集或统计口径不一致时记为 N/A。吞吐量差值为 `(new / old - 1) * 100`;评测分数使用 0–1,差值以百分点展示,并匹配 suite、metric、拓扑和样本量。 - -每次尝试记录所属 run ID、精确 head、运行次数、类型和编号、状态、以 en/zh 句子记录的变更/下一步、分别统计的 benchmark 与 eval 应有和通过数量,以及全部配置和评测结果。目标同样使用 en/zh 句子,明确引擎及精确的新旧镜像。可选 finding 字段保存诊断证据;finding 和覆盖计数均不渲染。保留失败、取消和请求错误。初始变更编号为 0,修复为 1–5。已确认的临时基础设施问题单独记为 infrastructure-retry,不消耗 recipe 修复次数;prompt 将其限制为每次尝试最多两次。不能因为吞吐量通过就把评测失败的 smoke 写成成功。 - -调度后立即发布每次尝试的记录,再等待运行。发生实质变化或等待满 30 分钟时,更新该 run/attempt 的同一条评论;完成的尝试保留为历史。较大的尝试记录拆成编号评论分段,不丢弃配置点,也不限制配置族大小。PR 正文包含完整基线及来源;评论仅记录尝试。记录以 parent/candidate/run/attempt 为幂等身份,只持久化类型化公开字段,不上传整个临时目录或执行记录。 - -使用紧凑元数据行、精确的 `8k/1k` 简写,并将共用配置放在表格上方。只有展示的工作负载、拓扑、统计口径一致且并发数唯一时,才仅用并发数标识行;否则保留可区分的完整标签。单元格显示新值和括号内的差值。评测样本量仅在新旧计数相同时显示 `N each`,否则分别列出新旧计数。失败、请求错误和无法比较的原因以简短备注保留。不添加 Result 列、Coverage/Finding 段落、图例、存储机制说明或重复状态总结;Next 仅写下一子目标。英文及全部结果表格保持展开,只折叠中文。 - -## 正文格式 - -```markdown -**Goal:** Update ENGINE image from `OLD_IMAGE` to `NEW_IMAGE`.\ -**Baseline:** DATE · `OLD_IMAGE`\ -8k/1k · TP8/EP1 · Mean latency · Sources: API links - -| Concurrency | Total tok/s/GPU ↑ | Output tok/s/GPU ↑ | TTFT ms ↓ | TPOT ms ↓ | -| ---: | ---: | ---: | ---: | ---: | -| C | value | value | value | value | - -| Eval | Score ↑ | Samples | -| --- | ---: | ---: | -| SUITE/METRIC · cN | SCORE% | N | - -
-中文 - -**目标:**将 ENGINE 镜像从 `OLD_IMAGE` 更新为 `NEW_IMAGE`。\ -**基线:**DATE · `OLD_IMAGE`\ -8k/1k · TP8/EP1 · 平均延迟 · 来源:API 链接;数值及异常说明见上表。 - -
-``` - -## 尝试评论格式 - -```markdown -**Repair N/5 · STATUS** · [Run ID / attempt N](RUN_URL) · UTC_TIMESTAMP\ -`IMAGE` · `HEAD` · 8k/1k · TP8/EP1 · Mean latency\ -**Change:** One sentence with relevant source links. - -| Concurrency | Output tok/s/GPU ↑ | TTFT ms ↓ | TPOT ms ↓ | -| ---: | ---: | ---: | ---: | -| C | 110 (+10%) | 180 (-10%) | 19 (-5%) | - -| Eval | Score ↑ | Samples | -| --- | ---: | ---: | -| SUITE/METRIC · cN | 97% (+0.50 pp) | 1,000 each | - -**Next:** Run the final full sweep. - -
-中文 - -**修复 N/5 · 状态** · [Run ID / attempt N](RUN_URL) · UTC_TIMESTAMP\ -`IMAGE` · `HEAD` · 8k/1k · TP8/EP1 · 平均延迟\ -**变更:**简短中文翻译;数值及异常说明见上表。\ -**下一步:**运行最终完整 sweep。 - -
-``` - -正常结束和中断恢复均由 `finish` 使用已验证产物和冻结基线生成最终报告,并在**标记就绪之前**发布。缺失的历史基线明确记为 N/A,不编造差值,也不另跑基线。成功 sweep 可以存在性能回归;就绪表示工作和验证结束,而非每项指标都提升。`finish` 返回 `validated` 后,Klaud 仅发布一次 `/use `,以便复用已完成的 sweep;其他结果不得发布 reuse 命令,也不得 stage 结果或合并 PR。 - -## 最终预检 - -添加 `full-sweep-fail-fast` 前,验证已推送精确 head 的完整矩阵: - -```bash -head_sha=$(git rev-parse HEAD) -uv run --no-project --exclude-newer PT12H --python 3.12 --with 'pydantic>=2.10,<3' --with pyyaml \ - python -m infx.matrix.plan --base-ref origin/main --head-ref "$head_sha" \ - --changelog-file perf-changelog.yaml > "$KLAUD_EVIDENCE/final-matrix.json" -"${KLAUD[@]}" check-final --matrix-file "$KLAUD_EVIDENCE/final-matrix.json" -``` - -验证器使用受信任 helper 代码,从精确 head 的 YAML 独立生成未过滤配置族。它按工作流的矩阵 schema 比较完整 recipe 设置,正确处理生成 fingerprint 后添加的默认字段;修改设置后复用原指纹仍会失败。覆盖等价的 scenario filter 可以通过;缺失或改变的配置点、默认评测不能通过。不会执行下载的 PR 代码。旧运行遇到生成器策略变化时需要检查,不能静默降低验证标准。 - -`check-final` 在调度前也会将**冻结基线中的每一个测试点**与规范最终配置族核对,仅豁免在候选基准提交上重新推导后完全一致的已记录退役测试点。`finish` 及中断恢复在验证完整产物覆盖后、标记就绪前执行相同检查。缺失基线、已记录的退役与重新推导结果不一致,或遗漏、改变任一未被退役记录覆盖的原始点时,即使较小的当前配置族 sweep 为绿色也无法通过。须报告受影响的点,并以 `outcome: failed` 调用 `finish`,清理自有运行、关闭 PR 并删除未移动的精确 head 分支;不得标记 ready 或 validated。`N/A` 仅表示差值无法核实,不能用于豁免缺失的新镜像结果。定向 smoke 仍可只运行子集。维护者明确接管时仍保留 PR 和分支。 diff --git a/inferencex-e2e/docs/klaud.md b/inferencex-e2e/docs/klaud.md index 7cb576e05b..699c8efcf7 100644 --- a/inferencex-e2e/docs/klaud.md +++ b/inferencex-e2e/docs/klaud.md @@ -1,11 +1,5 @@ # Klaud Cold auto-sweep -
- -**English** | [中文](klaud_zh.md) - -
- [`klaud-plan.yml`](../../.github/workflows/klaud-plan.yml) reconciles recorded interrupted sessions, prepares candidates with Python, uses a read-only Claude review to exclude overlapping PRs, then calls [`klaud-candidate.yml`](../../.github/workflows/klaud-candidate.yml). One autonomous Klaud Cold session owns each candidate’s edits, diagnosis and repairs. The `finish` command verifies validation or performs cleanup and posts its completion receipt; the read-only Stop hook and diagnostics verify that receipt against GitHub. Recovery uses the next existing autosweep, with no second agent or additional workflow. The PR review resolves overlaps, target clusters and public baseline model names for a bounded candidate batch. Candidate execution owns upstream image research. Models and turn limits are set in `klaud-plan.yml` and `klaud-candidate.yml`. The agent's display name is **Klaud Cold**; workflow filenames, CLI, artifacts, branches and runtime environment variables use `klaud` / `KLAUD`. Existing candidate branches with the previous spelling still block duplicate selection. Configure `DASH_API_KEY` before dispatching; workflows pass it to the existing `KLAUD_DASHBOARD_API_KEY` runtime variable. diff --git a/inferencex-e2e/docs/klaud_zh.md b/inferencex-e2e/docs/klaud_zh.md deleted file mode 100644 index 9a8b121cf7..0000000000 --- a/inferencex-e2e/docs/klaud_zh.md +++ /dev/null @@ -1,136 +0,0 @@ -# Klaud Cold 自动扫描 - -
- -[English](klaud.md) | **中文** - -
- -[`klaud-plan.yml`](../../.github/workflows/klaud-plan.yml) 先收尾有记录的中断会话,再用 Python 准备候选,经只读 Claude 检查排除重叠 PR 后调用 [`klaud-candidate.yml`](../../.github/workflows/klaud-candidate.yml)。每个候选仍由一个自主 Klaud Cold 会话负责修改、诊断和修复。`finish` 命令验证结果或执行清理,并发布完成记录;只读 Stop hook 和诊断步骤对照 GitHub 验证该记录。恢复工作放在下一次现有 autosweep 中,不增加第二个 agent 或工作流。 - -PR 检查为有界候选批次解析重复工作、目标集群及公开基线模型名。候选执行负责上游镜像调查。模型与轮数上限在 `klaud-plan.yml` 和 `klaud-candidate.yml` 中设置。Agent 的显示名称为 **Klaud Cold**;工作流文件名、CLI、产物、分支及运行时环境变量统一使用 `klaud` / `KLAUD`。旧拼写的候选分支仍会阻止重复选择。调度前须配置 `DASH_API_KEY`;工作流仍将其传给现有的 `KLAUD_DASHBOARD_API_KEY` 运行时变量。 - -## 候选选择 - -[`api.py`](../infx/klaud/api.py) 通过同一 HTTP 实现处理公开和私有读取。[统一 CLI](../infx/klaud/__main__.py) 为 `python -m infx.klaud`:`plan --directory DIR --review-batch-size N --cooldown-hours H` 准备候选和开放 PR;`select --max-candidates-per-run N --directory DIR` 校验 Claude 的结构化 `KLAUD_PR_REVIEW` 输出并应用工作流中的候选数量上限;`check-capacity --cluster ID` 在调度前重新检查容量。在 `plan` 前传入 `--root PATH`,可指定用于获取候选基准 SHA 的 checkout;不加载单独的 Klaud 策略配置文件。 - -- 规划阶段仅将 `/api/v1/latest-images` 用作已发布 benchmark 基线索引。候选配置族身份和当前镜像来自现有主配置。该数据源及 `/api/v1/framework-releases` 均不负责判断镜像是否最新或兼容;候选 agent 会独立检查官方上游源码、版本和可用镜像。 -- 私有读取仅使用 `/api/status/clusters`。要求响应新鲜且实际读取的字段有效、API 对集群判定为 `stale: false`、观测与接收时间戳有效且顺序正确、状态为 operational 或 degraded,并且至少有一个空闲节点。集群数据的过期阈值由 API 配置决定;Klaud 的 120 秒限制只用于响应获取/生成时间,不用于集群观测时间。排队任务、调度器预留和优先级覆盖不会改变低于 80% 的利用率规则。 -- 公开 API/CDN 负责 HTTP 缓存的新鲜度;Klaud 校验响应内容和本地获取时间。网络故障及 HTTP 408、429、5xx 响应会进行两次短暂且有界的重试;无效 JSON、schema 错误及其他语义错误立即失败。准备失败时,Actions 日志和摘要会报告具体错误码。 -- `plan` 使用现有矩阵生成器和 runner 元数据,从当前端到端项目目录的 `configs/*-master.yaml` 生成配置身份。按模型前缀、硬件、框架、精度、投机解码、分离部署、场景、ISL/OSL 和当前镜像与已发布基线求交集;比较镜像时将 registry 的 `/` 与 enroot 的 `#` 写法视为相同。已归档工作负载不会挤掉有效匹配。无法生成矩阵的配置族单独告警并排除。每个有效配置族选取最新匹配观测作为 benchmark 证据,再对不同配置族随机打乱一次。分支身份包含精确主配置文件/键及规范化当前镜像。现有配置族认领和开放 PR 仍用于去重;失败会话完成清理后删除分支,使配置族回到候选池。分页读取全部打开的 PR 及修改文件,包括草稿和重命名;失败或不完整的读取留给检查阶段处理。工作流每次最多向检查步骤发送 64 个候选。同一基准 SHA 的候选产物形成 24 小时软冷却:候选仍在池中,但排在近期未获得 agent 的候选之后。 -- Claude 根据 runner 和现有配置,对照私有 `capacity.json` 路由线索验证**全部实际目标集群**,检查与开放 PR 的语义重叠,并解析公开 API 基线查询所需的精确展示模型名。每个目标都必须符合条件;同类硬件的健康兄弟集群不能替代另一个集群。映射、重叠或容量无法证实时标记为 `uncertain`。重复或不确定的候选不占调度名额。结构化 schema 要求每个候选恰有一个决策,使后续符合条件的配置族能够补位容量变化、基线缺失或并发认领导致的空缺。Claude 检查开放 PR 的变更文件,再按需阅读正文和 diff。已有镜像更新、重叠修改或共享依赖会阻止候选,即使目标镜像 tag 不同;不同配置族仅模型或镜像相同不足以判为重复。结构化决策包含 `candidate-id`、`decision`、`family`、`baseline-model`、精确的 `telemetry-clusters`、`pull-requests` 和不含私有资格数据的简短 `reason`。上游源码、版本和镜像兼容性调查由候选 agent 负责。 -- `select` 仅接受通过校验且保留已提供配置族的 `proceed` 决策,刷新私有容量数据,要求检查结果中的每个目标仍符合条件,并在创建认领或启动 agent 前重建完整公开基线。基线不完整、有歧义或暂时不可用的候选记录在 `baseline-deferred-candidates` 中,后续已检查配置族可以补位。`select` 还会将冻结的基线点名单与当前规范配置族做最终覆盖检查。`MODELS.md` 中晚于基线日期、带日期的场景弃用声明所退役的冻结点,会作为退役记录写入基线并获得豁免(见[报告指南](klaud-reporting_zh.md))。如果配置族已不再生成其他冻结点(例如某个拓扑已被移除),则延后该候选,不创建认领、PR 或 agent 运行,并在 `baseline-mismatch-candidates` 中记录其 ID、原因 `baseline-point-mismatch` 和缺失点数量。随后按配置族去重,并按随机顺序应用总数量上限。`capacity-deferred-candidates` 记录最终容量检查未通过的候选。某个配置族被标记为重复或不确定时,即使另一条观测允许继续,也会排除整个配置族。检查不完整时延后本次选择,不将其报告为候选池已耗尽。检查 action 失败、输出格式错误、未知/重复 ID 或共享容量状态不可用会停止后续选择;重叠和基线检查绝不绕过。 - -两个 agent 都明确获得证据目录的访问权限。重叠检查 agent 使用 Read/Glob/Grep,并在每次 Bash 调用中只执行一个允许的只读 gh/git 命令;它在检查不受信任的 PR 内容时不使用 shell 包装、管道或不受限制的外部请求。两个 Klaud 工作流均不设置作业/步骤超时或 Bash 超时覆盖,使用 GitHub Actions 默认限制。预取也不设置整体截止时间。`selection.json` 记录容量与基线延后原因,作业摘要报告所选/延后数量。`review-diagnostics.json` 仅保留时长、轮数、费用等数值指标、按工具汇总的拒绝次数及固定的 Bash 分类(例如 shell 包装或文件过滤);不包含原始命令、路径、消息、结果或凭据。检查阶段诊断文件缺失不阻止选择收尾。检查步骤之外的基础设施故障或整个作业被取消仍可能导致无法完成。 - -私有容量门槛是 **节点利用率严格低于 80%**:`(summary.allocatedNodes + summary.mixedNodes) * 5 < summary.totalNodes * 4`,不做舍入。完全分配和部分使用的节点均计入已使用节点;恰好 80% 时不放行。不扣除预留节点。要求至少有一个空闲节点,避免整个集群不可用时仍以 0% 利用率通过检查。缺失、无效、不一致、过期或不可用的数据均拒绝。硬件匹配只用于初筛;检查阶段必须解析每个实际目标,选择阶段重新检查这些精确 ID。符合条件的作业可以先排队,由调度器等待完整物理节点需求能够满足后再启动。兼容性按实际读取的字段判断,不依赖 `schemaVersion`;新增字段或版本变化不会排除其他方面均有效的集群。 - -`klaud-plan` 产物仅显式包含 `candidates.json`、`open-prs.json`、`selection.json`、`review-diagnostics.json` 及每个所选候选的 `candidate.json` 和 `baseline-preflight.json`。本地 `capacity.json` 为检查阶段提供遥测 ID 和资格线索,**绝不上传**;任意临时文件也不会上传。每份交接文件包含已发布基线观测、已验证的 `baseline-model`、分支、基准 SHA、公开 benchmark 查询 URL 和通过校验的 `pr-review`,不包含私有节点计数或原始遥测。所选候选并行运行,各自获得独立 Klaud Cold 会话。一个候选失败不会取消其他候选。不再复制模型/runner 目录,也不保留 `recipes.py`;agent 使用现有 InferenceX 配置和工具理解实际 recipe 及上游镜像。 - -## Klaud Cold 负责执行 - -维护者可用 `klaud-handoff` 标签接管打开的候选 PR(首次使用前先创建仓库标签)。Klaud 在修改 PR/分支或取消运行前检查该标签;发现接管后保留 PR、分支、标签和运行中的作业,返回 `handoff`,Stop hook 同时释放监控责任。Klaud 不得自行添加或移除该标签。仍在活动的旧草稿继续占用候选,直到维护者恢复或恢复流程完成清理;已验证的历史完成记录会迁移到始终删除分支的策略。 - -除维护者明确接管外,会话结束时仅在最终验证成功后保留开放且 ready 的 PR。否则先报告失败或延后原因,取消所属未完成运行并确认所有作业结束,补全各次尝试评论中的结果,移除 sweep 标签、改回草稿、关闭 PR、删除未移动的精确 head 候选分支,并释放配置族认领。容量或就绪性阻塞、镜像不兼容、修复次数耗尽、原因不明及意外失败均采用同一清理方式,使配置族回到候选池;原因不明仍不得直接声称不兼容。不得关闭其他所有者的 PR,也不得删除已移动或已接管的分支。没有自己创建的 PR 时,仅报告停止原因,不创建占位 PR,也不删除无法验证归属的分支。 - -[报告指南](klaud-reporting_zh.md)统一定义正文、评论模板及类型化报告命令。正文仅包含目标和冻结的公开基线;尝试评论包含计数/状态/运行、紧凑元数据与 Change、benchmark/eval 表格,以及仅说明下一子目标的 Next。英文展开,简体中文折叠在 中文 区块,数值表格共用一次。单元格显示新值和差值,表头使用箭头,长度使用精确的 8k/1k 简写。不添加 Result 列、可见的 Coverage/Finding 段落、图例、存储说明或限制章节;失败及无法比较的原因保留为简短备注。目标/变更/下一步使用 en/zh 记录。 - -完成 checkout 和上下文准备后,candidate 工作流将控制权交给 Klaud Cold,并提供 `AGENT_PAT`、`ANTHROPIC_API_KEY` 和私有 API 只读密钥。Klaud Cold 将公开观测解析到一个活动主配置族,检查当前镜像和已有 PR,并在**编辑或创建分支/PR 之前**核实检查结果中的目标 ID 和实时容量。随后在使用 GPU 前认领分支,产生实际修改并创建草稿 PR。所有生成的 PR 标题必须以 `[Klaud Cold] ` 开头,后接英文 / 简体中文描述。不得在 GitHub 上 @提及用户/团队,也不得请求 review/re-review;这些操作由自动流程处理。它在认领分支前立即重新检查开放 PR,因为检查只是快照,不能锁住后来创建的人工 PR。有歧义、已退役或已经更新的候选直接停止,不运行扫描。提交、推送、调度、监控、诊断、修复及使用上述布局的 PR 正文/评论更新都由同一会话完成。 - -选择或修复镜像前,比较新旧镜像实际内置版本对应的 vLLM、SGLang、ATOM 或 TensorRT-LLM 源码标签/提交,以及关联的 serving 依赖。检查参数和配置解析器及执行路径,确认默认值或语义变化、改名/移除的选项和相关新增选项。仅看 release notes 不够;核实镜像与源码的对应关系,无法确认时如实说明,不能假定最新 `main` 就是镜像内容。将源码链接、相关变化和范围内的决策写入尝试评论。这不扩大允许修改的范围,也不允许运行时补丁。 - -定向尝试只测试更新后的镜像:从 `main` 调度 `e2e-tests.yml`,将 `inputs.ref` 设为实际测量 SHA,并使用 `generate-cli-command="test-config --config-files FILE --config-keys FAMILY --smoke"`。生成器将最低并发的吞吐量检查与规范并发上的代表性 eval 分开,不再把长评测降到吞吐量最低并发。这只能证明启动和兼容性,不能代表完整曲线。smoke 通过后,追加精确配置族的 changelog 条目,不使用场景、eval 选择或 append-only 修饰项。描述必须是最多 120 个字符的一句简洁英文,只写引擎版本变化,并仅在必要时附带一项关键兼容性调整。证据、结果、版本摘要、理由和限制写入尝试评论。保持 PR 为草稿并添加 `full-sweep-fail-fast`。最终 sweep 保留全部测试点和默认 eval。任何同仓库 PR 均可通过 sweep 标签授权草稿运行;fork PR 仍使用受信任调度路径。最终失败后,先移除 sweep 标签、保持草稿,再推送修复。补全尝试评论后调用 `finish`;它先验证全部必需结果,再将 PR 标记为 ready,触发自动审阅。标记为 ready 不会启动 sweep。确认结果为 `validated` 后,Klaud 仅发布一次 `/use `,保留已完成运行供合并时复用。不要求性能差值为正;回退应如实报告。Klaud 不自行 staging、请求 review 或合并。 - -在编辑或创建分支之前、每次定向调度之前,以及最终 sweep 的标签转换之前,使用 `check-capacity --cluster ID` 检查精确目标;通过重复 `--cluster` 指定每个可能的目标。退出状态 0 要求全部目标均通过新鲜度、可用性和低于 80% 利用率检查。如果该检查在定向调度、最终 sweep 转换或恢复调度之前失败,Klaud 会先在已有 PR 的评论中记录可公开的容量延后原因和当前尝试状态。随后取消并确认全部所属运行已经结束,再用终态或已取消行及确认后的状态更新尝试评论。最后移除所有 sweep 标签、将 PR 改回草稿、关闭 PR,并删除远程 Klaud 分支,使后续扫描可以重试该候选。如果尚无 PR,则在最终响应中记录延后结果,不创建占位 PR。调度后利用率上升不会导致健康运行被取消。Klaud 不会等待恢复或承诺自动继续。命令不打印容量详情。 - -Fail-fast 只会取消失败矩阵内排队或运行中的其他任务;其他矩阵仍可能继续运行。先诊断首个失败,并等待所有自有任务结束后再重试。被取消的测试点仍须取得成功结果;若基础设施故障导致整个 run 以 cancelled 结束,应在同一 head 上重跑整个 attempt。保留现有重试预算,不得将确定性的镜像失败归类为基础设施问题。只有在已记录基础设施例外、需要让健康任务在同矩阵其他任务失败后继续运行时,才使用 `full-sweep-enabled`;必须等自有任务结束后才能切换标签。已有的非 fail-fast 运行仍可用于验证。两种模式都要求唯一的 sweep 标签、精确 head 上成功的最终运行,以及全部基线测试点和默认 eval。 - -使用 `report` 分别记录初次尝试、修复 N/5、基础设施重试和最终完整 sweep。在等待前持久化所属 run/head/attempt。发生实质变化或等待满 30 分钟时更新同一条评论,完成的历史保留。渲染器统一处理匹配、单位、差值及大记录拆分。已确认的临时基础设施重试与 recipe 修复分开计算,每次尝试最多两次。`finish` 从已验证产物生成最终报告,发布后才标记就绪。缺失基线记为 N/A,回归如实报告,不设置拒绝阈值。 - -最终 sweep 无论测试点数量多少,都运行完整的所选配置族。单次 benchmark 运行可能长达三小时;Klaud Cold 在候选作业的总时限内监控其进展。Klaud 不再为单次 benchmark 运行设置额外超时。 - -工作流设置与其执行位置放在一起:[`klaud-plan.yml`](../../.github/workflows/klaud-plan.yml) 中的 `MAX_CANDIDATES_PER_RUN`、`REVIEW_BATCH_SIZE` 和 `CANDIDATE_COOLDOWN_HOURS` 分别控制并行调度、检查批次大小和软重复排序;[`klaud-candidate.yml`](../../.github/workflows/klaud-candidate.yml) 的 `MAX_REPAIRS` 将修复次数上限直接传入 agent 提示词。 - -Klaud Cold 最多运行 500 轮,使用 GitHub Actions 默认作业时限。诊断、修复选择和尝试评论仍由 agent 负责;`finish` 通过代码验证结果覆盖、子运行结束、最终报告和分支处理。作业时限、API 错误或 runner 被终止仍可能中断会话;下一次 autosweep 会在选择新候选前收尾有归属记录的会话。不增加自定义工作流超时。 - -Klaud Cold 调度 `e2e-tests.yml` 时显式设置布尔输入 `klaud-run: true`,并使用 `klaud-` 测试名称方便识别。手动和复用调用中的该输入均默认为 false,并传递至所有 benchmark/eval 模板。只有这个标志会为作业名称添加 `klaud | ` 前缀,供 InferenceX Dash 优先级调度器识别;普通测试名称不会改变优先级。配套调度器改动使 Klaud 始终排在普通人工任务之后,不受任务到达时间或 recipe 分数影响;Klaud 不获得等待时长加分或节点预留,skip-queue 请求也不生效。Klaud 使用剩余容量,不抢占已经运行的任务。显式管理员优先级覆盖保留原有优先顺序,Klaud 不得主动请求。启用 auto-sweep 前需部署配套 dashboard 调度器改动。 - -### 已发布基线与会话完成 - -基线来自 **`https://inferencex.semianalysis.com` 的公开 dashboard API**。规划阶段先解析 OpenAPI 展示模型名,并在启动 agent 前预检完整测试点清单。候选使用 `candidate.json` 中这一精确值,将 `candidate.source.date` 传给 `workflow-info` 和 `benchmarks`,设置 `date` 和 `exact=true`,不使用计算器 `view`。规划阶段将已验证的 benchmark 测试点清单写入 `baseline-preflight.json`,并绑定候选 ID、基准 SHA、来源观测和展示模型。候选解析精确的新旧镜像目标后,`prepare-baseline` 核对这些绑定并复用同一清单,不再重复读取 benchmark API;产物缺失或无效时候选停止。候选仍须补充公开 eval/数据集证据,并冻结、发布最终基线。核实旧镜像以及完整的模型、硬件、框架、精度、推测解码和工作负载身份,再逐点匹配拓扑、并发量及数据集。记录 API 查询、发布日期和每个测试点的来源 `run_url`/SHA,区分逻辑曲线快照与实际数据来源。按需读取已发布 eval,所有尝试共用这份固定基线。缺失或不可比较的数据填写 `N/A` 并说明原因。绝不调度或重跑旧镜像基线。 - -调度运行或创建草稿不代表任务完成。使用 `gh run watch --interval 60` 留在同一会话中等待,工具超时后继续等待,并检查作业级状态,因为 queued 工作流可能包含正在运行的作业。benchmark 矩阵失败后,eval 作业仍可能继续。定位首个服务端错误而非清理阶段症状;在原有范围、预算和容量规则内修复。工具调用被拒绝时改用允许的工具或命令,不得提前报告成功。先将所有尝试的最终结果写入 PR 尝试评论,再报告停止原因、修复次数、已确认的子运行结束状态和 PR URL。不得承诺稍后继续监控,也不得仅为结束会话而取消正常运行。 - -[Stop hook](https://code.claude.com/docs/en/hooks#stop) 通过 `check-stop` 检查 `$KLAUD_EVIDENCE/outcome.json`。结束前,将请求的 `CandidateOutcome` JSON 写入单独文件,运行 `uv run --no-project --exclude-newer PT12H --python 3.12 --with "pydantic>=2.10,<3" --with pyyaml python -m infx.klaud finish --outcome-file "$KLAUD_EVIDENCE/requested-outcome.json"`,然后仅调用一次 `StructuredOutput`,传入已验证的 `outcome.json` 对象,不附加说明文字,也不将其编码为字符串。诊断优先使用该验证文件;仅在文件不可用或无效时,才回退到 action 的重复结构化输出。命令从父运行原始创建时间起发现所有自有定向和最终运行,包括旧 head、已关闭或移除标签的 PR。先发布失败或延后报告,再取消运行;全部结束后才移除 sweep 标签、退回草稿、关闭 PR,并为所有失败结果删除未移动的精确 head 分支。完成记录包含实际运行 ID 和清理状态。取消或 PR 状态转换事件的作业仍在进行时,等待后重试 `finish`。维护者接管优先于清理;不覆盖其他所有者、fork、已移动的 head、已合并 PR 或不明确的状态。没有所属 PR 时不删除无法验证归属的分支。hook 仅做验证,不修改状态,也不能突破 Claude 内置的停止循环上限。 - -每次 agent 步骤结束后,无论 action 结果如何,`recover-current` 都执行一次受信任的非阻塞收尾。没有 PR/run 的会话会立即释放;健康子运行保留给后续恢复;已结束工作则完成清理或验证。随后诊断优先使用经 GitHub 验证的生命周期记录。固定错误码区分会话状态不可用、记录无效、结构化输出无效和生命周期验证失败。无法验证时,先上传脱敏产物,再让候选作业失败。基线阶段的失败结果必须附带固定 `reason-code`,标明首个经核实的阻碍:预检绑定、来源溯源、测试点身份、eval 证据、公开 API 或其他。经验证的完成记录、脱敏候选产物、作业摘要和 PR 完成评论保留该代码;没有代码的历史记录仍可读取。仅记录固定结果类别、数字 ID/指标及 head/attempt,不包含原始执行消息、命令、凭据或私有响应。 - -`run-sweep.yml` 上传包含完整矩阵、精确 head 和 run ID/attempt 的 `klaud-sweep-manifest`。`check-final` 与最终验证均使用受信任代码,从精确 head 的 YAML 独立生成未过滤配置族。覆盖等价的 scenario filter 可以通过,缺失或改变的配置点与默认 eval 不能通过。验证器选择当前 attempt 的 manifest,以及同一 run/head 下每个名称最新的产物。仅当对应配置生产作业没有重跑时,才保留之前的 aggregate;全部覆盖及原始结果/汇总一致性仍须通过。不同 archive 不叠加解压。缺失、过期产物及生成器策略变化需要检查;无 manifest 的旧运行不能自动认证。 - -### 中断恢复 - -选择步骤先原子创建每个配置族的 `klaud/claim-*` ref,保存经验证的归属,同时上传兼容旧流程的 `klaud-ownership`。ref 覆盖上传产物前的中断,并阻止同配置族其他 release 重复启动。恢复先验证完整清单,仅处理受信任 main 的已结束父运行,使用每会话 `klaud/recovery-*` 租约。旧租约所属工作流结束后,才通过非强制 fast-forward 的比较交换接管;没有全局工作流锁。健康子运行继续执行,下一轮再检查,不阻塞新候选选择。未解决配置族继续排除,其余配置族可以推进。全局归属或清单无效时仍停止调度。 - -恢复会先发布并认证成功的完整最终结果,再标记就绪。已结束但无法认证的结果以需检查的终态关闭并删除未移动的精确 head 分支,不能据此推断镜像不兼容。中断清理从绑定 head 的记录继续,不把未知修复次数改为零;不修改已移动 head、已合并、已接管或其他所有者的工作。恢复还会根据已验证的历史完成记录,删除过去保留的精确 head 分支。取消后未结束的子作业留到后续检查,恢复不阻塞等待。仅退休全部已解决的归属产物,公开报告保留。正常收尾或独占恢复释放配置族认领。恢复不会启动另一 agent、创建 PR 或调度替代 sweep。 - -## 公开 API 调查 - -从当前 [API 参考文档](https://inferencex.semianalysis.com/api) 和 [OpenAPI 文档](https://inferencex.semianalysis.com/api/openapi.json) 获取参数、响应结构和限制。planner 只用 `latest-images` 定位已发布 benchmark 基线;Klaud Cold 根据候选情况选择额外读取,并独立检查上游源码与镜像。API schema 和模型/runner 清单仍以各自的现有来源为准。 - -下表所有路径均相对于 `/api/v1/`: - -| 调查内容 | 可用读取接口 | -| --- | --- | -| 已发布覆盖范围与 recipe 溯源 | `availability` 提供实际场景和日期;`workflow-info` 提供运行尝试次数、SHA、变更日志中的配置键及各次运行覆盖范围;`submissions` 按日期汇总拓扑和测试点数量。 | -| 镜像与性能历史 | `benchmarks` 和 `benchmarks/history` 提供原始指标、镜像、拓扑、recipe fingerprint 和产出运行 URL。省略 calculator 视图以保留全部可用指标。 | -| 同组测试点 | `benchmark-siblings` 提供相关测试点及其并发/拓扑、来源 GitHub 运行和数据集 slug。比较前仍需筛选目标工作负载和拓扑。 | -| 已发布失败与质量信息 | `evaluations` 提供任务分数和运行来源;`reliability` 提供硬件/日期维度的成功计数,不能归因到具体镜像。 | -| 运行时诊断 | `log-availability` 检查日志是否保留;`server-log-files` 列出文件名;`server-log-search` 搜索全部保留文件并返回数量受限的片段;`server-log` 分块读取指定文件。通过 `nextOffset` 继续读取,并检查搜索结果是否被截断。 | -| AgentX 缓存、延迟与工作负载诊断 | `trace-availability`、`agentic-aggregates`、`derived-agentic-metrics`、`trace-histograms`、`trace-server-metrics` 和 `request-timeline` 提供已保留的 trace、百分位、token 样本、缓存/队列/吞吐量时间序列,以及请求阶段和取消信息。先读汇总,仅在需要时获取详细 trace。 | -| AgentX 数据集背景 | `datasets`、`datasets/{slug}`、`datasets/{slug}/conversations` 和 `datasets/{slug}/conversations/{convId}` 提供数据集元信息、分布与会话结构。使用该次运行的数据集 slug,不预设数据集。 | -| 通信背景 | `collectivex/latest`、`collectivex/runs` 和 `collectivex/runs/{runId}` 提供带版本的通信测量,可用于相关的多节点故障调查。必须明确指定受支持版本;接口可能返回已存储的回退数据。 | - -解读响应时应注意以下实现细节: - -- `latest-images` 和 `availability` 返回原始模型键;benchmark 查询要求使用当前 OpenAPI 枚举中的展示名称。核对返回的模型及完整候选身份。`latest-images` 仅用作 benchmark 基线观测,不能代替当前仓库配置族、当前版本或兼容替换镜像清单;Klaud 会独立检查上游源码和镜像。 -- 向 `workflow-info` 传入观测日期:虽然参考文档说省略日期会查询全部日期,当前查询实现会将该参数转换为 SQL 日期。变更日志中的配置键和运行覆盖范围可以缩小查找范围,但不能证明配置族唯一。 -- 对于 append-only 运行,`exactRun=true` 可能包含同一镜像的前序运行链。保留各测试点产出运行的 `run_url`,并与逻辑 `curve_*` 快照元数据区分。benchmark 行的 `workflow_run_id` 是数据库 ID;`runId` 参数和 `workflow-info` 中的运行标识是 GitHub ID。诊断接口要求传入数据库基准测试结果的正整数 `id`。 -- `submissions` 按配置/日期聚合测试点,未排序便选取一个非 null 镜像,因此不能用于确定精确镜像基线。公开缓存和数据导入可能滞后于新运行。诊断数据缺失表示证据不可用,不代表数值为零或测试通过。 -- 原始 benchmark 时间指标使用秒;请求时间线使用纳秒偏移,延迟字段名称明确标注毫秒。服务器时间序列偏移使用秒。物理芯片数与逻辑 TP 独立;只有分离式部署才应将 prefill/decode 芯片数相加。 - -应用还有一些有用的**未发布 UI 读取接口**:`/api/unofficial-run` 将尚未导入的运行产物归一化,`/api/gpu-metrics` 读取 GPU 指标产物,`/api/v1/eval-samples` 和 `/api/v1/eval-samples-live` 可下钻失败样本,`/api/v1/trace-server-metric-source` 获取所选 worker/来源的时间序列。按需使用前先检查当前 handler;这些契约由页面内部使用。非官方 benchmark 行使用合成的 `id: 0`,不能用于查询已存储的诊断数据。新旧镜像比较的证据仍须对应原始运行产物。 - -`tco-feed` 提供经过插值的图表/TCO 背景,不用于精确 recipe 比较。`overview`、`request-chart-data` 和 `resident-sequence-lengths` 是 UI 投影,没有此处候选选择所需的额外数据。反馈与管理路由不参与候选调查。 - -## 修改范围与 PR 策略 - -权威[候选指令](../../.github/klaud-candidate-prompt.md)仅允许修改所选 master 镜像,以及其已引用且未共享的单节点 recipe 或 srt-slurm YAML 中有源码依据的兼容性参数/环境变量。模型、精度、拓扑、推测解码、工作负载/数据集、时长、资源、全部配置点和 eval 保持不变。`model.container` 和 `identity.container.image` 必须一致。Klaud 不进行广泛调优,也不修改共享脚本、launcher、库或工作流。运行时引擎/serving 技术栈补丁必须为零,包括选定路径已有的补丁:禁止改写源码、容器、site-packages,禁止 overlay、monkey patch 或重建/fork 的 wheel。选择可原样运行的镜像,否则报告不兼容。 - -smoke benchmark 和代表性 eval 都通过后,在 changelog 物理末尾追加条目并保留历史字节,推送精确 head,生成/检查完整矩阵并重新检查容量。保持草稿,只添加 `full-sweep-fail-fast`。最终失败后,先移除 sweep 标签并保持草稿,再修复。仅 `finish` 在结果验证和最终报告发布后标记就绪;就绪触发审查,不启动新 sweep。随后 Klaud 用 `/use` 记录已验证的最终运行;审查、staging 和合并仍由维护者决定。 - -## 工作流操作与凭据 - -入口工作流每六小时运行一次(`0 */6 * * *`,UTC),并支持手动触发(`workflow_dispatch`)。每次调用最多选择五个候选并行运行。条件 `github.ref == 'refs/heads/main' && github.run_attempt == 1` 会跳过功能分支、tag 和重新运行。candidate 作业也跳过重跑;应重新调度 autosweep,先执行恢复。只有 candidate 暴露 `workflow_call`。两个 Klaud 工作流均不设置并发组:新调用可以与已有调用重叠,且不会取消已有运行。五个候选的上限按每次调用计算,因此多轮重叠时,活跃候选总数可以超过五个。开放 PR 检查和 agent 对精确分支的原子认领仍用于防止重复工作;审查只是快照,agent 必须在认领前再次检查。恢复先于选择执行,但不阻塞等待活动子运行。配置族认领和每会话恢复租约保护重叠调用,未解决配置族仍被排除。 - -恢复和最终选择步骤使用 `AGENT_PAT` 执行已确认归属的清理及配置族认领;只读重叠检查 agent 不获得该凭据。在审查与选择之间,`regenerate-producers` 步骤在不含任何凭据的环境中运行基线产出修订版自身的生成器,并将数据行写入 `producers.json`;选择步骤只读取该文件,不运行其他修订版的代码。planner 的 Python 准备和最终容量检查步骤使用 dashboard key;准备步骤还使用只读工作流 token。限轮数的 Claude PR 检查使用 `ANTHROPIC_API_KEY` 和具有 `pull-requests: read` 权限的只读工作流 token。它接收私有资格线索,但不接收 `AGENT_PAT` 或 dashboard key,也不执行 GitHub 写操作。candidate 获得用于分支/PR 写入及 e2e 调度/取消的 `AGENT_PAT`、用于 Klaud Cold 的 `ANTHROPIC_API_KEY`,以及覆盖 clusters 的限期 `status:read` `DASH_API_KEY`。Klaud Cold 不得发布凭据或私有 API 响应。共享 HTTP 读取器固定来源,同时限制压缩和解码后的 GET 响应大小,支持明确的 gzip/identity JSON 响应,并拒绝重定向或不支持的编码。非有限 JSON 数值(包括 `1e400` 这样的指数溢出)会在校验或哈希计算前被拒绝。不需要部署额外服务、数据库或新增 environment 配置。 - -重叠检查在独立的 `review` 作业中运行,与持有凭据的 `recover` 和 `select` 作业分离。它可用的 gh/git 命令仅限 `gh pr list/view/diff`、`gh api --method GET`、`git status` 和 `git ls-tree`;`git show`、`git diff` 和 `git log` 可通过 `--output` 写入任意文件,因此不在允许列表中。`select` 作业重新 checkout 恢复阶段的提交,只读取数据:planner 生成的 `candidates.json` 和 `open-prs.json`(在 agent 启动前作为短期 `klaud-review-input` 产物上传)、检查的结构化输出与结果状态,以及执行日志最终结果的脱敏子集。检查 agent 在其工作区、runner 临时目录或工具缓存中写入的任何内容都不会进入持有 `AGENT_PAT` 的步骤。 - -所有外部 action 均在工作流 YAML 中固定完整提交 SHA。内部调用使用 `./.github/workflows/klaud-candidate.yml` 解析调用者的精确提交,并显式传递三个必需 secret。 - - -## 本地验证 - -```bash -uv run --no-project --exclude-newer PT12H --python 3.12 --with "pydantic>=2.10,<3" python -m infx.klaud --help -``` - -CLI 和工作流检查不能证明 GPU 实际可运行。Klaud Cold 使用现有 InferenceX 校验和 e2e 工作流验证候选修改。本地验证不调用真实模型、不调度 benchmark、不创建 PR、不部署。 - -严格 zizmor 扫描没有未忽略的发现。使用 `--no-ignores` 检查时,会报告允许多轮重叠的并发例外,以及五项现有仓库 secret environment 提示。`actionlint` 1.7.12 尚不识别 runner 的 `$/` 同仓库工作流调用语法,因此会报告该现有调用,但 GitHub Actions 可以接受它。 - -### 结果文件命名与最终 sweep 调度 - -定向和最终工作流使用同一个有长度上限的结果文件前缀。长前缀对完整身份(包括完整 recipe fingerprint)做哈希,JSON 中保留原始 fingerprint。对不含文件命名辅助程序的旧提交运行基准测试时,工作流会回退为对完整身份做哈希。SRT 测试点文件保留数字并发/GPU 后缀,只压缩过长的配置名;长度预算包含 `power_validation_`、`.json` 和原子写入的 `.tmp` 后缀。较短的测试点文件名保持不变。 - -最终 sweep 的每个 benchmark/eval 调用(包括 canary)都会为同仓库、由 `Klaud-Cold` 创建且分支为 `klaud/auto-*` 或旧拼写的 PR 传递后台优先级标志。人工 PR 不会因标题或标签而获得 Klaud 优先级;最终运行与定向运行使用相同的 `klaud |` 调度器标志。 diff --git a/inferencex-e2e/docs/recovery-results-procedures.md b/inferencex-e2e/docs/recovery-results-procedures.md index db677230d2..6fd03f0885 100644 --- a/inferencex-e2e/docs/recovery-results-procedures.md +++ b/inferencex-e2e/docs/recovery-results-procedures.md @@ -1,11 +1,5 @@ # Results, Ingest, and Recovery Procedures -
- -**English** | [中文](recovery-results-procedures_zh.md) - -
- Use this page after a throughput or eval job starts producing output, or when a sweep, runner, cluster, handoff, or database ingest fails. It separates evidence collection from repair so an infrastructure problem is not mistaken for a benchmark regression and an ingest problem does not trigger another expensive GPU sweep. ## Safety gates diff --git a/inferencex-e2e/docs/recovery-results-procedures_zh.md b/inferencex-e2e/docs/recovery-results-procedures_zh.md deleted file mode 100644 index 9021d2f427..0000000000 --- a/inferencex-e2e/docs/recovery-results-procedures_zh.md +++ /dev/null @@ -1,361 +0,0 @@ -# 结果、摄取与恢复流程 - -
- -[English](recovery-results-procedures.md) | **中文** - -
- -当吞吐量或评测任务开始产出结果,或 sweep、runner、集群、交接或数据库摄取失败时,请使用本页。本页将证据收集与修复分开,避免把基础设施问题误判为基准性能回归,也避免因摄取问题重新触发昂贵的 GPU sweep。 - -## 安全关卡 - -1. **在做任何更改前,先确定准确的 run、attempt、job、event、branch、head SHA 和 runner。** dispatch 任务绿色(`merge-ingest.yml` 中的 `ingest`,或旧版 `run-sweep.yml` push run 中的 `trigger-ingest`)并不能证明有效基准结果行已经进入数据库。 -2. **先检查,后变更。** 读取 GitHub 日志、`sinfo`、`squeue`、sysctl、文件所有者和制品是安全的。删除共享文件、更改 sysctl、drain 节点、重启服务或修改集群状态,都需要运维者明确批准。 -3. **绝不要仅为修复正式摄取而重跑失败的 push-to-`main` 目标。** 应使用经过验证的制品复用恢复路径;它既能避免 GPU 工作,也能保留源 run 的来源信息。 -4. **只重跑已经确诊的偶发故障。** 重试不会修复错误的镜像、recipe、模型、launcher、配置、缺失或过期的制品,也不会修复执行语义变化。 -5. **把 `source-run-id` 和 `merge-run-id` 当作一对。** source run 拥有基准/评测制品,merge run 拥有发布/changelog 元数据。在信任摄取前,必须在下游日志中核对两者。 -6. **不要仅按时间新旧选择 InferenceX-app 摄取 run。** 过时或伪造的摄取可能比恢复摄取更新。 -7. **清理前保留证据。** 记录 run/job URL、run attempt、runner 名称、source/merge ID、制品名称与数量、首个因果错误,以及所有节点或 Slurm job ID。 - -来源:[sweep 调试安全规则](../../.agents/skills/debug-runs/SKILL.md#L78-L152)、[失败摄取安全规则](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.claude/commands/recover-failed-ingest.md#L22-L54)。 - -## 结果流水线:先明确应当存在什么 - -### 吞吐量结果 - -可复用基准工作流在启动 GPU 任务前准备 Python 3.12,并通过 -`INFERENCEX_RESULTS_PYTHON` 导出其绝对路径。固定序列结果处理和 AgentX 功耗处理 -(包括 H200 DCGM 路径)都会校验并使用该解释器。该设置缺失或为空时,处理失败; -AgentX launcher 仍会先保留已有的审计和服务端产物,再返回失败状态。 - -对于普通单节点吞吐量任务: - -1. launcher 必须在工作区留下 `${RESULT_FILENAME}.json`。工作流会短暂等待;如果该文件一直没有出现,任务失败。 -2. `infx/results/fixed_sequence.py` 读取原始 JSON 以及拓扑/运行时环境变量,规范化元数据和每 GPU 吞吐量,把毫秒字段转换成秒,推导 interactivity,并写出 `agg_${RESULT_FILENAME}.json`。 -3. 任务将聚合结果上传为制品 `bmk_${RESULT_FILENAME}`。 -4. `collect-results.yml` 下载 `bmk_*`,运行 `python3 -m infx.results.collect_results results/ bmk`,再上传 `results_bmk`;其负载为 `agg_bmk.json`。 - -对于多节点吞吐量,每个 `${RESULT_FILENAME}_*.json` 都会单独处理。工作流从各文件名推导 GPU 总数、prefill GPU 数和 decode GPU 数,并调用: - -```bash -RESULT_FILENAME=${result_file%.json} \ -IS_MULTINODE=true \ -PREFILL_GPUS="$prefill_gpus" \ -DECODE_GPUS="$decode_gpus" \ -"$INFERENCEX_RESULTS_PYTHON" -m infx.results.fixed_sequence -``` - -上传的 `bmk_${RESULT_FILENAME}` 制品包含 `agg_${RESULT_FILENAME}_*.json`。缺少源文件属于基准/launcher 故障;缺少 `agg_` 文件属于结果处理故障;缺少 `results_bmk` 属于收集故障。不要把这些问题归类为数据库故障。 - -来源:[单节点处理/上传](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/benchmark-tmpl.yml#L289-L323)、[多节点处理/上传](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/benchmark-multinode-tmpl.yml#L345-L387)、[`infx.results.fixed_sequence` 契约](../infx/results/fixed_sequence.py)、[吞吐量收集器](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/collect-results.yml#L25-L38)。 - -### 评测结果 - -评测任务上传以 `eval_${EXP_NAME}_${RESULT_FILENAME}` 命名的逐配置制品。制品包含评估命令按 [`infx/bench/eval/stage.py`](../infx/bench/eval/stage.py) 中的允许列表为该评测器暂存的文件,即 `meta_env.json`、`results*.json`、`sample*.jsonl`,以及厂商评估的原生报告(`*_report.json`)、详细结果(`*_results.jsonl`)和归档(`*_artifacts.tar.gz`)。工作流的以下行为都是有意设计的: - -- eval-only 任务没有任何评测文件时会报错; -- 评测文件在 `always()` 条件下上传,以保留失败任务的部分证据; -- `infx/evals/validate_scores.py` 在上传后验证 eval-only 分数覆盖范围; -- `collect-evals.yml` 下载 `eval_*`,运行 `python -m infx.results.collect_eval_results`,打印摘要,并上传 `eval_results_all/agg_eval_all.json`。 - -应用既能摄取聚合行,也能摄取逐配置评测目录。两种输入最终落到相同的自然键,而 sample 文件把详细数据附加到已经解析的评测行。因此,仅有聚合文件只能证明完成了收集,不能证明 sample 完整;当逐 sample 输出很重要时,必须核对逐配置制品。 - -来源:[单节点评测上传/验证](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/benchmark-tmpl.yml#L362-L385)、[多节点评测上传/验证](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/benchmark-multinode-tmpl.yml#L416-L434)、[评测收集器](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/collect-evals.yml#L24-L46)、[应用侧评测制品处理](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/ingest-ci-run.ts#L738-L792)。 - -### 在不改变 run 的情况下检查结果制品 - -```bash -RUN_ID= - -# Run identity and jobs -gh run view "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --json event,headBranch,headSha,status,conclusion,attempt,jobs - -# Exact unexpired artifact inventory -gh api "repos/SemiAnalysisAI/InferenceX/actions/runs/$RUN_ID/artifacts?per_page=100" \ - --paginate --jq '.artifacts[] | select(.expired == false) | [.name,.created_at,.size_in_bytes] | @tsv' - -# Download only the two collection products when they exist -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --name results_bmk --dir /tmp/infx-results-$RUN_ID -gh run download "$RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --name eval_results_all --dir /tmp/infx-evals-$RUN_ID - -jq 'length' /tmp/infx-results-$RUN_ID/agg_bmk.json -jq 'length' /tmp/infx-evals-$RUN_ID/agg_eval_all.json -``` - -**关卡:** 零行、缺失聚合制品或源制品已过期,都要求先完成故障分类再重试。制品存在并不能证明其中有有效行:当两个请求计数字段都存在且 `num_requests_successful == 0` 时,应用会有意跳过该基准结果行。 - -来源:[失败结果行关卡](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/etl/benchmark-mapper.ts#L203-L216)、[恢复流程使用的制品清单检查](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.claude/commands/recover-failed-ingest.md#L149-L174)。 - -## InferenceX-app 交接与摄取验证 - -push 到 `main` 时,[`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) 的 `ingest` 任务只会在验证已合并 PR 的复用授权和 source run,并上传合并时的 `changelog-metadata` 之后才 dispatch。changelog 增量包含 agentic 条目时,会以相同 ID 加上 `database-target: production` dispatch `ingest-agentic-results`;否则负载为: - -```json -{ - "event_type": "ingest-results", - "client_payload": { - "source-run-id": "", - "merge-run-id": "" - } -} -``` - -`source-run-id` 始终指向经过验证并被复用的 PR sweep,`merge-run-id` 指向 `main` 上新的 Merge Ingest run(恢复时即恢复 PR 合并产生的 run)。由于 `main` 从不运行 sweep,正式摄取不再让两个 ID 指向同一个 run。InferenceX-app 会从 source run 中为每个准确制品名称选择最新、未过期的上传,并用 merge run 的 `changelog-metadata` 替换 source 的 changelog 元数据。如果 source 没有未过期制品,或 merge run 没有 changelog 制品,准备步骤会失败。 - -之后,应用工作流依次运行:制品准备、迁移、数据库摄取、run overrides、数据库验证、缓存失效和 unmapped entity 检查。数据库写入具有幂等性(`ON CONFLICT DO UPDATE` 或 `DO NOTHING`),因此指向正确目标的摄取在部分失败后可以安全恢复。 - -来源:[当前 dispatch](../../.github/workflows/merge-ingest.yml)、[历史 `run-sweep.yml` dispatch 负载与关卡](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.github/workflows/run-sweep.yml#L978-L1021)(`merge-ingest.yml` 启用前)、[制品选择](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/lib/ci-artifact-preparation.ts#L10-L48)、[应用摄取阶段](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/.github/workflows/ingest-results.yml#L50-L124)、[幂等性设计理由](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/docs/data-pipeline.md#L26-L34)。 - -### 验证准确的下游摄取 - -```bash -gh run list --repo SemiAnalysisAI/InferenceX-app \ - --workflow "Ingest Benchmark Results" \ - --event repository_dispatch --limit 10 \ - --json databaseId,status,conclusion,createdAt - -INGEST_RUN_ID= -SOURCE_RUN_ID= -MERGE_RUN_ID= - -gh run view "$INGEST_RUN_ID" --repo SemiAnalysisAI/InferenceX-app --log \ - | grep -m1 "Source run: $SOURCE_RUN_ID" -gh run view "$INGEST_RUN_ID" --repo SemiAnalysisAI/InferenceX-app --log \ - | grep -m1 "Merge run: $MERGE_RUN_ID" - -gh run watch "$INGEST_RUN_ID" \ - --repo SemiAnalysisAI/InferenceX-app --exit-status -``` - -不能只要求结论为绿色;还要满足以下全部条件: - -- 两条日志匹配都指向预期的 source/merge run 及其 attempt; -- 制品准备报告了预期的制品名称和数量; -- 复用摄取明确说明 changelog 元数据来自 merge run; -- 数据库摄取报告合理的 benchmark/eval/changelog 数量,并解释所有跳过的行; -- run overrides 和数据库验证成功; -- 已尝试缓存失效; -- 没有 unmapped model、hardware 或 precision,或这些项已经明确完成分类处理。 - -准备脚本输出的 `Source run:` 和 `Merge run:` 是权威匹配行。复用摄取的 source run 已经完成,所以不会等待五分钟。 - -来源:[权威准备日志](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/prepare-ci-artifacts.ts#L99-L152)、[正式验证顺序](../../.claude/commands/recover-failed-ingest.md#8-merge-and-verify-official-ingest)([历史快照](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.claude/commands/recover-failed-ingest.md#L391-L429),`merge-ingest.yml` 启用前)。 - -## 失败摄取恢复 - -首先把事件分成两种情况。 - -### 情况 A:正确的应用摄取已存在,但中途失败 - -如果其准备日志匹配预期的 source/merge 对,且制品仍未过期,那么重跑该 **InferenceX-app 摄取 run** 在数据层面是安全的,因为 ETL 具有幂等性: - -```bash -gh run rerun "$INGEST_RUN_ID" \ - --repo SemiAnalysisAI/InferenceX-app --failed -``` - -如果 GitHub 拒绝只重跑失败任务,完整重跑同一个应用 run 在数据层面仍然是幂等的: - -```bash -gh run rerun "$INGEST_RUN_ID" \ - --repo SemiAnalysisAI/InferenceX-app -``` - -当准备日志显示 ID 错误、制品已过期/缺失、changelog 元数据缺失,或候选 source SHA 之后执行语义发生变化时,**不要重跑**。重试只会忠实重复错误操作。 - -### 情况 B:正式摄取缺失、被跳过、无有效数据或指向错误 source - -使用仓库的恢复 PR 流程。不要重跑失败目标,不要新增一次性工作流,也不要手工把行复制进数据库。 - -#### 1. 检查并证明目标 - -在干净的 InferenceX checkout 中运行,并确保 `gh`、`git`、`jq` 已认证且 Python 依赖可用: - -```bash -python3 -m infx.workflows.recover_failed_ingest inspect-target \ - "$FAILED_RUN_OR_JOB_URL" \ - --output /tmp/infx-recovery-target.json - -TARGET_RUN_ID=$(jq -r .run_id /tmp/infx-recovery-target.json) -TARGET_JOB_ID=$(jq -r .job_id /tmp/infx-recovery-target.json) -ORIGINAL_PR=$(jq -r .pr_number /tmp/infx-recovery-target.json) -ORIGINAL_MERGE_SHA=$(jq -r .merge_sha /tmp/infx-recovery-target.json) - -gh run view "$TARGET_RUN_ID" --repo SemiAnalysisAI/InferenceX \ - --job "$TARGET_JOB_ID" --log > "/tmp/infx-target-$TARGET_RUN_ID.log" - -python3 -m infx.workflows.recover_failed_ingest audit-changelog \ - --ref "$ORIGINAL_MERGE_SHA" -``` - -**目标关卡:** 必须是 `main` 上 `.github/workflows/merge-ingest.yml` 的已完成 push run;若为 `merge-ingest.yml` 启用前的旧合并,则为 `.github/workflows/run-sweep.yml` 的已完成 push run。忘记复用命令时,Merge Ingest run 会在复用检查处失败,此时尚未上传元数据或 dispatch,因此不会留下无有效数据的摄取。旧版 `run-sweep.yml` 目标即使结论为 `success` 或 `cancelled`,仍可能包含无有效数据的摄取:忘记启用复用时,GPU 任务可能被取消,但 `trigger-ingest` 仍针对目标自己的 run ID 成功。不要删除该行;正确恢复后的发布会使用新的 run ID。 - -#### 2. 验证 source、祖先关系和制品 - -```bash -SOURCE_RUN_ID= -SOURCE_JSON=$(gh api \ - "repos/SemiAnalysisAI/InferenceX/actions/runs/$SOURCE_RUN_ID") -SOURCE_HEAD_SHA=$(jq -r .head_sha <<<"$SOURCE_JSON") -SOURCE_RUN_ATTEMPT=$(jq -r .run_attempt <<<"$SOURCE_JSON") - -jq -e ' - .event == "pull_request" and - .status == "completed" and - .path == ".github/workflows/run-sweep.yml" -' <<<"$SOURCE_JSON" >/dev/null - -gh api "repos/SemiAnalysisAI/InferenceX/pulls/$ORIGINAL_PR/commits" \ - --paginate --jq '.[].sha' | grep -Fx "$SOURCE_HEAD_SHA" - -gh api \ - "repos/SemiAnalysisAI/InferenceX/actions/runs/$SOURCE_RUN_ID/artifacts?per_page=100" \ - --paginate --jq '.artifacts[] | select(.expired == false) | .name' \ - | grep -Eq '^(results_bmk|eval_results_all|bmk_agentic_)' -``` - -未显式固定的 source 只能使用成功 run。明确固定的失败 run 只能恢复其中已完成的点,因为失败的基准结果行会被跳过。将 source SHA 与原始 PR 的最终 head 比较;如果后续编辑改变了待恢复项的镜像、模型、recipe、runner、launcher、基准参数或配置值,必须**停止**。 - -#### 3. 在更改 changelog 前授权复用 - -从当前 `main` 创建一个空恢复 PR,只添加一个 full-sweep 标签,并在推送恢复 changelog commit 前固定 source: - -```bash -gh pr edit "$RECOVERY_PR" --repo SemiAnalysisAI/InferenceX \ - --add-label full-sweep-fail-fast -gh pr comment "$RECOVERY_PR" --repo SemiAnalysisAI/InferenceX \ - --body "/use $SOURCE_RUN_ID" -``` - -把恢复条目追加到 `perf-changelog.yaml` 末尾;绝不要修改历史字节。保留原始 `config-keys`、`description`、`evals-only` 和 `scenario-type`,但使用恢复 PR URL。在 `inferencex-e2e/` 中验证 changelog 和生成的范围,以便工具正确解析主配置文件的相对路径: - -```bash -python3 -m infx.workflows.validate_perf_changelog \ - --changelog-file perf-changelog.yaml \ - --base-ref origin/main \ - --head-ref "$RECOVERY_COMMIT" -python3 -m infx.matrix.plan \ - --changelog-file perf-changelog.yaml \ - --base-ref origin/main \ - --head-ref "$RECOVERY_COMMIT" \ - > /tmp/recovery-full-config.json -``` - -#### 4. 在不改变文件树的情况下保留 source 祖先关系 - -恢复分支最终 head 必须以恢复 commit 为第一父提交、source SHA 为第二父提交,并且文件树保持不变: - -```bash -TARGET_PARENT=$(git rev-parse HEAD) -TARGET_TREE=$(git rev-parse "${TARGET_PARENT}^{tree}") -ATTACH_SHA=$( - printf 'chore: attach reusable sweep run %s\n' "$SOURCE_RUN_ID" | - git commit-tree "$TARGET_TREE" \ - -p "$TARGET_PARENT" \ - -p "$SOURCE_HEAD_SHA" -) -git reset --hard "$ATTACH_SHA" - -test "$(git rev-parse HEAD^1)" = "$TARGET_PARENT" -test "$(git rev-parse HEAD^2)" = "$SOURCE_HEAD_SHA" -test "$(git rev-parse HEAD^{tree})" = "$(git rev-parse HEAD^1^{tree})" -test "$(git diff --name-only origin/main...HEAD)" = "inferencex-e2e/perf-changelog.yaml" -git diff --check origin/main...HEAD -``` - -推送后,绝不要对这个 carrier commit 执行 rebase、本地 squash、amend 或 force-push。必须确认 source SHA 出现在 PR commit 列表中、Files 中只有 `perf-changelog.yaml`、`check-changelog` 与 `reuse-sweep-gate` 通过,并且 PR GPU 任务被跳过。只有获得明确授权后才能合并,且绝不能绕过失败或等待中的检查。随后使用上文交接流程验证新的 Merge Ingest push run 和下游应用 run。 - -权威来源:[完整失败摄取恢复命令](../../.claude/commands/recover-failed-ingest.md)([历史快照](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.claude/commands/recover-failed-ingest.md),`merge-ingest.yml` 启用前)。 - -## AMD root-owned 工作区的预防与恢复 - -### 防止复发 - -容器可能以 root 身份运行,同时 GitHub 工作区被 bind mount。基准测试工作流为每个作业设置以下变量,使 Python 字节码缓存不写入工作区: - -```yaml -PYTHONDONTWRITEBYTECODE: '1' -PYTHONPYCACHEPREFIX: /tmp/inferencex-pycache -``` - -不要把这些路径重新覆盖到工作区。出现 `EACCES` 清理错误后,应执行下述恢复扫描,包括由已退役启动器遗留的日志导致的错误。 - -来源:[Python 缓存预防](../../.github/workflows/benchmark-tmpl.yml#L145-L146)。 - -### 集群特定恢复 - -这些操作需要集群特权访问并须获得明确批准。请遵循维护者 playbook,而不是复制其中的命令: - -- MI355X TW `EACCES` 工作区清理:[`clean-amd-mi355-runner-root-files.md`](../../.claude/commands/clean-amd-mi355-runner-root-files.md)。先只读扫描,只删除 `actions-runner/_work/` 下已核实的路径,绝不对 `/it-share` 运行无范围限制的 `rm -rf`。 -- MI300X `enroot-nsenter: failed to create user namespace`(pyxis):[`debug-mi300-enroot-pyxis.md`](../../.claude/commands/debug-mi300-enroot-pyxis.md)。修改任何节点前,先确认各节点的 AppArmor userns 配置漂移。 - -## 安全地重跑工作流 - -先列出失败任务并保存仅失败日志: - -```bash -gh run view "$RUN_ID" --repo SemiAnalysisAI/InferenceX --json jobs \ - --jq '.jobs[] | select(.conclusion=="failure") | "\(.databaseId)\t\(.name)"' -gh run view "$RUN_ID" --repo SemiAnalysisAI/InferenceX --log-failed \ - > /tmp/sweep_failed.txt -``` - -| 诊断 | 安全操作 | 禁止操作 | -| --- | --- | --- | -| PR sweep 上的临时 runner pickup、网络问题或已确认基础设施偶发故障 | `gh run rerun "$RUN_ID" --repo SemiAnalysisAI/InferenceX --failed` | dispatch 新 sweep 并丢失原始 run 上下文 | -| MI355X 工作区清理或 MI300X 修复后的 cancelled run | 先尝试仅重跑失败任务;如果 GitHub 因 run 被取消而拒绝,运行 `gh run rerun "$RUN_ID" --repo SemiAnalysisAI/InferenceX` | 在修复共享状态前完整重跑;它可能以相同方式失败并消耗 GPU 时间 | -| 可复现 OOM、HIP/CUDA/RCCL/NCCL 错误、无效结果、错误分数、镜像/recipe/配置缺陷 | 先修复或验证根因,再重跑最窄的受影响路径 | 仅因为某次重试通过就把事件标记为偶发故障 | -| 正确的 InferenceX-app 摄取发生部分 DB/迁移/验证失败 | 重跑该应用 run 的失败任务;如有需要,完整应用重跑在数据层面具有幂等性 | 重跑 InferenceX 目标或其生成 GPU 结果的 source sweep | -| source 制品错误/缺失/过期,或 source/merge 对错误 | 修复制品选择,或使用恢复 PR 流程 | 反复重跑同一个错误摄取 | -| 正式 push-to-main 摄取缺失、被跳过、无有效数据或失败 | 创建经过验证的恢复 PR,并复用原始 PR 制品 | 重跑失败目标工作流/任务,或创建一次性摄取工作流 | - -如果已取消的 InferenceX run 拒绝部分重跑,完整重跑会重复所有符合条件的工作,成本可能很高。移除再重新添加 PR sweep 标签是最后手段,因为它会创建新 sweep,而不是保留失败 run。 - -来源:[偶发故障重跑规则](../../.agents/skills/debug-runs/SKILL.md#L146-L153)、[cancelled run 回退方案](https://github.com/SemiAnalysisAI/InferenceX/blob/0c28706b33d4a796b82f6f9c3594c19c46365575/.claude/commands/clean-amd-mi355-runner-root-files.md#L52-L57)、[应用摄取幂等性](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/docs/data-pipeline.md#L26-L34)。 - -## 故障分类 - -按最早出现故障的边界分类,而不是按最后一个红色任务分类。 - -| 类别 | 证据 | 负责人/操作 | -| --- | --- | --- | -| **基准/运行时** | server 一直未就绪;OOM;HIP/CUDA/RCCL/NCCL;请求失败;原始结果缺失;成功请求数为零 | 复现准确配置,与工作节点/SKU 比较,修复 recipe/镜像/运行时;不要改摄取 | -| **评测** | eval-only 没有 `results*.json`;分数验证失败;`meta_env.json` 覆盖范围/并发不匹配;sample 文件不完整 | 检查评测器输出和请求并发;保留已上传的部分制品;修复评测器/配置后再重跑 | -| **处理/收集** | 原始 JSON 存在但缺少 `agg_*.json`;收集器无法解析;缺少 `results_bmk` 或 `eval_results_all` | 检查 `infx.results.fixed_sequence`/收集器日志和制品布局;理解格式问题后才重跑失败工作流任务 | -| **Runner 工作区** | checkout 清理在 `_work/.../benchmark_logs/logs/slurm_job-*` 下报 `EACCES` | 只读所有者扫描、批准后的有范围删除、零结果验证,然后重跑 | -| **MI300X provisioning** | pyxis/enroot 命名空间特征;失败节点 sysctl 为 `1`,工作节点为 `0` | 获批后修复节点并升级 provisioning image,然后重跑受影响任务 | -| **Dispatch/交接** | `merge-ingest.yml` 的 `ingest` dispatch(旧版为 `trigger-ingest`)后没有应用 run;curl/auth 失败;应用准备日志显示错误 ID 或制品缺失/过期 | 修复 dispatch 凭据/选择,或使用恢复流程;不要重跑 GPU 工作 | -| **ETL/数据库** | 正确 source/merge 对和制品已准备,随后迁移/摄取/验证失败 | 诊断数据库/服务原因后重跑同一应用摄取;依靠幂等性,而非手动删除 | -| **映射/数据质量** | 应用报告跳过失败行、unmapped model/hardware/precision、评测行缺失或数量不合理 | 新增/修复实体映射或源元数据;存在 unmapped 数据时,工作流绿色也不代表完成验证 | -| **发布/来源** | changelog、source-run 来源、merge-run 身份错误,或无有效基准数据的伪造 run | 使用 append-only 恢复 PR;保留 source 祖先关系,并验证准确的下游摄取 | - -可执行的事件报告应记录: - -```text -InferenceX run / attempt / event / SHA: -Failed job / runner / node / Slurm job: -Failure class and first causal signature: -Raw, per-config, and aggregate artifact names/counts: -Expected source run / attempt / SHA: -Expected merge run: -InferenceX-app ingest run: -Repair performed and approval obtained: -Rerun command and resulting run: -DB verification, skipped rows, and unmapped entities: -Remaining durable fix: -``` - -这些证据就是完成关卡。如果没有制品身份、source/merge 身份和摄取数量,仅仅“工作流绿色”并不代表结果恢复已经验证。 - -### AMD 多节点 GPU 预检协调 - -Slurm 启动器先在独立步骤中完成所有选定节点的 Docker 预清理和现有 GPU VRAM -回收检查,然后才启动服务器容器。任一节点预检失败都会阻止服务步骤启动,不会 -消耗健康节点等待容器就绪的期限。节点本地的 `preflight_.log` 文件 -通过常规日志汇总流程收集,包括失败日志。VRAM 阈值、15 分钟 GPU 检查期限及 -容器和服务器就绪期限均保持不变。这一协调消除了节点间等待的竞态,但无法修复 -不能回收显存的 GPU 驱动。现有 Docker 预清理范围保持不变。 diff --git a/inferencex-e2e/docs/results-and-ingestion.md b/inferencex-e2e/docs/results-and-ingestion.md index 12b298307d..7d6b2c3a8f 100644 --- a/inferencex-e2e/docs/results-and-ingestion.md +++ b/inferencex-e2e/docs/results-and-ingestion.md @@ -1,11 +1,5 @@ # Results and Ingestion -
- -**English** | [中文](results-and-ingestion_zh.md) - -
- Use this page to identify benchmark artifacts, inspect their contracts, and decide whether a run is safe to hand to InferenceX-app. The producers and ingest code remain authoritative. InferenceX-app links below are pinned to commit [`3be1c34`](https://github.com/SemiAnalysisAI/InferenceX-app/tree/3be1c34a174f62fea2194f1133210e692e5bf415). ## Source map diff --git a/inferencex-e2e/docs/results-and-ingestion_zh.md b/inferencex-e2e/docs/results-and-ingestion_zh.md deleted file mode 100644 index aae3d44021..0000000000 --- a/inferencex-e2e/docs/results-and-ingestion_zh.md +++ /dev/null @@ -1,472 +0,0 @@ -# 结果与摄取 - -
- -[English](results-and-ingestion.md) | **中文** - -
- -本页用于识别基准工件、检查其契约,并判断一次运行能否安全交给 InferenceX-app。生产端和摄取代码仍是权威来源。下列 InferenceX-app 链接固定在提交 [`3be1c34`](https://github.com/SemiAnalysisAI/InferenceX-app/tree/3be1c34a174f62fea2194f1133210e692e5bf415)。 - -## 权威来源 - -| 权威来源 | 控制内容 | -| --- | --- | -| [`benchmark-tmpl.yml`](../../.github/workflows/benchmark-tmpl.yml)、[`benchmark-multinode-tmpl.yml`](../../.github/workflows/benchmark-multinode-tmpl.yml) | 吞吐量、评测和 AgentX 工件的单配置名称、文件及上传规则 | -| [`infx/results/fixed_sequence.py`](../infx/results/fixed_sequence.py) | 固定序列吞吐量聚合架构及派生的每 GPU 指标 | -| [`infx/results/collect_results.py`](../infx/results/collect_results.py)、[`collect-results.yml`](../../.github/workflows/collect-results.yml) | 将基准结果递归收集为 `agg_.json` 和 `results_` | -| [`infx/results/collect_eval_results.py`](../infx/results/collect_eval_results.py)、[`collect-evals.yml`](../../.github/workflows/collect-evals.yml) | 评测发现、指标提取、批量并发选择及 `eval_results_` | -| [`infx/results/evals.py`](../infx/results/evals.py)、[`eval_artifacts.py`](../infx/results/eval_artifacts.py) | 供收集流程和 Klaud 共用的评测读取、结果选择、复用一致性检查及重跑去重 | -| [`infx.results.agentic`](../infx/results/agentic/__init__.py)、[`request_metrics.py`](../infx/results/agentic/request_metrics.py)、[`artifacts.py`](../infx/results/agentic/artifacts.py) | AgentX 聚合架构、原始记录过滤、请求计数和派生指标 | -| [`validate_agentic_result.py`](../infx/results/agentic/validate_agentic_result.py) | AgentX 上传前错误率门禁 | -| [`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml)、[`recover-reused-ingest.yml`](../../.github/workflows/recover-reused-ingest.yml) | 应用分发载荷及 source/merge 运行身份 | -| [InferenceX-app `prepare-ci-artifacts.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/prepare-ci-artifacts.ts)、[`ci-artifact-preparation.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/lib/ci-artifact-preparation.ts) | 跨运行工件选择、attempt 及复用来源信息 | -| [InferenceX-app `ingest-ci-run.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/ingest-ci-run.ts) | 端到端摄取顺序、配对、跳过、汇总和刷新 | -| [InferenceX-app `benchmark-mapper.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/etl/benchmark-mapper.ts)、[`eval-mapper.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/etl/eval-mapper.ts)、[`agentic-v3-flatten.ts`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/etl/agentic-v3-flatten.ts) | 工件到数据库的架构和规范化 | -| [InferenceX-app 架构](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/migrations/001_initial_schema.sql)、[AgentX 迁移](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/migrations/008_agentic.sql) | 持久化自然键、JSONB 指标和 trace-replay 旁表 | -| [InferenceX-app 基准测试 API](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/app/src/app/api/v1/benchmarks/route.ts)、[模型常量](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/constants/src/models.ts) | 已发布结果查询与前端模型名称 | - -## 索引 - -1. [各层身份](#各层身份) -2. [吞吐量工件](#吞吐量工件) -3. [评测工件](#评测工件) -4. [AgentX 工件](#agentx-工件) -5. [应用交接和复用运行](#应用交接和复用运行) -6. [摄取阶段](#摄取阶段) -7. [去重和失败行行为](#去重和失败行行为) -8. [来源不变量](#来源不变量) -9. [已发布结果 API](#已发布结果-api) -10. [安全检查](#安全检查) -11. [验证和停止条件](#验证和停止条件) - -## 各层身份 - -不要用一种标识符替代另一种。 - -| 层 | 身份 | 含义 | -| --- | --- | --- | -| GitHub 工作流 | `(github_run_id, run_attempt)` | 一次执行 attempt。InferenceX-app 将其存为 `workflow_runs` 自然键。 | -| 已上传工件 | 一个工作流运行内的工件 `name` | 可下载的文件包。重跑可以再次上传完全相同的名称。 | -| 单配置结果 | `RESULT_FILENAME`,多点 AgentX 路径按并发各产一个文件时还包含 `_concN` 后缀 | 用于命名文件和同级工件包的运行时配置身份。它不是数据库键。 | -| 规范化配置 | 模型、硬件、框架、精度、推测方法、解耦状态、拓扑及相关配置字段 | InferenceX-app 在规范化后解析或创建一条 `configs` 记录。 | -| 吞吐量或 AgentX 数据库点 | `(workflow_run_id, config_id, benchmark_type, isl, osl, conc, offload_mode)`,空值视为相等 | 幂等基准身份。AgentX 使用 `benchmark_type=agentic_traces`、空 `isl`/`osl`,并将并发解释为用户数。 | -| 评测数据库点 | `(workflow_run_id, config_id, task, isl, osl, conc)` | 所有可空维度均以相同值填充时,聚合评测和单配置评测工件会汇入同一记录。当前唯一约束采用 PostgreSQL 普通空值语义,因此空 `isl`、`osl` 或 `conc` 不会与另一个空值冲突。 | -| 评测样本 | `(eval_result_id, doc_id)` | 单文档样本身份。 | -| AgentX 原始旁表 | `benchmark_results.trace_replay_id` | 从规范化 AgentX 数据点指向保留及预计算 trace 数据的链接。 | - -由于每次正式摄取都复用 PR sweep,这些区别尤其重要。工件字节来自 PR sweep,而变更日志元数据和摄取触发来自之后 `main` 上的 Merge Ingest 运行。存储后的基准记录仍归属于 source 运行及其 source attempt。 - -## 吞吐量工件 - -### 生产端和收集器 - -对于单节点固定序列任务,[`benchmark-tmpl.yml`](../../.github/workflows/benchmark-tmpl.yml) 根据实验、精度、框架、TP/PP/DCP/PCP/EP/DP-attention、解耦、推测模式、并发和具体 runner 构建 `RESULT_FILENAME`。基准先写入 `.json`。[`infx/results/fixed_sequence.py`](../infx/results/fixed_sequence.py) 读取该文件并写入 `agg_.json`。工作流按下列身份上传: - -```text -artifact: bmk_ -file: agg_.json -``` - -多节点模板在基础名称中编码 prefill 和 decode 拓扑、worker 数、模式、并发及 runner。一个 `bmk_` 工件中可以包含多个 `agg__*.json` 文件。 - -[`collect-results.yml`](../../.github/workflows/collect-results.yml) 通常接收 `result-prefix: bmk`。它下载 `bmk_*`,[`infx/results/collect_results.py`](../infx/results/collect_results.py) 再递归加载每个 JSON 文件,形成一个数组。交接身份为: - -```text -artifact: results_bmk -file: agg_bmk.json -shape: array of benchmark row objects -``` - -收集器不验证记录、不排序,也不去重。成功解析 JSON 是它唯一的内容检查。应把 `results_bmk` 视为传输聚合,而不是所有记录均可用的证明。 - -### 吞吐量记录架构 - -固定序列转换器要求 runner、框架、精度、推测模式、结果文件名、ISL、OSL、解耦、模型前缀和镜像元数据。其基础输出包括: - -| 字段组 | 重要字段 | -| --- | --- | -| 配置和路由 | `hw`、`model`、`infmax_model_prefix`、`framework`、`precision`、`spec_decoding`、`image`、`disagg`、`is_multinode`、`isl`、`osl`、`conc` | -| 单节点拓扑 | `tp`、`pp`、`dcp_size`、`pcp_size`、`ep`、`dp_attention` | -| 多节点拓扑 | `prefill_tp`、`prefill_pp`、`prefill_dcp_size`、`prefill_pcp_size`、`prefill_ep`、`prefill_dp_attention`、`prefill_num_workers`,对应的 `decode_*` 字段,`num_prefill_gpu`、`num_decode_gpu`,以及可选的 `prefill_hw`/`decode_hw` | -| 主要派生指标 | `tput_per_gpu`、`input_tput_per_gpu`、`output_tput_per_gpu` | -| 延迟和交互性 | 基准输入中每个以 `ms` 结尾的键都会从毫秒换算为秒,并移除 `_ms`。包含 `tpot` 的键还会产生其倒数 `intvty`。 | -| 可选运行时元数据 | 形式必须精确为 `{name, version}` 的 `router`、`kv_p2p_transfer`,以及多节点结果中由 srt-slurm 遥测包补入的实测功耗 | - -单节点 GPU 数为 `tp * pp * pcp_size`。DCP 不会增加物理 GPU 数。多节点每 GPU 指标的分母使用声明的 prefill 和 decode GPU 数。无效或缺失的必需元数据会使转换失败。只有多节点结果执行功耗聚合;单节点结果不含功耗字段或结论。功耗聚合默认尽力而为;当设置 `REQUIRE_POWER=1` 时,功耗验证失败会在保留已有结果和审计后使任务失败。 - -InferenceX-app 将路由字段作为列或配置维度,并把数值测量存入 `benchmark_results.metrics` JSONB。映射器支持共享拓扑的 v1、拆分 prefill/decode 拓扑的 v2,以及嵌套 AgentX 指标的 v3。未知数值指标会被保留并产生警告,因此架构可以扩展,同时不会无提示地丢失数值数据。 - -### 固定序列基准结果状态与 PowerX 审计 - -服务客户端在保存原始结果前写入 `benchmark_outcome`,保留现有的 5% 最大请求失败率,以及请求总数、完成数和失败数。处理器检查该记录并复制到聚合结果中;即使遥测有效,请求失败率超限仍返回失败。零成功请求会保留诊断聚合结果,但不会生成不存在的延迟倒数。请求计数无效时,失败诊断状态保留原始 `requested`/`completed` 值和 `error`,不生成无依据的失败数或失败率;客户端先保存原始 JSON 再退出,处理器仍拒绝该结果。没有状态元数据的历史结果仍可区分;功耗有效不能证明基准成功或答案质量。 - -`power_invalid_reasons` 和 `power_audit` 在数值指标旁携带有界摘要,包括可用的测量窗口、预期与观测 GPU 数、采样诊断、观测设备标识和生产者版本。`source` 指向保留的 `power_validation_*.json` 工件名称。设备标识保留采集器原有语义。 - -对于多节点固定序列任务,`python -m infx.results.fixed_sequence --all` 先处理所有已有结果,再返回失败。它接受 `_c_gpus_...`、`_conc_gpus_...` 和 AMD 的 `_concurrency__req_rate__gpus_...` 文件名,也支持 `inf` 请求速率。它将结果并发度与 `CONC_LIST` 比较,拒绝重复或矛盾的点身份,并将遗漏和错误记录到 `result_processing_.json`。共享工作池通过 `AGGREGATE_GPUS` 及零值角色 GPU 数进行遥测验证;独立的 prefill/decode 能耗保持缺失。当 `DISAGG=true` 的配置组中某个点没有 decode worker 时,聚合行会有意设置 `disagg: false` 并记录 `num_aggregate_gpu`;文件名、工件名和工作流输入仍保留配置组身份。下游应按聚合行的拓扑解释测量结果。 - -PR changelog 选择具有代表性的 NVIDIA 和 AMD 覆盖,并非所有受影响配置的完整列表;共享处理逻辑的变更适用于所有固定序列配置。 - -启动器或验证失败后仍会运行处理步骤以及多节点任务的功耗诊断上传,并在审计工件中保留原始及聚合 JSON。正常 `bmk_*` 上传要求基准和处理步骤成功,因此不完整批次或 Slurm 失败不会发布诊断数据。主分支的入库触发器仍可发布部分失败 sweep 中其他成功配置的数据;这并不证明整个硬件范围已完成覆盖。下游导入器可利用保留的状态拒绝明确失败的基准结果。 - -### SRT 多节点窗口保留 - -SRT samples CSV 支持版本 1、2 和 3。版本 3 新增可选的 `temperature_c`(摄氏度);温度保留在上传产物中供应用读取,不参与 GPU 能量计算。缺失值保持为空。格式错误的温度单元格会按现有严格产物校验规则使该包无效。应先部署此读取器,再升级到输出版本 3 的采集器。 - -功耗审计文件在 `selected_window` 中保留独立验证后的测量;`package_integrity_valid` -记录共享证据检查,`window_validations` 记录逐窗口结论。保留测量仍要求证据可信、 -拓扑匹配且结果绑定正确。其他窗口失败时,顶层及聚合结果的 `power_valid` 仍为 false, -审计顶层 `metrics` 为空,聚合结果不输出功耗指标,`REQUIRE_POWER=1` 返回失败。 -审计文件仍可包含健康窗口的指标, -以及顶层 `per_gpu_energy_j` / `per_gpu_max_sample_gap_s` 诊断字段;这些不构成发布许可。 -回放不会重写输入或修复不一致的证据。 - -## 评测工件 - -### 单配置身份和收集 - -每个评测上传名为 `eval__`。当前允许的载荷包括 `meta_env.json`、`results*.json`、样本 JSONL,以及厂商评估的原生报告、详细结果和归档。收集器只使用元数据和 lm-eval 结果 JSON 来生成聚合记录。 - -收集与复用共用结果读取和选择逻辑,但保留各自的校验规则。收集可以输出失败批次中已完成的点;复用则拒绝失败或不完整的批次。每个阶段使用已读取的 JSON 完成选择和校验。去重改写或删除工件后,校验会重新读取最终文件。 - -共享评测元数据写入器保留单节点的 `DP_ATTENTION`,并将其作为 -`prefill_dp_attention` 和 `decode_dp_attention` 的默认值。只有 -`IS_MULTINODE=true` 的任务才会转换独立的 prefill/decode 环境变量; -这类任务两侧的 DP attention 设置可以不同。收集器不会根据工件名称或 -服务端日志重建拓扑。受旧版无条件转换逻辑影响的历史工件,可能将实际启用 -DP attention 的单节点评测记录为 `false`。修复写入器不会修复这些工件或 -已有数据库记录:应先核实原始任务配置和服务端日志,再更正元数据、重新生成 -聚合结果并重新摄取受影响的数据。 - -[`infx/results/collect_eval_results.py`](../infx/results/collect_eval_results.py) 执行以下规则: - -1. 评测集是包含 `meta_env.json` 的根目录或一级子目录。 -2. 候选结果文件必须能解析为对象并包含 `lm_eval_version`。 -3. 传统评测集按修改时间贡献最新的候选文件。 -4. 列表类型的 `eval_concs` 标识批量评测集。每个允许并发贡献最新的 `_concN` 结果。如果存在 `completed_eval_concs`,还会据此限制并发。 -5. `results` 中的每个任务成为一条逻辑记录。 -6. 主要 `score` 优先使用 strict 或 resolved exact match,其次使用 accuracy。标准误差单独保留。 - -收集交接形式为: - -```text -artifact: eval_results_all -file: agg_eval_all.json -shape: array of one row per config, concurrency, and task -``` - -### 评测聚合架构 - -| 字段组 | 重要字段 | -| --- | --- | -| 配置 | `is_multinode`、`model_prefix`、`model`、`hw`、`framework`、`precision`、`spec_decoding`、`isl`、`osl`、`conc` | -| 拓扑 | `tp`、`ep`、`dp_attention`,以及拆分的 `prefill_*` 和 `decode_*` worker 字段 | -| 评测 | `task`、`score`、`score_name`、`score_se`、`em_strict`、`em_strict_se`、`em_flexible`、`em_flexible_se`、`n_eff` | -| 可追踪性 | `source`,即已下载工件树中被选中的结果 JSON 路径 | - -应用也会读取每个未聚合的 `eval_*` 目录。`meta_env.json` 提供配置身份,`results_*.json` 提供 `lm_eval_version`、任务、原始数值指标和有效样本数。应用会规范化 strict 和 flexible exact-match 名称。样本文件按任务附加到解析后的评测记录。该双路径是有意设计。聚合记录用于摘要摄取,单配置文件则保留样本详情。 - -收集器解析失败时,`load_json` 会跳过文件,不会生成一条失败的评测记录。缺少 `meta_env.json`、没有可识别的 lm-eval 结果、`results` 对象为空,或并发不在 `completed_eval_concs` 中,都会导致不输出聚合记录。 - -## AgentX 工件 - -### 三种相关身份 - -AgentX 使用同一 `RESULT_FILENAME` 系列,但生成两类同级工件: - -```text -aggregate artifact: bmk_agentic_ -aggregate file: .json -raw artifact: agentic_ -raw tree: results/**, excluding inputs.json and profile_export_raw.jsonl -``` - -聚合工件匹配 `bmk_*` 收集模式,因此也会成为 `results_bmk/agg_bmk.json` 中的一条记录。原始同级工件不会交给 `infx.results.collect_results`。InferenceX-app 移除 `bmk_` 和 `agentic_` 后缀前缀,将 `bmk_agentic_` 与 `agentic_` 配对。对于以 `_concN.json` 命名的文件,并发也参与 trace 同级工件查找。 - -服务器日志是单独的 `server_logs_` 工件。应用会使用完全移除前缀后的后缀作为回退,从而让 AgentX 记录找到不含 `agentic_` 前缀的日志工件。 - -只有 `IS_MULTINODE=true` 的回放才采集 AgentX 功耗。单节点回放(包括设置 -`IS_MULTINODE: false` 的聚合式 srt-slurm 配方)无论 `ENABLE_AGENTX_POWER` 如何设置, -都不发布功耗字段或结论。多节点运行在 `power_audit_` 工件中保留 -`LOGS/power/` 下的部署遥测,以及 `LOGS/agentic/` 下各并发的窗口和校验文件。 -即使基准测试失败,已有的审计文件和 AgentX 聚合结果仍会上传。 -文件缺失不代表路径支持功耗采集:多节点配方还需启用 `telemetry`,让固定版本的 srt-slurm -向自定义基准命令导出 `SRT_MEASUREMENT_WINDOW_DIR`;InferenceX 据此目录和回放本身推导结果根目录与并发数。 -缺少测量窗口接口时,聚合结果记录 `power_valid: 0`,审计原因标记为 -`multinode_power_contract_missing`;设置 `REQUIRE_POWER=1` 还会在保留已有结果后使任务失败。 - -`power_valid: 1` 与 `power_metric_schema_version: 2` 只表示 GPU 遥测有效, -不代表请求计数或模型质量通过验证。用于可靠对比前,应将已发出、已完成、已取消及 -出错请求数与原始 profiling 记录和 token 总数核对。GPU 板卡能耗与整机功耗估算分开报告。 - -GB200 GLM-5.2 聚合部署的 AgentX 配方通过共享 custom-window producer、DCGM -监控器和任务结束后的功耗适配器,覆盖两个各含四块 GPU 的节点。launcher 按实际 -选择的并发数绑定测量窗口,在返回失败前保留 Slurm 原生状态、producer 和 exporter -身份以及校验诊断。聚合 JSON 缺失或损坏时,仍生成该并发点的 -`power_validation.json`,且不伪造聚合结果。普通 Slurm 时限以及包括 HiCache 和合成接受率在内的 -服务配置保持不变。其他 GB200 AgentX 配方继续使用原有 producer 与功耗限制。 - -### 原始输入和聚合架构 - -[`process_agentic_result.py`](../infx/results/agentic/process_agentic_result.py) 可解析当前的 `results/aiperf_artifacts` 布局,也可解析只含一个子目录的嵌套布局。它要求存在 `profile_export.jsonl`,并在存在时读取以下输入: - -| 输入 | 作用 | -| --- | --- | -| `profile_export.jsonl` | 单请求指标和生命周期元数据。必需。 | -| `profile_export_aiperf.json` | AIPerf 聚合元数据,包括已输出时的数据集来源。可选。 | -| `server_metrics_export.json` | 服务器缓存、KV-cache 和 token 指标。数据缺失时会生成空的或带警告的服务器指标,不会取代请求数据源。 | -| 服务器日志 | 特定框架的服务器指标和容量回退来源。 | - -每条非空 JSONL 记录都会增加 `records_total`。`metadata.benchmark_phase` 不等于 `profiling` 的记录是 warmup 诊断,会被排除。含真值 `error` 的记录也会被排除并分类。没有 phase 的旧记录按 profiling 处理。保留记录数成为 `num_requests_successful`。完整计数保存在 `request_accounting` 中,包括 profiled、总丢弃、warmup 丢弃、错误丢弃和 `error_categories`。 - -`request_metrics.tokens.output_expected` 只读取 AIPerf 在 -`metadata.dataset.hf_dataset_name` 中明确声明的数据集的本地 trace 元数据。 -由于导出内容没有记录实际解析到的数据集 revision,对应缓存必须恰好只有一个 snapshot。 -缺少数据集身份、缺少元数据或存在多个 snapshot 时,该分布保持为空; -不会根据缓存修改时间或其他数据集进行猜测。实际 token 数、GPU 能耗的分母及 -AIPerf 理论缓存命中率继续使用各自原有的数据来源。 - -AgentX 聚合的顶层身份和拓扑字段与基准摄取兼容。 - -`num_gpus` 明确记录共享处理器使用的物理 GPU 数。单节点运行使用 -`tp * pp * pcp_size`,EP 和 DCP 共享设备。使用结果时应优先读取该字段, -避免仅根据并行参数推断 GPU 数。 - -其他重要 AgentX 字段包括: - -| 字段组 | 重要字段 | -| --- | --- | -| 场景和请求数 | `scenario_type: agentic-coding`、`num_requests_total`、`num_requests_successful`、`request_accounting` | -| 缓存配置 | `kv_offloading`、`kv_offload_backend`、可选的 `kv_p2p_transfer`、`allocated_cpu_dram_gb`、可选的 `router` | -| 来源 | 从 AIPerf `metadata.dataset` 复制的 `dataset` | -| 请求指标 | `request_metrics.qps`,包含 TTFT/E2EL/ITL/TPOT/交互性的 `latency` 块,token 分布、吞吐量、缓存和每 GPU 吞吐量 | -| 服务器指标 | `server_metrics.cache`、`kv_cache`、token 总数、来源详情,以及可能存在的 `warnings` | -| 兼容性 | `kv_cache_pool_tokens` 镜像 `server_metrics.kv_cache.gpu_total_tokens` | - -当 `dynamo-sglang` 运行包含 `sglang:` 遥测时,处理器使用 SGLang 适配器 -聚合缓存、利用率和 token 指标。逻辑 GPU KV 容量保持 `null` 并附带警告, -因为多个 TP rank 可能重复报告容量值。原始 Dynamo 前端总数可能包含预热请求。 -缺少主机命中计数并不代表 CPU 缓存命中为零。 - -应用会将嵌套 AgentX v3 值展平为规范指标键。例如 `median_ttft`、`p95_e2el`、`total_tput_tps`、`tput_per_gpu`、`server_gpu_cache_hit_rate` 和 `gpu_kv_cache_usage_pct`。p50 映射为 `median`。存在 full-response ITL 字段时优先使用它。交互性百分位数按对应 ITL 百分位数的倒数派生,使历史记录和当前记录采用同一定义。 - -正常上传前,单节点工作流会运行 [`validate_agentic_result.py`](../infx/results/agentic/validate_agentic_result.py)。它要求聚合为对象,`request_count.avg` 是非负数值,已完成请求数为正,错误率不高于配置阈值。通过该门禁不表示没有失败请求。失败请求记录仍可通过 `request_accounting` 观察,但不参与性能指标计算。 - -## 应用交接和复用运行 - -每次合并时,[`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) 只向 InferenceX-app 分发 `ingest-results` 或 `ingest-agentic-results` 之一。变更日志增量包含 agentic 条目时,它分发携带 `database-target: production` 的 `ingest-agentic-results`。`run-sweep.yml` 从不分发摄取。 - -- `source-run-id` 标识被复用的 PR `run-sweep.yml` 运行,其基准、评测、AgentX、日志和统计工件提供测量数据。 -- `merge-run-id` 标识 `main` 上授权摄取并提供当前变更日志元数据的 Merge Ingest 运行。 -- 两个 ID 总是不同:`main` 从不运行 sweep,因此不存在同时提供测量工件和合并元数据的运行。 - -InferenceX-app 的工件准备会从 source 运行中,为每个完全相同的工件名保留最新且未过期的上传。在复用模式下,它排除 source 运行的 `changelog-metadata`,要求 merge 运行中存在未过期的变更日志工件,并把该 merge 运行工件加入计划。没有未过期 source 工件,或复用时没有 merge 运行变更日志,都会直接失败。 - -只有两个 ID 不同时,它才写入 `reused-ingest-metadata/reuse_source_run.json`。该文件记录 source ID、source attempt、URL、PR、head SHA,以及 ingest ID、ingest attempt 和 URL。摄取期间,该元数据会把记录归属切回 source 运行和 source attempt。source PR 分支、SHA 和公开运行 URL 继续附在测量记录上。触发时间可以来自 merge 运行。这样不会把复用的 PR 测量伪装成 merge 运行产出的数据。 - -两个应用工作流都会把 merge 运行 ID 和 attempt 传入初始 CI 设置,因为它代表触发包。`ingest-ci-run.ts` 随后读取复用元数据,并在创建或解析 `workflow_runs` 前有意将其替换为 source 身份。 - -## 摄取阶段 - -InferenceX-app 按以下顺序执行。固定序列工作流超时为 30 分钟。包含大量 blob 的 AgentX 工作流超时为 180 分钟,并可选择 staging 或 production。 - -1. **准备工件。** 获取 source 和 merge 运行元数据,选择未过期工件,将每个工件下载到空目录,并在需要时写入复用元数据。 -2. **运行数据库迁移。** 摄取不会假设目标架构已是最新状态。 -3. **解析来源。** 读取复用元数据,获取 GitHub 元数据,预加载规范化配置记录,创建或解析 source `(github_run_id, run_attempt)` 工作流记录。若 source 运行或 attempt 位于 run overrides 中,此阶段即停止,不写结果。 -4. **读取变更日志元数据。** 检测 `evals-only`。没有有效变更日志工件时,根据工作流元数据生成回退描述。Evals-only 运行跳过基准和运行统计阶段。 -5. **摄取基准记录。** 读取 `results_bmk` 以及每个 `bmk_*` 或 `results_*` 目录。规范化模型、硬件、框架、精度、拓扑、场景、offload 模式、镜像和数值指标。解析配置,跳过 point overrides,批量 upsert 记录,只根据批量写入成功的记录构建 availability。 -6. **附加大型旁路数据。** 链接服务器日志。配对 AgentX 聚合及原始工件。对于尚无 trace 链接的记录,worker 进程压缩原始 profile/server JSON,计算聚合统计、图表序列和请求时间线,随后持久化一条旁表记录并链接至基准记录。 -7. **链接数据集来源。** 从 AgentX 聚合记录提取数据集 slug,并 upsert 一条 `run_datasets` 映射。一个工作流内出现多个 slug 是硬冲突。若数据集表中没有该 slug,则会报告,因为在数据集摄取前,时间线深层链接会失败。 -8. **摄取运行统计。** 对非 evals-only 运行按硬件 upsert 成功数和总数。 -9. **摄取评测摘要和样本。** 先处理 `eval_results_all`,再处理单配置 `eval_*` 目录。两者解析到相同的评测自然键。按任务和文档 ID 附加样本 JSONL。 -10. **摄取变更日志并汇总。** Upsert 变更日志记录,打印新增、重复、跳过计数和未映射值,并写出供工作流告警使用的未映射实体报告。 -11. **刷新并验证。** 刷新 `latest_benchmarks`。工作流随后应用已审计的 point overrides,运行 `admin:db:verify`,再使应用缓存失效。 - -该顺序是有意设计。基准记录成功写入前不会创建 availability。所有目标记录已经有旁表时,不会插入 trace blob。只有在迁移、摄取、overrides 和数据库验证之后,才会使缓存失效。 - -## 去重和失败行行为 - -多个边界都存在去重。诊断重复前,先确认所处边界。 - -| 边界 | 行为 | -| --- | --- | -| CI 中的工件准备 | 每个完全相同的工件名保留最新且未过期的上传。复用只会以 merge 运行副本替换变更日志元数据。 | -| 应用直接下载模式 | [`dedupeArtifactsByLogicalName`](https://github.com/SemiAnalysisAI/InferenceX-app/blob/3be1c34a174f62fea2194f1133210e692e5bf415/packages/db/src/lib/github-artifacts.ts) 移除末尾 runner-pool 和 attempt token,并保留最新的逻辑工件,防止重试工件覆盖良好指标。 | -| 基准收集 | `infx.results.collect_results` 附加每个已解析 JSON。它不做记录级去重。 | -| 基准数据库写入 | 按基准自然键执行 `ON CONFLICT`,更新指标、镜像、功耗 worker 及相关字段。当新工件缺少服务器派生的 `kv_cache_pool_tokens` 时会保留已有值。 | -| 评测数据库写入 | 维度完整且匹配的聚合记录和单配置记录会按评测自然键冲突。后一次写入刷新指标,并返回同一记录 ID 供样本附加。任一可空键维度为空时,PostgreSQL 当前的普通唯一约束不会对这些记录去重。 | -| 评测样本 | 按 `(eval_result_id, doc_id)` 冲突,防止文档重复。 | -| AgentX trace 旁表 | 先查询已有链接。所有基准记录都已链接时,跳过 blob 准备和插入。 | - -失败数据与去重分开处理: - -- 当数值类型 `num_requests_successful` 为零且存在 `num_requests_total` 时,应用基准映射器会丢弃该记录。这也包括总数为零的服务器启动失败。此规则防止无数据重试替换良好的自然键记录。 -- AgentX 聚合从指标计算中排除 warmup 和错误请求记录,但在 `request_accounting` 中保留计数和类别。 -- 未知模型或硬件、缺少固定序列 ISL/OSL/并发、无效 JSON、point overrides 和数据库错误都会被跟踪为跳过,不会成为占位记录。 -- 评测收集器解析失败或缺少可识别结果文件时不输出记录。应用侧格式错误的单配置文件会产生警告或已跟踪的跳过。 -- 数据库写入具备幂等性,因此部分摄取可以安全重跑。但不能忽略新增跳过计数、冲突的数据集来源、缺失的 AgentX 原始同级工件或失败的数据库验证。 - -## 来源不变量 - -1. **运行来源包含两个维度。** 必须记录运行 ID 和 attempt。不含 attempt 的运行 URL 可能指向最新重跑,而不是已摄取字节对应的执行。 -2. **复用不会改变测量归属。** 指标和 source Git 元数据属于 `source-run-id`。只有 merge 运行变更日志和触发上下文来自 `merge-run-id`。 -3. **工件来源必须可检查。** 保留精确工件名、上传时间、过期状态和选中文件。评测聚合中的 `source` 是路径线索,不能替代工作流运行和工件身份。 -4. **数据集来源必须传递,不能推测。** AgentX 将 AIPerf `metadata.dataset` 复制到顶层 `dataset`。应用根据声明的 Hugging Face 数据集名派生仪表板 slug,不会根据基准名称猜测。 -5. **一个 AgentX 工作流最多映射一个数据集。** 冲突 slug 会停止摄取。缺少来源信息的旧工件不会改动已有运行映射。 -6. **规范化也是来源的一部分。** 诊断映射时,应保留原始 `model`、`infmax_model_prefix`、`hw`、`framework`、精度、镜像、拓扑和场景字段。数据库 config ID 是规范化身份,不是原始拼写。 -7. **AgentX 原始数据必须与聚合指标配对。** 基准点可以在没有原始旁表的情况下摄取,但系统会报告同级工件缺失,详情视图也会不完整。 - -## 已发布结果 API - -查询已经入库到 Dashboard 的结果时使用公共 API。查询尚未入库的 Run、原始输出、日志或调试证据时使用 GitHub Actions 产物。 - -```bash -INFERENCEX_API=https://inferencex.semianalysis.com/api/v1 -curl --fail --compressed \ - "$INFERENCEX_API/benchmarks?model=DeepSeek-V4-Pro" \ - | jq 'first(.[] | select(.benchmark_type == "single_turn" and .isl == 8192 and .osl == 1024)) | {date, model, hardware, framework, precision, isl, osl, tput_per_gpu: .metrics.tput_per_gpu, run_url}' -``` -该示例只返回一条有界的 8k1k 记录。将选中行作为证据前,应添加精确的 hardware、framework、precision 与 date 条件。 - -`model=` 使用链接的 InferenceX-app 模型常量所定义的前端显示名称。固定序列行使用数字 `isl` 和 `osl`;`agentic_traces` 行的长度为空,不要意外过滤掉它们。`view=calculator&sequence=8k/1k` 返回紧凑的插值数据。`date`、`runId`、`exact` 和 `exactRun` 用于限定历史或特定 Run 的查询。发现端点包括 `/availability`、`/workflow-info`、`/evaluations` 和 `/reliability`。 - -始终使用 `--compressed` 并通过 `jq` 过滤。不要输出原始基准测试 JSON,不要绕过缓存,也不要反复轮询 CDN 缓存结果。 - -## 安全检查 - -下列命令对 GitHub 都是只读操作。下载内容进入新建临时目录。只有在列出运行工件后,才替换 ID 和工件名。 - -### 检查运行元数据和工件清单 - -```bash -RUN_ID= -REPO=SemiAnalysisAI/InferenceX - -gh api "repos/$REPO/actions/runs/$RUN_ID" \ - --jq '{id,run_attempt,status,conclusion,event,head_branch,head_sha,html_url}' - -gh api --paginate "repos/$REPO/actions/runs/$RUN_ID/artifacts?per_page=100" \ - --jq '.artifacts[] | [.id,.name,.created_at,.expires_at,.expired,.size_in_bytes] | @tsv' -``` - -如果 ID 不是数字、仓库错误、run attempt 不是目标执行、必需工件已过期,或无法按时间区分多个同名上传,请停止。 - -### 预览 source/merge 工件计划 - -在固定或已审查修订的 InferenceX-app checkout 中运行: - -```bash -SOURCE_RUN_ID= \ -MERGE_RUN_ID= \ -INGEST_REPO=SemiAnalysisAI/InferenceX \ -bun run admin:db:prepare:ci --dry-run -``` - -`--dry-run` 获取元数据并打印选中的工件计划,不下载工件,也不连接数据库。复用时,应确认基准数据来自 source 运行,而 `changelog-metadata` 来自 merge 运行。 - -### 下载并检查聚合架构 - -```bash -tmp="$(mktemp -d "${TMPDIR:-/tmp}/infx-results.XXXXXX")" - -gh run download "$RUN_ID" -R "$REPO" -n results_bmk -D "$tmp/results_bmk" -jq 'type, length' "$tmp/results_bmk/agg_bmk.json" -jq '.[0] | {hw,model,infmax_model_prefix,framework,precision,scenario_type,isl,osl,conc,is_multinode,disagg}' \ - "$tmp/results_bmk/agg_bmk.json" - -# Run this only when eval_results_all appeared in the inventory. -gh run download "$RUN_ID" -R "$REPO" -n eval_results_all -D "$tmp/eval_results_all" -jq 'type, length' "$tmp/eval_results_all/agg_eval_all.json" -jq '.[0] | {model_prefix,model,hw,framework,task,conc,score,score_name,n_eff,source}' \ - "$tmp/eval_results_all/agg_eval_all.json" -``` - -不要假定第零条记录代表正在调查的配置。确认架构后,应按稳定字段过滤: - -```bash -jq --arg model '' \ - '[.[] | select(.infmax_model_prefix == $model or .model_prefix == $model)] | - map({scenario_type,hw,framework,precision,isl,osl,conc,num_requests_total,num_requests_successful,request_accounting})' \ - "$tmp/results_bmk/agg_bmk.json" -``` - -### 检查一个原始 AgentX 同级工件 - -从清单中选择精确的 `agentic_` 名称: - -```bash -AGENTIC_ARTIFACT='agentic_' -gh run download "$RUN_ID" -R "$REPO" -n "$AGENTIC_ARTIFACT" -D "$tmp/agentic" - -jq '{metadata,request_count,error_request_count,completed_request_count}' \ - "$tmp/agentic/results/aiperf_artifacts/profile_export_aiperf.json" - -jq -s '{rows:length, - profiling:map(select((.metadata.benchmark_phase // "profiling") == "profiling"))|length, - warmup:map(select((.metadata.benchmark_phase // "profiling") != "profiling"))|length, - errors:map(select(.error))|length}' \ - "$tmp/agentic/results/aiperf_artifacts/profile_export.jsonl" -``` - -部分历史原始工件使用只含一个子目录的嵌套 AIPerf 目录。如果上面的精确路径不存在,应先停止并检查下载目录名称,再选择文件。不要凭猜测展平、重命名或合并文件。 - -检查完成后,只删除刚刚创建的临时目录: - -```bash -printf 'temporary inspection directory: %s\n' "$tmp" -rm -rf -- "$tmp" -``` - -## GPU 实测功耗 P75 和 P90 - -通过验证的多节点 DCGM 结果还会输出 `p75_total_gpu_power_w`、 -`p75_power_w`、`p90_total_gpu_power_w` 与 `p90_power_w`。两个整组指标使用与能耗 -积分相同的正式基准测试窗口,对参与测量的所有 GPU 板卡功耗之和计算按时间加权的 -第 75 和第 90 百分位数。各设备采样通过分段线性插值按时间对齐后求和,分位数按 -持续时间加权,而不是按采样数量加权。两个按芯片均摊的指标分别将对应的整组 GPU -功耗分位数除以参与测量的 GPU 数量,因此既不是单个 GPU 的分位数,也不是 -各设备分位数的平均值。遥测验证失败时,四项指标都不发布。旧结果需要使用原始 -遥测重新计算;不能从平均功耗推算 P75 或 P90。验证 sidecar 会记录 `power_percentile_method`。 - -## 验证和停止条件 - -只有全部适用检查通过,交接才算验证完成。 - -### 摄取前验证 - -- 明确目标 `github_run_id` 和 `run_attempt`。 -- 预期吞吐量或 AgentX 数据点时,`results_bmk` 包含 JSON 数组。 -- 预期聚合评测时,`eval_results_all` 包含 JSON 数组。需要样本详情时,对应单配置 `eval_*` 文件包仍然存在。 -- 每个预期 AgentX 聚合都有对应的 `agentic_` 原始同级工件。需要服务器派生指标时,服务器日志存在。 -- 固定序列记录具有正数 `isl`、`osl` 和 `conc`。AgentX 记录具有 agentic 场景、正并发、请求计数,以及预期的 offload 和数据集元数据。 -- source/merge dry-run 精确选择预期的 source 测量和 merge 变更日志。 -- 工件过期时间为完整应用工作流留出足够时间,尤其是更长的 AgentX trace 处理路径。 - -### 摄取后验证 - -使用应用工作流日志和数据库 verifier,不能只根据工件存在来判断。确认: - -- `ingest-ci-run` 显示的 source 运行和 source attempt 正确; -- 对于首次摄取或重跑,新增数和重复数合理; -- 已理解跳过计数、未映射实体、缺失数据集和缺失 trace 同级工件; -- 没有发生数据集来源冲突; -- AgentX 数据点已创建 trace-replay 链接,或明确显示链接已存在; -- 应用 overrides 后 `admin:db:verify` 通过; -- 验证之后执行了缓存失效。 - -### 停止条件 - -出现以下任一情况时,停止摄取或恢复调查: - -- source 和 merge ID 或 attempt 有歧义; -- 选中的 source 没有未过期结果工件,或复用时没有未过期的 merge 运行变更日志; -- 聚合 JSON 格式错误、顶层结构错误,或不含预期记录; -- 固定序列数据点缺少身份维度,或 AgentX 聚合报告成功请求数为零; -- AgentX 验证错误率超过配置阈值; -- 无法确定性配对 AgentX 聚合和原始工件后缀; -- 一个工作流运行中出现多个数据集 slug,或缺少必需的数据集来源; -- 意外重复自然键必须依赖输入顺序才能决定最终值; -- 未映射的模型、硬件或精度会使目标记录被丢弃; -- 应用摄取报告数据库错误、缺失必需旁表、override 不匹配或数据库验证失败。 - -不要通过编辑已下载 JSON、更改 ID、抑制跳过或手工插入记录来修复这些情况。应在源头修复生产端、映射、来源或工件选择,再重跑幂等摄取。 diff --git a/inferencex-e2e/docs/testing.md b/inferencex-e2e/docs/testing.md index 4a369e0ec6..a187202df8 100644 --- a/inferencex-e2e/docs/testing.md +++ b/inferencex-e2e/docs/testing.md @@ -1,9 +1,3 @@ -
- -**English** | [中文](testing_zh.md) - -
- # Testing Use the narrowest check that can falsify the change, then widen only when the changed contract crosses more layers. Local checks are fast proof of syntax, schema, generation, and transformation behavior. GPU execution is proof of allocation, serving, workload, and artifact behavior. A smoke run reduces feedback time, but it is not the full-sweep-and-eval evidence required for merge review. @@ -26,7 +20,7 @@ Use the narrowest check that can falsify the change, then widen only when the ch - [`run-sweep.yml`](../../.github/workflows/run-sweep.yml) is the executable PR sweep gate, and [`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) is the push-to-`main` reuse and ingest gate. [`e2e-tests.yml`](../../.github/workflows/e2e-tests.yml) is the manually dispatched end-to-end path. - [`docs/PR_REVIEW_CHECKLIST.md`](PR_REVIEW_CHECKLIST.md) is the merge-review standard. [The verifier prompt](../../.github/codeowner-signoff-verify-prompt.md#check-1--a-passing-sweep--evals-ran-on-a-commit-in-this-pr) states how sweep and eval evidence is independently checked. -These sources outrank this guide when behavior changes. Update the English page first, then translate the same structure and evidence into this page's Chinese counterpart. +These sources outrank this guide when behavior changes. Update this English guide to match them. ## Testing layers diff --git a/inferencex-e2e/docs/testing_zh.md b/inferencex-e2e/docs/testing_zh.md deleted file mode 100644 index a8bdb18ab2..0000000000 --- a/inferencex-e2e/docs/testing_zh.md +++ /dev/null @@ -1,232 +0,0 @@ -
- -[English](testing.md) | **中文** - -
- -# 测试 - -先使用能够证伪本次变更的最小检查,仅当变更契约跨越更多层级时才扩大范围。本地检查可以快速证明语法、模式、生成与转换行为;GPU 执行则证明分配、服务、工作负载和制品行为。冒烟运行可以缩短反馈时间,但不能替代合并评审所要求的全量扫描与评测证据。 - -## 索引 - -- [事实来源](#事实来源) -- [测试层级](#测试层级) -- [测试质量](#测试质量) -- [本地检查](#本地检查) -- [冒烟、扫描与评测](#冒烟扫描与评测) -- [证据标准](#证据标准) -- [评审门禁](#评审门禁) -- [停止条件](#停止条件) - -## 事实来源 - -- [`.github/AGENT_OPERATIONS.md`](../../.github/AGENT_OPERATIONS.md#sweep-labels-and-reuse) 定义扫描标签与修饰标签;其[派发章节](../../.github/AGENT_OPERATIONS.md#workflow-dispatch-and-monitoring)定义手动运行与产物检查。 -- [`.github/workflows/README.md`](../../.github/workflows/README.md) 记录矩阵生成、`e2e-tests.yml`、PR 扫描和复用。 -- [`run-sweep.yml`](../../.github/workflows/run-sweep.yml) 是可执行的 PR 扫描门禁,[`merge-ingest.yml`](../../.github/workflows/merge-ingest.yml) 是推送到 `main` 时的复用与入库门禁;[`e2e-tests.yml`](../../.github/workflows/e2e-tests.yml) 是手动分发的端到端路径。 -- [`docs/PR_REVIEW_CHECKLIST.md`](PR_REVIEW_CHECKLIST.md) 是合并评审标准。[验证器提示词](../../.github/codeowner-signoff-verify-prompt.md#check-1--a-passing-sweep--evals-ran-on-a-commit-in-this-pr) 说明如何独立核验扫描和评测证据。 - -当行为发生变化时,上述来源优先于本指南。先更新英文页面,再把相同结构和证据翻译到本页中文对应版本。 - -## 测试层级 - -[`CI`](../../.github/workflows/ci.yml) 在 PR(包括 fork)或向 `main` 的推送修改 Python 文件、`.github/scripts/` 辅助脚本、`ci.yml`、`pyproject.toml`、`uv.lock`、`.python-version`、Ruff 配置或 `pytest.ini` 时,并行运行 **Lint** 和 **Tests**。[`Workflow security`](../../.github/workflows/zizmor.yml) 在工作流、action 定义、Dependabot、pre-commit 或 zizmor 配置变更时运行 **Zizmor**。仅修改 Python 文件不会触发 Zizmor;仅修改其他工作流不会触发 Lint 或 Tests。修改 `ci.yml` 会触发全部三项任务。两个工作流均可手动分发。仅修改其他文档、Shell 脚本或基准测试 YAML 不会触发这两个工作流;请在本地执行相应检查,或手动分发。 - -Tests 使用四个 pytest worker 运行 `infx/tests/`、`utils/`、`runners/`、`../collectivex/tests/` 和 `../operatorx/tests/` 下的测试,但排除上游 `utils/srt-slurm/` 测试套件。这些目录中的新增测试会自动发现。CI 通过 `uv sync --locked --all-extras --group test --no-editable` 将 `infx` 安装为 wheel,使用 Python 3.12 和仅支持 CPU 的 PyTorch。一项任务失败不会取消另一项;PR 更新会取消旧提交的 CI。尚未创建 PR 的分支推送不再单独触发变更日志测试。 - -| 层级 | 能够证明 | 不能证明 | -| --- | --- | --- | -| 解析与语法 | 编辑后的 YAML 可加载;编辑后的 Bash 可解析 | 模式有效性、运行时路由或 GPU 行为 | -| 模式与矩阵 | 配置键通过验证并发出预期矩阵字段 | 运行器可用性、服务器启动或性能 | -| 聚焦 Python 测试 | 变更后的生成器、changelog、结果、评测、收集或复用契约在覆盖输入上行为正确 | 容器、加速器、网络或 Slurm 行为 | -| 冒烟运行 | 一条严格过滤的路径可完成分配、启动服务器、运行工作负载并产生制品 | 完整并发/搜索空间或合并资格 | -| 手动精简运行 | 每个选中的单节点和多节点部署形态运行其最低并发(`e2e-tests.yml` 设置 `trim-conc: true`;changelog-ref 模式下只精简吞吐行,评测保留选定的并发)。没有任何 PR 标签会精简并发 | 全量扫描所要求的中间并发点 | -| 全量扫描与评测 | 选中的未精简矩阵和评测任务在被评审提交上实际执行 | 未检查证据的正确性或无关配置 | - -较后层级变绿不会弥补较早层级缺少证据。例如,绿色收集器可能只聚合了空集合,因此评审必须检查底层实际执行的任务和制品。 - -## 测试质量 - -强制性的测试规则(禁止的测试类型、保留测试应满足的要求以及四个评审问题)位于 [`AGENTS.md`](../../AGENTS.md#test-quality)。此处另有两点补充: - -- 保留真正的契约:数值结果、无效输入拒绝行为、稳定的产物格式,以及由不同组件独立读取的配置之间的一致性。只断言使用方真正依赖的部分。 -- 在涉及时间的测试中控制时钟和长时间等待,以可观察到的就绪状态进行同步。测试进程终止或产物写入契约时,应保留真实操作,并为等待和清理设置上限,避免回归导致测试进程一直挂起。 - -## 本地检查 - -从 `inferencex-e2e/` 目录运行检查,并用实际变更路径或键替换占位符。 - -### Python 环境 - -[`pyproject.toml`](../pyproject.toml) 定义 `infx` 包及其依赖;[`uv.lock`](../uv.lock) 记录解析后的版本。运行 `uv sync --locked` 安装核心工具,然后用 `uv run --locked python -m infx.matrix.generate ...` 调用现有模块命令。CODEOWNER/GitHub 集成使用 `--extra workflows`,评测摘要和数据库比较使用 `--extra results`。`test` 依赖组包含 CPU 测试所需依赖。 - -开发时 uv 以 editable 模式安装包,源码修改立即生效。CI 安装普通 wheel,但主 pytest 套件导入源码 checkout。独立的安装包测试创建仅含核心或 results 依赖的独立环境,并在源码 checkout 之外运行,检查配方节点数、运行器元数据、矩阵拒绝、包内阈值加载、分数验证、BFCL 许可证归属记录,以及生成的评测结果行与摘要。依赖仓库文件的命令在 editable 安装时使用源码仓库;使用 wheel 时,应从 `inferencex-e2e/` 目录运行。评测 YAML/JSON 资源及 Apache 许可证随包分发。 - -核心依赖使用 `uv add` 添加,集成依赖使用 `uv add --optional `,测试工具使用 `uv add --group test`。同时提交 manifest 和 lockfile。`uv lock --upgrade-package ` 更新指定依赖;解析时按 `pyproject.toml` 执行 12 小时发布冷却期。Ruff 和 Zizmor 不加入 lockfile,CI 继续使用满足冷却期的最新版本。基准测试镜像、供应商评测环境和测量历史 checkout 的命令保留原有依赖安装方式。 - -依赖限制在当前支持的最新主版本内;次版本和补丁更新记录在 `uv.lock` 中,并通过 CI 验证。对尚未达到 1.0 的包,次版本升级也需审查。新版本发布不会自动改变已锁定的环境。 - -结果收集、结果比较和运行统计使用当前 `main` 中的 `infx`,在 sweep setup 时解析一次提交,并在这些 job 间共享。Klaud 同样只解析一次 `main`,将该提交传给所有候选任务;候选任务的 hook 使用独立的工具 checkout,避免配方编辑替换导入的包。Sign-off 也检出当前受信任的 `main`。这些工具不固定到发布版本,仓库提交不受依赖发布冷却期限制。PR CI 测试 PR 自身的包;矩阵生成、基准测试脚本和配方仍使用所选 checkout。Sweep 摘要显示解析后的 setup 和工具提交;复用基准测试时还显示源 head。E2E 基准测试和评测 job 使用与矩阵生成相同的已解析 SHA,即使请求的分支在任务排队时发生移动也不受影响。Klaud 摘要显示作为候选任务基础的工具提交。 - -### Python 静态检查与格式化 - -Ruff 按照 [`infx/ruff.toml`](../infx/ruff.toml) 中的规则检查 `infx/`,目标版本为 Python 3.12,行长度设为 100。任何 Python 文件变更都会触发 CI,使用已发布至少 12 小时的最新 Ruff 版本。 - -```bash -uvx --exclude-newer PT12H ruff@latest check --fix infx -uvx --exclude-newer PT12H ruff@latest format infx -``` - -应尽量修复问题。确有理由保留的例外使用行内 `# noqa: CODE`;多余的忽略标记会被检查。未启用预览规则或自动不安全修复。 - -### GitHub Actions 安全检查 - -CI 使用发布至少 12 小时的最新 zizmor 版本,启用最严格的 `auditor` 模式、严格输入收集、全部受支持的输入类型,以及在线 action 引用检查。所有未豁免的发现都会使任务失败,包括信息级和低置信度发现。使用已认证的 GitHub token 在本地执行同样的检查: - -```bash -GH_TOKEN="$(gh auth token)" uvx --exclude-newer PT12H zizmor@latest \ - --persona auditor --strict-collection --collect all --no-config --no-progress . -``` - -所有第三方 action 仍固定到提交 SHA。同仓库工作流使用 `$/` 引用,解析到工作流的确切提交,要求 Actions runner 版本至少为 2.336.0。Dependabot 在 action 发布七天后才更新。合并后的 Claude 工作流保留审阅和编码两个独立任务,分别设置权限;固定到提交 SHA 的 Claude action 负责安装其支持的 CLI 版本。 - -Auditor 模式也会报告有意保留的架构选择。豁免仅标注在对应的 YAML 行,并附上原因,不会全局禁用规则: - -- 独立的 GPU 分发、评论请求和 Klaud 批次不应互相取消。资源限制由优先级调度器和候选任务归属声明处理。 -- 可信外部分发使用 `pull_request_target`,运行可信控制代码,并在执行特权操作前验证授权。 -- 保留现有仓库级集成凭据。迁移到受保护的 GitHub Environments 必须同步迁移实际存储的 secret;仅添加空的 `environment:` 字段不算修复。 -- Profiling 存储仓库的 checkout 保留其专用 SSH deploy key,因为下一步需要向该独立仓库推送 trace 提交。基准测试 checkout 不保留凭据。 - -添加 `--no-ignores` 可复查全部豁免。新增发现仍必须阻止 CI;若豁免涉及的触发器、checkout、凭据使用方或授权发生变化,必须重新审查。该安全检查不需要运行 GPU 任务。 - -### 解析与语法 - -```bash -python3 -c "import yaml; yaml.safe_load(open('configs/-master.yaml')); yaml.safe_load(open('configs/runners.yaml')); yaml.safe_load(open('perf-changelog.yaml'))" -bash -n benchmarks//