Skip to content

Commit 0c6f90a

Browse files
committed
Shrink evals.json to nvidia/skills minimal Q&A style
The first version of evals.json caused the validate:content job to time out (1h limit) because Tier 3 ran ~56 minutes on cutile-autotuning's 7 cases × 2 agents × 2 attempts with fixture-based execution, leaving only 4 of 7 skills validated before SIGTERM. Switch to the pattern used by existing skills in NVIDIA/skills (aiq-deploy, aiq-research, cuopt-*): one minimal Q&A case per skill, no fixtures, no executable scripts. Each entry asks the agent to walk through the skill's API/workflow in order without producing runnable code, and is graded on a detailed ground_truth + expected_behavior checklist. Changes: - Remove skills/cutile-autotuning/evals/files/ (18 fixtures, 6 dirs) - Rewrite all 7 skills' evals.json to a single ordered-list Q&A case with 7-8 expected_behavior bullets each - Drop negative cases (none of the existing nvidia/skills evals use should_trigger=false; Tier 3 covers trigger evaluation via the agent_lift dimension) Each evals.json is now ~2KB; the full Tier 3 pass should fit well under the 1h job timeout. Signed-off-by: Hannah Li <hanli@nvidia.com>
1 parent 99b3c0a commit 0c6f90a

25 files changed

Lines changed: 73 additions & 3276 deletions

File tree

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
11
[
22
{
3-
"id": "01-add-rmsnorm-op",
4-
"question": "I want to add a new operator `rms_norm` to TileGym with a cuTile backend. Walk me through the end-to-end steps: registering the dispatch, implementing the cuTile kernel, exporting from `__init__.py`, and writing tests and benchmarks. I want the registration in `src/tilegym/ops/ops.py` and the impl under `src/tilegym/ops/cutile/rms_norm.py`.",
3+
"id": "adding-cutile-kernel-001-end-to-end-steps",
4+
"question": "I want to add a new operator `my_op` to TileGym with a cuTile backend. List the end-to-end steps and the files I need to create or modify, in order. Don't write the full code — just name each step and the file it touches.",
55
"expected_skill": "adding-cutile-kernel",
66
"expected_script": null,
7-
"ground_truth": "Agent follows the 6-step checklist from the adding-cutile-kernel skill: (1) add `@dispatch(\"rms_norm\")` in `src/tilegym/ops/ops.py`; (2) implement the cuTile backend in `src/tilegym/ops/cutile/rms_norm.py` with `@register_impl(\"rms_norm\", backend=\"cutile\")`; (3) export the new module from `src/tilegym/ops/cutile/__init__.py`; (4) add a unit test at `tests/ops/test_rms_norm.py` with a `test_op*` function so the CI `-k test_op` filter discovers it; (5) add a benchmark at `tests/benchmark/bench_rms_norm.py` with `plot_name` ending in `-TFLOPS` or `-GBps`; (6) verify via `pytest tests/ops/test_rms_norm.py -v`.",
7+
"ground_truth": "The agent lists the 6 ordered steps without producing full runnable code. The list, in order: (1) Register dispatch in `src/tilegym/ops/ops.py` via `@dispatch(\"my_op\")` — single entry point for all backends. (2) Implement the cuTile backend in `src/tilegym/ops/cutile/my_op.py` with `@ct.kernel` plus `@register_impl(\"my_op\", backend=\"cutile\")`. (3) Export the new module from `src/tilegym/ops/cutile/__init__.py`. (4) Add unit tests at `tests/ops/test_my_op.py` with test functions named `test_op*` (the CI filter `-k test_op` only collects test functions whose names match `test_op*`; any non-matching test is silently skipped). (5) Add a benchmark at `tests/benchmark/bench_my_op.py` with `plot_name` ending in `-TFLOPS` or `-GBps` (so it's parsed into the CI summary). (6) Verify with `pytest tests/ops/test_my_op.py -v`. The agent uses TodoWrite to track the 6 steps before editing code, executes them in order, and does not silently skip steps.",
88
"expected_behavior": [
9-
"Agent reads the adding-cutile-kernel SKILL.md and copies the 6-step checklist into a TodoWrite list before editing code",
10-
"Agent edits `src/tilegym/ops/ops.py` to add `@dispatch(\"rms_norm\")` declaring the public entry point",
11-
"Agent creates `src/tilegym/ops/cutile/rms_norm.py` containing `@ct.kernel` plus `@register_impl(\"rms_norm\", backend=\"cutile\")`",
12-
"Agent exports the new module from `src/tilegym/ops/cutile/__init__.py`",
13-
"Agent adds a test file `tests/ops/test_rms_norm.py` with test functions named `test_op*` (required by the CI `-k test_op` filter)",
14-
"Agent adds a benchmark file `tests/benchmark/bench_rms_norm.py` with `plot_name` ending in `-TFLOPS` or `-GBps`",
15-
"Agent runs `pytest tests/ops/test_rms_norm.py -v` (or equivalent) to verify"
16-
]
17-
},
18-
{
19-
"id": "02-css-styling-negative",
20-
"question": "How do I center a `<div>` horizontally and vertically using CSS flexbox? The parent is a full-viewport container.",
21-
"expected_skill": null,
22-
"expected_script": null,
23-
"should_trigger": false,
24-
"ground_truth": "Agent provides standard CSS flexbox guidance (`display: flex; justify-content: center; align-items: center;`). The adding-cutile-kernel skill is NOT activated because the question is unrelated to TileGym, cuTile, or GPU kernels.",
25-
"expected_behavior": [
26-
"The adding-cutile-kernel skill is NOT loaded",
27-
"Agent provides standard CSS flexbox guidance",
28-
"Agent does not mention TileGym, cuTile, `@dispatch`, or `@register_impl`",
29-
"Agent does not run destructive commands"
9+
"Lists 6 ordered steps, each pointing to a specific file under `src/tilegym/ops/` or `tests/`",
10+
"Names `@dispatch(\"my_op\")` in `src/tilegym/ops/ops.py` as the single entry point",
11+
"Names `@register_impl(\"my_op\", backend=\"cutile\")` in `src/tilegym/ops/cutile/my_op.py`",
12+
"Mentions that test functions MUST be named `test_op*` to be discovered by the CI `-k test_op` filter",
13+
"Mentions that the benchmark `plot_name` must end with `-TFLOPS` or `-GBps` to appear in the CI summary",
14+
"Mentions using TodoWrite to track the checklist before editing code",
15+
"Does not invent file paths that are not part of TileGym's layout"
3016
]
3117
}
3218
]
Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
11
[
22
{
3-
"id": "01-port-vector-add-julia",
4-
"question": "I have a cuTile Python kernel that does element-wise vector addition with an alpha scaling factor:\n\n```python\n@ct.kernel\ndef vector_add_alpha(x, y, alpha, out, N):\n i = ct.program_id(0)\n start = i * TILE\n idx = start + ct.arange(TILE)\n mask = idx < N\n a = ct.load(x, idx, mask=mask)\n b = ct.load(y, idx, mask=mask)\n ct.store(out, idx, a + alpha * b, mask=mask)\n```\n\nPlease port it to cuTile.jl (Julia) under `julia/kernels/add.jl`, following TileGym's Julia layout. The Julia entry point should accept `(x::CuArray, y::CuArray, alpha::Number)` and return a `CuArray` result.",
3+
"id": "converting-cutile-to-julia-001-conversion-checklist",
4+
"question": "I'm porting a CuTile Python `@ct.kernel` to cuTile.jl (Julia). List the conversion checkpoints I need to handle — name each Python-to-Julia mapping and one-line what changes. Don't write a full runnable kernel.",
55
"expected_skill": "converting-cutile-to-julia",
66
"expected_script": null,
7-
"ground_truth": "Agent creates `julia/kernels/add.jl` containing a `function vector_add_alpha(...)` cuTile.jl kernel plus a host-side `run_vector_add_alpha(x, y, alpha)` bridge function that allocates the output, computes the grid, and launches the kernel. The conversion correctly applies the Python-to-Julia differences: 0-indexed → 1-indexed program_id, `ct.arange` → Julia `range`, row-major → column-major memory layout. The Julia function compiles via `CUDA.jl` + `cuTile.jl` and matches the Python kernel's semantics.",
7+
"ground_truth": "The agent lists the Python-to-Julia conversion checkpoints without producing a full kernel. The list covers: (1) 0-indexed `ct.program_id(0)` → 1-indexed Julia program-id (Julia uses 1-based indexing). (2) `ct.arange` → Julia `range` semantics; mind the inclusive end. (3) Row-major (Python) → column-major (Julia) memory layout — broadcasting and reductions axis change. (4) `np.float32` / `np.float16` → Julia `Float32` / `Float16` type mapping; mention `bfloat16` via `BFloat16s.BFloat16`. (5) `ct.load(ptr, idx, mask=...)` → cuTile.jl `ct.load` with column-major index order. (6) `ct.launch(stream, grid, kernel, args)` Python launch → Julia `cuTile.@launch`-style host call. (7) File location: kernel goes under `julia/kernels/<op>.jl` next to existing ground-truth examples; test goes under `julia/test/test_<op>.jl` and must be registered in `julia/test/runtests.jl`. (8) Mentions that the Julia sub-project is standalone (`Project.toml` under `julia/`); no Python bridge. The agent consults `references/api-mapping.md`, `references/critical-rules.md`, and the existing `julia/kernels/{add.jl, matmul.jl, softmax.jl}` ground-truth files before writing.",
88
"expected_behavior": [
9-
"Agent reads the converting-cutile-to-julia SKILL.md and consults `references/api-mapping.md` for the Python→Julia API mapping",
10-
"Agent inspects `julia/kernels/add.jl` (the ground-truth example) to mirror the established layout / signature pattern",
11-
"Agent creates `julia/kernels/add.jl` with the cuTile.jl kernel and a host-side bridge function",
12-
"Agent correctly translates the 0-indexed `program_id` to Julia's 1-indexed convention",
13-
"Agent uses Julia column-major memory layout where applicable (vs Python's row-major)",
14-
"Agent does not break any existing files under `julia/kernels/` or `julia/test/`",
15-
"The new Julia file uses `cuTile.jl` (not `CUDA.jl` raw kernels) and follows TileGym's `Project.toml` dependency layout"
16-
]
17-
},
18-
{
19-
"id": "02-django-orm-negative",
20-
"question": "I have a Django model `class Order(models.Model)` with a ForeignKey to `User`. How do I query all orders for users whose email ends with `@nvidia.com`, ordered by `created_at` descending?",
21-
"expected_skill": null,
22-
"expected_script": null,
23-
"should_trigger": false,
24-
"ground_truth": "Agent provides a Django ORM query example: `Order.objects.filter(user__email__iendswith='@nvidia.com').order_by('-created_at')`. The converting-cutile-to-julia skill is NOT activated because the question is about Django ORM, not GPU kernels.",
25-
"expected_behavior": [
26-
"The converting-cutile-to-julia skill is NOT loaded",
27-
"Agent provides a Django ORM query answer",
28-
"Agent does not mention cuTile, Julia, `@ct.kernel`, or `cuTile.jl`",
29-
"Agent does not run destructive commands"
9+
"Lists the Python→Julia conversion checkpoints without producing full code",
10+
"Mentions 0-indexed → 1-indexed `program_id` translation",
11+
"Mentions row-major (Python) → column-major (Julia) memory layout difference",
12+
"Names the Python ↔ Julia dtype mapping (np.float32 → Float32, etc.)",
13+
"Mentions that kernels live under `julia/kernels/<op>.jl` and tests under `julia/test/test_<op>.jl`, registered in `runtests.jl`",
14+
"References `references/api-mapping.md` and the ground-truth `julia/kernels/*.jl` examples",
15+
"Does not invent Julia APIs that are not in cuTile.jl"
3016
]
3117
}
3218
]
Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,19 @@
11
[
22
{
3-
"id": "01-convert-matmul-cutile-to-triton",
4-
"question": "Convert the following cuTile matmul kernel (which uses `ct.mma` and `ct.load`/`ct.store` with TMA-style tile loads) to Triton (`@triton.jit`). Place the Triton implementation in `triton_matmul.py` alongside the cuTile original. After conversion, run the relevant tests to confirm correctness on the current GPU.\n\nKey requirements:\n- Use `tl.make_tensor_descriptor` for 2D+ block loads (do NOT use raw `tl.load(ptr+offs, mask=...)` for full tiles — this is the most common source of large performance regressions).\n- Use Triton's bracket launch syntax `kernel[grid](args)` (with normal ASCII brackets in code).\n- If there is a `transpose` flag in the cuTile source, follow the dual-kernel + META-grid pattern.\n- Don't modify the original cuTile kernel.",
3+
"id": "converting-cutile-to-triton-001-conversion-checklist",
4+
"question": "I'm converting a CuTile `@ct.kernel` matmul to Triton (`@triton.jit`). List the conversion checkpoints I need to handle — name each cuTile → Triton mapping and one-line what changes. Don't write a full runnable kernel.",
55
"expected_skill": "converting-cutile-to-triton",
66
"expected_script": null,
7-
"ground_truth": "Agent follows the phase-gated workflow (analyze → convert → validate → test → benchmark) from `translations/workflow.md`. Agent uses `tl.make_tensor_descriptor` for 2D+ tile loads (TMA), maps `ct.mma` to `tl.dot`, uses bracket-launch syntax, and runs `pytest tests/ops/test_matmul.py -k triton -vs` to verify correctness before declaring done. If a `transpose` flag exists, agent emits two kernels with META-grid selection.",
7+
"ground_truth": "The agent follows the phase-gated workflow (analyze → convert → validate → test → benchmark) and lists the conversion checkpoints without a full kernel. The list covers: (1) Pre-flight: count `@ct.kernel` definitions and find `ct.load`/`ct.store`, `ct.launch`, `ct.Constant`, layout flags. (2) `ct.load(ptr, index=(i,j), shape=(M,N))` for 2D+ block-shaped tile loads → MUST use `tl.make_tensor_descriptor` (TMA), NOT raw `tl.load(ptr+offs, mask=...)` — skipping TMA is the most common source of 10-50× regressions. (3) `ct.mma(acc, a, b)` → `tl.dot(a, b, acc)` with explicit accumulator. (4) `ct.Constant[int]` kernel args → Triton `tl.constexpr` parameters. (5) `ct.launch(stream, grid, kernel, args)` → Triton bracket-launch syntax `kernel[grid](args)` (ASCII brackets in code). (6) Layout flags (`transpose=True/False`) → dual-kernel + META-grid pattern in `translations/advanced-patterns.md`, NOT one kernel + `tl.trans`. (7) For attention / FMHA / Gemma / GQA / soft-cap / sliding-window kernels: read `references/optimization-strategy.md` §4 and apply the Gemma FMHA checklist before treating conversion as optimized. (8) Validate with `pytest tests/ops/test_<op>.py -k triton -vs` before benchmarking. The agent does NOT modify the original cuTile kernel.",
88
"expected_behavior": [
9-
"Agent reads the converting-cutile-to-triton SKILL.md and the `references/api-mapping.md`",
10-
"Agent runs the Pre-flight Analysis grep commands on the cuTile source (count `@ct.kernel`, find `ct.load`/`ct.store`, layout flags)",
11-
"Agent uses `tl.make_tensor_descriptor` for 2D+ block-shaped tile loads (TMA), not raw pointer+mask loads",
12-
"Agent uses Triton's bracket launch syntax `kernel[grid](args)` with normal ASCII brackets",
13-
"Agent handles layout flags (e.g. `transpose=True/False`) via the dual-kernel + META-grid pattern documented in `translations/advanced-patterns.md` (if present in source)",
14-
"Agent does NOT modify the original cuTile kernel file",
15-
"Agent runs `pytest tests/ops/test_*.py -k triton -vs` (or equivalent) to validate before declaring done",
16-
"If benchmarking shows 10-50× slowdown, agent reads the CRITICAL PERFORMANCE PATTERNS section before declaring done"
17-
]
18-
},
19-
{
20-
"id": "02-react-hooks-negative",
21-
"question": "What is the difference between `useEffect` and `useLayoutEffect` in React? When would I use one over the other?",
22-
"expected_skill": null,
23-
"expected_script": null,
24-
"should_trigger": false,
25-
"ground_truth": "Agent explains that `useEffect` runs asynchronously after the browser paints, while `useLayoutEffect` runs synchronously before paint. Use `useLayoutEffect` only when you need to read layout from the DOM and synchronously re-render (e.g., measuring tooltip positioning). The converting-cutile-to-triton skill is NOT activated.",
26-
"expected_behavior": [
27-
"The converting-cutile-to-triton skill is NOT loaded",
28-
"Agent explains the React `useEffect` vs `useLayoutEffect` distinction",
29-
"Agent does not mention cuTile, Triton, `@ct.kernel`, or `@triton.jit`",
30-
"Agent does not run destructive commands"
9+
"Lists the conversion checkpoints in order following analyze → convert → validate → test → benchmark",
10+
"Names `tl.make_tensor_descriptor` (TMA) for 2D+ block-shaped tile loads — NOT raw `tl.load` with masks",
11+
"Maps `ct.mma` → `tl.dot` with explicit accumulator argument",
12+
"Maps `ct.Constant[int]` → `tl.constexpr` for kernel parameters",
13+
"Names Triton's bracket-launch syntax `kernel[grid](args)` with ASCII brackets",
14+
"Mentions the dual-kernel + META-grid pattern for `transpose` layout flags (per advanced-patterns.md)",
15+
"Does NOT modify the original cuTile kernel source",
16+
"Validates via `pytest tests/ops/test_<op>.py -k triton -vs` before benchmarking"
3117
]
3218
}
3319
]

0 commit comments

Comments
 (0)