Skip to content

feat(scripts): sanitize FlashInfer level-3 logs into workload JSONL#425

Open
yyihuang wants to merge 2 commits into
flashinfer-ai:mainfrom
yyihuang:feature/log-to-workload-sanitizer
Open

feat(scripts): sanitize FlashInfer level-3 logs into workload JSONL#425
yyihuang wants to merge 2 commits into
flashinfer-ai:mainfrom
yyihuang:feature/log-to-workload-sanitizer

Conversation

@yyihuang

@yyihuang yyihuang commented May 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds scripts/sanitize_fi_log.py and a companion .claude/skills/sanitize-fi-log/ skill for converting FlashInfer level-3 API logs (FLASHINFER_LOGLEVEL=3+) into per-API workload JSONL files.

  • Lightweight alternative to collect-workloads: no tensor dumps, no safetensors blobs — every tensor input becomes {"type": "random"} with shape/dtype derived from the log. Useful for workload distribution capture and template auditing; not for correctness eval.
  • Trace-aware alignment: when paired with FlashInfer trace-dumped definition JSONs (from @flashinfer_api(trace=...) + FLASHINFER_TRACE_DUMP=1), each log call is matched to a definition — workload entries carry the definition name, named inputs, and resolved var axes. Calls with no template (or a mismatched one) fall back to a raw arg_N / kwarg_NAME form with shape/dtype embedded inline.

Matching pipeline

For each log call, candidates are looked up by suffix-match on every fi_api: tag in --trace-dir. Then:

  1. Strict — name match on kwargs.
  2. Strict — unique-shape match (rank, dtype, const-axis consistent; binds vars).
  3. Strict — positional fallback for symmetric-input templates (e.g. fused_add_rmsnorm's two interchangeable [batch, hidden] tensors).
  4. Lenient — name-based with relaxed rank/const checks (skipped under --strict). Catches schema/runtime discrepancies like MLA rank-collapsed K tensors so they still align to their definition.

Validated end-to-end on three real DSR1+SGLang B200 logs (~64K calls each); the skill's triage matrix documents how to read raw entries (template missing / rank mismatch / workspace_buffer aliasing / dim-order flip) and which patterns to grep for in flashinfer/trace/templates/.

Skill

.claude/skills/sanitize-fi-log/SKILL.md covers:

  • When to use this vs collect-workloads / collect-workloads-bench.
  • The matching pipeline and what each pass tolerates.
  • A triage matrix for raw entries under --strict.
  • A worked example on a DSR1 B200 log (36,549/64,673 calls strict-matched after companion FlashInfer template fixes).

Test plan

  • python3 -m py_compile scripts/sanitize_fi_log.py
  • pre-commit run --files scripts/sanitize_fi_log.py .claude/skills/sanitize-fi-log/SKILL.md — black, isort, end-of-files, etc. all pass
  • End-to-end run on synthetic log + 2 trace JSONs (rmsnorm, gqa_ragged): correct definition matching, axes resolved
  • End-to-end run on real DSR1 logs at /home/averyh/fi_log_runs/level3/good/2026-05-01T{1933,1955,2027,2113}/: produces 3–11 JSONL files per log with correct counts

Companion FlashInfer changes (separate repo)

While iterating on this script we found three FlashInfer trace templates whose schemas didn't match runtime calls (MLA k_rope rank-3 vs rank-2, workspace_buffer aliasing num_pages/num_q_tokens, DeepSeek V's head_dim_v modeled as the same const as head_dim_qk). Fixes to those templates land in a separate flashinfer PR; this PR is self-contained and works against any trace dir.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a CLI tool to convert FlashInfer API logs and tensor dumps into structured workload JSONL and per-definition artifacts.
  • Documentation
    • New guidance for log-to-workload sanitization, template alignment, output naming, deduping, and troubleshooting.
    • Expanded workflows and operational notes for workload collection, multi-node benching, streaming collection, and dump-based sanitization.

Convert FlashInfer level-3 API logs (FLASHINFER_LOGLEVEL>=3) into per-API
workload JSONL files, with optional alignment against trace-dumped
definition JSONs from @flashinfer_api(trace=...) + FLASHINFER_TRACE_DUMP=1.

Lighter-weight than the existing collect-workloads (level-10) pipeline:
no tensor dumps, no safetensors blobs — every tensor input is emitted as
{"type": "random"} with shape/dtype derived from the log. Suitable for
workload distribution capture and template auditing; not for correctness
eval.

Matching pipeline (when --trace-dir is supplied):
1. Strict — name match on kwargs.
2. Strict — unique-shape match (rank/dtype/const-axis consistent).
3. Strict — positional fallback for symmetric-input templates.
4. Lenient — name-based with relaxed rank/const checks (skipped under
   --strict). Catches schema/runtime discrepancies like MLA rank-collapsed
   K tensors so they still align to their definition.

Output: <definition_name>.jsonl when matched, <api_name>.jsonl when raw.

The companion .claude/skills/sanitize-fi-log/SKILL.md captures when to
use this vs collect-workloads, the matching pipeline, a triage matrix
for raw entries (template missing / rank mismatch / const aliasing /
dim-order flip), and recurring template bugs to grep for.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

A new CLI tool and several skill documents are added to support converting FlashInfer logs and tensor dumps into per-API JSONL workload entries. The CLI parses level-3+ logs, optionally loads trace definition JSONs, runs a multi-pass matching pipeline (strict → shape → positional → lenient), and writes deduplicated per-key JSONL outputs; docs describe level-3 and level-10 workflows, pairing rules, and troubleshooting.

Changes

Sanitize & Collection Pipeline

Layer / File(s) Summary
Parser / Input Shape
scripts/sanitize_fi_log.py
Parses FlashInfer level-3+ log API call blocks into parameter descriptors: tensors → {type:"random", shape, dtype} or literal repr, non-tensors → scalar/enum/literal.
Trace Loading / Indexing
scripts/sanitize_fi_log.py, --trace-dir JSONs (trace dumps)
Loads trace-dumped definition JSONs, indexes by fi_api: dotted-name suffixes for candidate discovery.
Matching Pipeline (Core)
scripts/sanitize_fi_log.py
Multi-pass matching: strict name + dtype/shape + var-axis binding; greedy unique shape match; positional-order fallback; optional lenient matcher (bindable const axes, tolerate rank mismatches) when not --strict.
Output Construction & Dedupe
scripts/sanitize_fi_log.py
Emit matched workloads (definition name, axes, named inputs) or raw workloads; optional --include-defaults, --dedupe; group by output key and write one .jsonl per key. Prints parse/match/write summary.
Documentation / Usage
.claude/skills/sanitize-fi-log/SKILL.md
New skill doc describing log sanitization, trace alignment options, matching behavior, output JSONL schema, naming conventions, and troubleshooting with a worked example.
Level-10 Dump Sanitization Doc
.claude/skills/sanitize-fi-dumps/SKILL.md
New/expanded doc describing dump→definition mapping, plan()/run() pairing, safetensors policy for structural ints, float→random mapping, kv_indices trimming, dedupe, CLI flags and streaming batch workflow.
Collection Orchestration Docs
.claude/skills/collect-workloads/SKILL.md, .claude/skills/collect-workloads-bench/SKILL.md
Updated docs describing level-3 default (sanitize-fi-log) and opt-in level-10 (sanitize-fi-dumps) flows, multi-node behavior, dump include patterns, SSH / NFS environment guidance, streaming collection (collect_stream.py) behavior, error handling, and PR/verification requirements.

Sequence Diagram

sequenceDiagram
    participant Log as FlashInfer Log
    participant Parser as Log Parser
    participant Loader as Trace Loader
    participant Matcher as Matching Pipeline
    participant Writer as JSONL Writer

    Log->>Parser: Read API Call blocks
    Parser->>Parser: Parse parameters & Tensor blocks
    alt With --trace-dir
        Parser->>Loader: Request candidate definitions by fi_api suffix
        Loader->>Loader: Load and index trace JSONs
        Loader->>Matcher: Provide candidates
        Matcher->>Matcher: Try strict name/shape/axes match
        alt Strict fails
            Matcher->>Matcher: Try greedy unique shape match
            alt Shape fails
                Matcher->>Matcher: Try positional-order fallback
                alt Fallback fails and not --strict
                    Matcher->>Matcher: Apply lenient matcher (bindable axes)
                end
            end
        end
    end
    Matcher->>Writer: Produce matched or raw workload entry
    Writer->>Writer: Optionally dedupe & group by output key
    Writer->>Writer: Write per-key .jsonl files
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Ubospica
  • yzh119
  • yongwww

Poem

🐰 I hopped through logs by moonlit code,
Found API calls on the dusty road,
Matched traces, bound axes tight,
Turned messy dumps to JSON bright,
Now workloads dance in tidy rows — behold! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding a script to sanitize FlashInfer level-3 logs into workload JSONL format.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the sanitize-fi-log skill and a Python script to convert FlashInfer level-3 API logs into per-API workload JSONL files. The script includes logic for parsing log blocks and aligning them with trace definitions. The review feedback highlights several opportunities to improve memory efficiency when processing large log files by adopting a streaming approach for both reading the input and writing the output. There is also a suggestion to remove a redundant helper function to simplify the code.

Comment on lines +154 to +176
def _iter_blocks(lines: list[str]) -> Iterable[tuple[str, list[str]]]:
"""Yield (function_name, block_body_lines) for every API call in the log."""
n = len(lines)
i = 0
while i < n:
m = API_CALL_RE.match(lines[i])
if not m:
i += 1
continue
func_name = m.group(1).strip()
i += 1
body: list[str] = []
while i < n:
ln = lines[i]
if SEPARATOR_RE.match(ln):
i += 1
break
if API_CALL_RE.match(ln):
# Inputs-only block (e.g. crash before output) — start of next call.
break
body.append(ln)
i += 1
yield func_name, body

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation of _iter_blocks requires the entire log file to be loaded into memory as a list of strings. For large FlashInfer logs (which can contain tens of thousands of calls), this can lead to significant memory consumption. Refactoring this function to accept an Iterable[str] (such as a file object) and using a state-machine approach would allow for streaming the log file line by line.

def _iter_blocks(lines: Iterable[str]) -> Iterable[tuple[str, list[str]]]:
    """Yield (function_name, block_body_lines) for every API call in the log."""
    func_name = None
    body = []
    for line in lines:
        m = API_CALL_RE.match(line)
        if m:
            if func_name:
                yield func_name, body
            func_name = m.group(1).strip()
            body = []
        elif func_name:
            if SEPARATOR_RE.match(line):
                yield func_name, body
                func_name = None
                body = []
            else:
                body.append(line)
    if func_name:
        yield func_name, body

Comment on lines +463 to +465
def null_value() -> Any:
# Tiny helper so the JSON output renders ``null`` rather than ``"null"``.
return None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The null_value helper is redundant because json.dumps(None) correctly produces the JSON null literal. Additionally, it is used inconsistently in the script; for example, _build_matched_workload uses None directly. It is recommended to remove this helper and use None everywhere for consistency and simplicity.

Comment on lines +660 to +663
text = args.log_file.read_text()
lines = text.splitlines()

grouped: dict[str, list[dict[str, Any]]] = defaultdict(list)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Reading the entire log file into memory with read_text() and then buffering all workload records in the grouped dictionary can be very memory-intensive for large logs. Consider streaming the log file using with open(...) as f: and writing the output records to their respective files incrementally. This can be achieved by maintaining a dictionary of open file handles for each API/definition encountered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
.claude/skills/sanitize-fi-log/SKILL.md (1)

103-122: 💤 Low value

Minor documentation clarity on pipeline ordering.

The phrase "For each candidate the matcher tries, in order: 1,2,3,4" suggests all four passes are attempted per candidate sequentially. The actual implementation (per _select_match in the script) exhausts strict passes 1-3 on all candidates first, then falls back to lenient pass 4 on all candidates. The end result is the same (strict matches are preferred), but this wording could confuse readers investigating multi-candidate behavior.

Consider rewording to something like:

The matcher first attempts strict alignment (passes 1-3) against each candidate. If no candidate strictly matches, it falls back to lenient alignment (pass 4) against each candidate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/sanitize-fi-log/SKILL.md around lines 103 - 122, Update the
documentation in SKILL.md to clarify that the matcher performs strict alignment
(passes 1–3) across all candidates first and only if no strict match is found
does it run the lenient pass (4) across all candidates; reference the
implementation in _select_match and reword the "For each candidate the matcher
tries, in order:" paragraph to something like "The matcher first attempts strict
alignment (passes 1–3) against each candidate; if no candidate strictly matches,
it falls back to lenient alignment (pass 4) across the candidates."
scripts/sanitize_fi_log.py (2)

452-481: 💤 Low value

Inconsistent null_value() vs None usage.

_build_raw_workload uses null_value() (lines 457-458) while _build_matched_workload uses None directly (lines 478-479). Since json.dumps(None) already renders as null, the helper is unnecessary. Consider using None consistently throughout.

♻️ Suggested fix

Remove the helper and use None directly:

-def null_value() -> Any:
-    # Tiny helper so the JSON output renders ``null`` rather than ``"null"``.
-    return None
-
-
 def _build_raw_workload(func_name: str, log_inputs: dict[str, Any]) -> tuple[str, dict[str, Any]]:
     """Build a raw (unmatched) workload entry keyed by api name."""
     record = {
         "definition": None,
         "workload": {"uuid": str(uuid.uuid4()), "api": func_name, "inputs": log_inputs},
-        "solution": null_value(),
-        "evaluation": null_value(),
+        "solution": None,
+        "evaluation": None,
     }
     return func_name, record
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/sanitize_fi_log.py` around lines 452 - 481, The code mixes a custom
null_value() helper with direct None usage; remove the unnecessary null_value()
function and replace its uses in _build_raw_workload (and anywhere else) with
None so both _build_raw_workload and _build_matched_workload consistently set
"solution" and "evaluation" to None; also delete the null_value() definition to
avoid dead code.

426-429: 💤 Low value

Unused loop variable log_key.

Static analysis correctly identifies that log_key is not used in this loop. Consider using mapping.values() for clarity.

♻️ Suggested fix
-    for log_key, def_name in mapping.items():
+    for def_name in mapping.values():
         named_inputs[def_name] = {"type": "random"}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/sanitize_fi_log.py` around lines 426 - 429, The loop creating
named_inputs uses an unused loop variable log_key; change the iteration to use
mapping values directly so it's clear and avoids the unused variable (e.g.,
iterate over mapping.values() and assign named_inputs[def_name] = {"type":
"random"}). Update the loop around named_inputs, mapping, and def_name in
sanitize_fi_log.py accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.claude/skills/sanitize-fi-log/SKILL.md:
- Around line 103-122: Update the documentation in SKILL.md to clarify that the
matcher performs strict alignment (passes 1–3) across all candidates first and
only if no strict match is found does it run the lenient pass (4) across all
candidates; reference the implementation in _select_match and reword the "For
each candidate the matcher tries, in order:" paragraph to something like "The
matcher first attempts strict alignment (passes 1–3) against each candidate; if
no candidate strictly matches, it falls back to lenient alignment (pass 4)
across the candidates."

In `@scripts/sanitize_fi_log.py`:
- Around line 452-481: The code mixes a custom null_value() helper with direct
None usage; remove the unnecessary null_value() function and replace its uses in
_build_raw_workload (and anywhere else) with None so both _build_raw_workload
and _build_matched_workload consistently set "solution" and "evaluation" to
None; also delete the null_value() definition to avoid dead code.
- Around line 426-429: The loop creating named_inputs uses an unused loop
variable log_key; change the iteration to use mapping values directly so it's
clear and avoids the unused variable (e.g., iterate over mapping.values() and
assign named_inputs[def_name] = {"type": "random"}). Update the loop around
named_inputs, mapping, and def_name in sanitize_fi_log.py accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2a87f07f-f725-4d40-9b19-17468f43d559

📥 Commits

Reviewing files that changed from the base of the PR and between 40e6ca7 and 20a4950.

📒 Files selected for processing (2)
  • .claude/skills/sanitize-fi-log/SKILL.md
  • scripts/sanitize_fi_log.py

…el-10 into sanitize-fi-dumps

The level-3 sanitization path (added in this PR via /sanitize-fi-log) is
lighter, faster, and sufficient for shape-coverage workloads. Make it the
documented default for /collect-workloads and /collect-workloads-bench;
require an explicit opt-in for the level-10 (real-tensor) path.

Changes:

- New skill .claude/skills/sanitize-fi-dumps/SKILL.md: extracts the
  level-10 sanitization details (sanitize_dumps.py invocation, plan/run
  pairing, tensor storage policy, dump-dir env var preparation) out of
  /collect-workloads. /sanitize-fi-dumps and /sanitize-fi-log now mirror
  each other as the two terminal sanitization skills.

- .claude/skills/collect-workloads/SKILL.md: re-frames the workflow as
  two modes — default level 3 + /sanitize-fi-log, opt-in level 10 +
  /sanitize-fi-dumps. Adds a "Two collection modes" comparison table at
  the top so the choice is visible. Sanitization phase delegates to
  /sanitize-fi-dumps. Eval/PR2 phases unchanged.

- .claude/skills/collect-workloads-bench/SKILL.md: same restructuring —
  level-3 flow as the primary, level-10 (multi-node SLURM, model_configs)
  remaining as opt-in. Also adds proper YAML frontmatter (was missing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/collect-workloads-bench/SKILL.md:
- Around line 123-125: The incremental-sanitize examples call sanitize_dumps.py
without limiting appended workloads, so they contradict the text that each pass
should collect 2–3 workloads; update the example command invocations of
sanitize_dumps.py (the examples around the paragraph and the other occurrence at
lines ~171-174) to include the --max-new-workloads flag set to 2 or 3 (e.g.,
--max-new-workloads 3) and briefly note the value matches the “2–3 workloads per
pass” guidance so runs don’t over-append between batch-size iterations.

In @.claude/skills/collect-workloads/SKILL.md:
- Around line 309-313: Update the PR artifact requirement to reference the new
entrypoints: replace the instruction to include stdout from
`collect_workloads.py sglang` with stdout from the current workflow (e.g.,
`collect_stream.py sglang` or the `bench_serving.py` run that drives collection)
under the `## SGLang Collection Log` section; ensure the text explicitly
requires real ShareGPT inference logs that show diverse `(batch_size,
kv_length)` pairs (and call out that uniform tiny KV caches like
`batch_size=4096` with 1-page contexts are synthetic and unacceptable). Locate
and edit the sentence(s) mentioning `collect_workloads.py` and update example
commands and expectations to match `collect_stream.py`/`bench_serving.py` so
contributors run the correct tool and include the correct stdout artifact.

In @.claude/skills/sanitize-fi-dumps/SKILL.md:
- Around line 113-116: The fenced code block that shows the two path lines
containing {flashinfer_trace_dir}/workloads/{op_type}/{def_name}.jsonl and
{flashinfer_trace_dir}/blob/workloads/{op_type}/{def_name}/{def_name}_{uuid}.safetensors
is missing a language tag; update that Markdown fence to include a language
identifier (e.g., change the opening ``` to ```text) so the block reads as a
labeled text code fence for better linting and editor rendering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 72f618aa-8757-4eb7-b60b-a7c4eeedf351

📥 Commits

Reviewing files that changed from the base of the PR and between 20a4950 and 6f1af5b.

📒 Files selected for processing (3)
  • .claude/skills/collect-workloads-bench/SKILL.md
  • .claude/skills/collect-workloads/SKILL.md
  • .claude/skills/sanitize-fi-dumps/SKILL.md

Comment on lines +123 to 125
Run one batch size at a time to avoid node overload. After each run, sanitize
to collect 2–3 workloads, then delete the dump dir before the next run.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Incremental sanitize example is missing --max-new-workloads.

The text says each pass should collect 2–3 workloads, but the example command uses sanitize_dumps.py defaults (20). That mismatch can over-append workloads per batch-size iteration.

Suggested doc patch
   conda run -n flashinfer_bench python scripts/sanitize_dumps.py \
     --dump-dir $DUMP_DIR \
     --definitions <def_name> \
-    --flashinfer-trace-dir $TRACE_DIR
+    --flashinfer-trace-dir $TRACE_DIR \
+    --max-new-workloads 4

Also applies to: 171-174

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/collect-workloads-bench/SKILL.md around lines 123 - 125, The
incremental-sanitize examples call sanitize_dumps.py without limiting appended
workloads, so they contradict the text that each pass should collect 2–3
workloads; update the example command invocations of sanitize_dumps.py (the
examples around the paragraph and the other occurrence at lines ~171-174) to
include the --max-new-workloads flag set to 2 or 3 (e.g., --max-new-workloads 3)
and briefly note the value matches the “2–3 workloads per pass” guidance so runs
don’t over-append between batch-size iterations.

Comment on lines +309 to +313
**PR description must include** the full stdout of `collect_workloads.py sglang`
under `## SGLang Collection Log`. The log must show real ShareGPT inference
with diverse `(batch_size, kv_length)` pairs — uniform tiny KV caches (e.g.
`batch_size=4096` with 1-page contexts) indicate synthetic data, not real
inference.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

PR2 log requirement references the old entrypoint.

This section asks for stdout from collect_workloads.py sglang, but the updated workflow in this same doc is centered on collect_stream.py/bench_serving.py. Please align the required artifact to avoid contributor confusion.

Suggested doc patch
-**PR description must include** the full stdout of `collect_workloads.py sglang`
+**PR description must include** the full stdout/log from the actual collection run
+(`collect_stream.py` or `bench_serving.py`, depending on the path used)
 under `## SGLang Collection Log`.  The log must show real ShareGPT inference
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**PR description must include** the full stdout of `collect_workloads.py sglang`
under `## SGLang Collection Log`. The log must show real ShareGPT inference
with diverse `(batch_size, kv_length)` pairs — uniform tiny KV caches (e.g.
`batch_size=4096` with 1-page contexts) indicate synthetic data, not real
inference.
**PR description must include** the full stdout/log from the actual collection run
(`collect_stream.py` or `bench_serving.py`, depending on the path used)
under `## SGLang Collection Log`. The log must show real ShareGPT inference
with diverse `(batch_size, kv_length)` pairs — uniform tiny KV caches (e.g.
`batch_size=4096` with 1-page contexts) indicate synthetic data, not real
inference.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/collect-workloads/SKILL.md around lines 309 - 313, Update the
PR artifact requirement to reference the new entrypoints: replace the
instruction to include stdout from `collect_workloads.py sglang` with stdout
from the current workflow (e.g., `collect_stream.py sglang` or the
`bench_serving.py` run that drives collection) under the `## SGLang Collection
Log` section; ensure the text explicitly requires real ShareGPT inference logs
that show diverse `(batch_size, kv_length)` pairs (and call out that uniform
tiny KV caches like `batch_size=4096` with 1-page contexts are synthetic and
unacceptable). Locate and edit the sentence(s) mentioning `collect_workloads.py`
and update example commands and expectations to match
`collect_stream.py`/`bench_serving.py` so contributors run the correct tool and
include the correct stdout artifact.

Comment on lines +113 to +116
```
{flashinfer_trace_dir}/workloads/{op_type}/{def_name}.jsonl
{flashinfer_trace_dir}/blob/workloads/{op_type}/{def_name}/{def_name}_{uuid}.safetensors
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language tag to the fenced output-format block.

The code fence at Line 113 is missing a language identifier; this triggers markdown lint and reduces editor rendering quality.

Suggested doc patch
-```
+```text
 {flashinfer_trace_dir}/workloads/{op_type}/{def_name}.jsonl
 {flashinfer_trace_dir}/blob/workloads/{op_type}/{def_name}/{def_name}_{uuid}.safetensors
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 113-113: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @.claude/skills/sanitize-fi-dumps/SKILL.md around lines 113 - 116, The fenced
code block that shows the two path lines containing
{flashinfer_trace_dir}/workloads/{op_type}/{def_name}.jsonl and
{flashinfer_trace_dir}/blob/workloads/{op_type}/{def_name}/{def_name}_{uuid}.safetensors
is missing a language tag; update that Markdown fence to include a language
identifier (e.g., change the opening totext) so the block reads as a
labeled text code fence for better linting and editor rendering.


</details>

<!-- fingerprinting:phantom:triton:hawk:a692d414-f554-49d8-bf26-63f7d7a84560 -->

<!-- d98c2f50 -->

<!-- This is an auto-generated comment by CodeRabbit -->

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants