wl-benchmark 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wl_benchmark-0.4.0/PKG-INFO +244 -0
- wl_benchmark-0.4.0/README.md +222 -0
- wl_benchmark-0.4.0/pyproject.toml +37 -0
- wl_benchmark-0.4.0/setup.cfg +4 -0
- wl_benchmark-0.4.0/wl_benchmark/__init__.py +0 -0
- wl_benchmark-0.4.0/wl_benchmark/__main__.py +3 -0
- wl_benchmark-0.4.0/wl_benchmark/cli.py +250 -0
- wl_benchmark-0.4.0/wl_benchmark/client.py +166 -0
- wl_benchmark-0.4.0/wl_benchmark/publisher.py +113 -0
- wl_benchmark-0.4.0/wl_benchmark/reporter.py +61 -0
- wl_benchmark-0.4.0/wl_benchmark/review_pdf.py +297 -0
- wl_benchmark-0.4.0/wl_benchmark/runner.py +87 -0
- wl_benchmark-0.4.0/wl_benchmark/site.py +275 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks/__init__.py +46 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks/base.py +70 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks/essay.py +226 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks/quant.py +259 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks/scheduling.py +475 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks/svg.py +255 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/01-storytelling/rubric.md +69 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/01-storytelling/rubric.png +0 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/01-storytelling/spec.json +47 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/01-storytelling/task.md +12 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/02-argument/rubric.md +69 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/02-argument/rubric.png +0 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/02-argument/spec.json +64 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/02-argument/task.md +10 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/03-proposal/rubric.md +70 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/03-proposal/rubric.png +0 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/03-proposal/spec.json +78 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/essay/03-proposal/task.md +11 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/quant/fe-mining-01.json +1143 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/scheduling/term-plan-2627t1.json +743 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/svg/stage1-riding.json +24 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/svg/stage2-relation.json +13 -0
- wl_benchmark-0.4.0/wl_benchmark/tasks_data/svg/stage3-architecture.json +16 -0
- wl_benchmark-0.4.0/wl_benchmark.egg-info/PKG-INFO +244 -0
- wl_benchmark-0.4.0/wl_benchmark.egg-info/SOURCES.txt +39 -0
- wl_benchmark-0.4.0/wl_benchmark.egg-info/dependency_links.txt +1 -0
- wl_benchmark-0.4.0/wl_benchmark.egg-info/entry_points.txt +2 -0
- wl_benchmark-0.4.0/wl_benchmark.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wl-benchmark
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: WL-Benchmark: the AI benchmark of CUHK Shenzhen — tool use, RUBRIC essays, scheduling, SVG
|
|
5
|
+
Author: WL
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: llm,benchmark,evaluation,function-calling,agents
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# WL-Benchmark
|
|
24
|
+
|
|
25
|
+
**The New AI Benchmark for General Tasks.**
|
|
26
|
+
|
|
27
|
+
A benchmark for CUHK Shenzhen with its unique context and background information, packaged as a self-contained CLI tool (`wlb`). However, it's not exclusive for a single university, since it could somehow tell the real ability of a model, regardless the background information (university).
|
|
28
|
+
|
|
29
|
+
This benchmark cares about general agent tasks, not only coding capability. It will not evaluate the output, leaving the right to human.
|
|
30
|
+
|
|
31
|
+
## What makes a good benchmark (for us)?
|
|
32
|
+
|
|
33
|
+
A Benchmark shouldn't be easily obtained by AI manufacturers or service providers. In other words, AI companies don't have to specifically pre-train with our tests. Hence, our tests should not be general to cover every user nor every field. We only care about where we, as LGUers, will use AI to solve problems.
|
|
34
|
+
|
|
35
|
+
Meanwhile, the test problems are narrowed down to the CUHKSZ context, which means every problem is made of CUHKSZ. This does not actually prevent pre-train cheats. It would be even better if they could have a domain-specific pre-train towards CUHKSZ.
|
|
36
|
+
|
|
37
|
+
As a benchmark in a "NewAPI/Sub2API/CliProxyAPI" era, we do not put too much weight on API testers like hvoy, since such providers may have special techniques to game potential problems. But we keep the possibility of using them as a reference.
|
|
38
|
+
|
|
39
|
+
## How scoring works
|
|
40
|
+
|
|
41
|
+
- **Programmatic scoring** (no model judge): tool use (count of correct operations) and scheduling (constraint solving).
|
|
42
|
+
- **Human review**: essays (graded against the RUBIC) and SVG drawings (graded from the rendered PNG). The harness only generates the artifacts and saves them; a human opens them and scores.
|
|
43
|
+
|
|
44
|
+
## Benchmark domains
|
|
45
|
+
|
|
46
|
+
### Scheduling Problems
|
|
47
|
+
|
|
48
|
+
The AI plays a Financial Engineering (Quantitative Finance stream) student planning the **2026-27 Term 1 registration**. It receives:
|
|
49
|
+
|
|
50
|
+
1. a condensed **study scheme** (major requirements, university core, GE structure and rules, CEC rule, registration rules) — grounded in the official study scheme circular and the Registry pages 选课和改选 (/page/24: term load 9-18 units) and 通识教育 (/page/21: GE = foundations GFH+GFN + one course from each area A/B/C/D; GEW does not count toward the GE core),
|
|
51
|
+
2. the **transcript through 2025-26 Term 2** (extracted from the official unofficial transcript; the 2026-27 in-progress rows are ignored — Term 1 has not been selected yet),
|
|
52
|
+
3. the **course offering list** for 2026-27 Term 1 with fully randomized session times (15-min grid starts, mixed durations). Every offered section pairs one Lecture with one Tutorial session (2-3 sessions, optionally a Lab).
|
|
53
|
+
|
|
54
|
+
This task also carries the **tool use and function calling** dimension: the four research tools are unlabeled (opaque names, no descriptions, terse parameter names — the model must infer what each does and how to use it, the same treatment once planned for a standalone tool-use domain), and the plan must be submitted through the documented `enroll` tool.
|
|
55
|
+
|
|
56
|
+
The raw materials are NOT given in the prompt. The model must gather every fact itself through four pseudo tools — `search_registry` (rule documents), `query_transcript`, `query_prerequisite`, `search_course_offering` — and the search corpus contains noise: the OLD GE rule version (2017-22 admits: "GEW counts toward the GE core") next to the current one, the FinTech-stream study scheme next to the Quantitative Finance one, and the offering search hides the not-offered courses behind explicit "not offered" responses.
|
|
57
|
+
|
|
58
|
+
After researching, the AI must audit its own remaining requirements and submit the plan through the only documented tool, `enroll` (batch or one call per course) — the opaque research tools stay undescribed, but the answer channel is explicit. The enroll tool accepts any well-formed submission blindly (no conflict/prereq validation feedback — otherwise a model could brute-force the unique solution through the SIS). A text-JSON fallback exists for models that never call `enroll`. The plan:
|
|
59
|
+
|
|
60
|
+
- retake the two withdrawn (W) courses — ECO3121 and MAT3007;
|
|
61
|
+
|
|
62
|
+
- retake the two withdrawn (W) courses — ECO3121 and MAT3007;
|
|
63
|
+
- take every offered major-required course whose prerequisites are completed — and exclude the **prerequisite trap** FIN4120 (its prereq FIN3080 is only in progress);
|
|
64
|
+
- complete the last GE foundation course **GFH1000** (与人文对话);
|
|
65
|
+
- take the remaining CEC course **CEC4000** (GEW-type: it does not count toward the GE core or the 2-GE-per-term limit);
|
|
66
|
+
- add exactly one GE-area course (area B/C/D still remaining — decoy area courses conflict with everything);
|
|
67
|
+
- fit the **full 18-unit load** with zero time conflicts.
|
|
68
|
+
|
|
69
|
+
The instance is constructed plant-then-noise with a fixed seed: the unique solution is planted first (pairwise non-overlapping sessions), then noise sections are added that deliberately overlap planted sessions — so **exactly one valid plan exists** (verified by a solver at generation time). Two more binding constraints raise the difficulty: the timetable must leave **Friday completely free** (a same-feasibility decoy area course sits entirely on Friday — dropping this rule yields 3 valid plans instead of 1, verified at generation time), and the GE-area course must be chosen under that rule. Scores are computed programmatically as ten weighted rule checks: required coverage (0.15), prerequisite-trap avoidance (0.10), no unknown/extra courses (0.10), GE foundation (0.10), CEC4000 (0.15), GE-area course (0.10), GE per-term limit (0.05), zero conflicts (0.10), exact 18-unit load (0.10), Friday-free timetable (0.05).
|
|
70
|
+
|
|
71
|
+
### Quantitative Research Practice (multi-factor mining, inference, out-of-sample test)
|
|
72
|
+
|
|
73
|
+
A math-heavy **agentic research task**, scored 80% programmatically + 20% by human review of the written note. No data is given in the prompt: the model must discover the data universe through two opaque tools (`meta_list`, `series_fetch`) — the universe contains 10 series including a revised-index decoy (SZTECH_V2), a BTC distraction, and a five-candidate factor library (MOM / VAL / SIZE / VOL / LIQ) where three factors are pure noise.
|
|
74
|
+
|
|
75
|
+
The true driver of SZTECH (estimation window 2024, 12 observations) is the market plus **exactly two** library factors (MOM + VAL) — verified at generation time (t(MOM) = 15.2, t(VAL) = 6.1, every noise factor |t| < 1.5 when appended to the true model, corr(MOM, VAL) = 0.10, seeded by rejection sampling). The model must:
|
|
76
|
+
|
|
77
|
+
- slice the 2024 window out of the 24-month histories (the fetch returns everything — window-slicing noise);
|
|
78
|
+
- mine the factor library as a **subset-selection** problem: screen candidates, keep the two real factors, exclude decoys;
|
|
79
|
+
- estimate the four-unknown OLS **by hand** (const + MKT + MOM + VAL — 4x4 normal equations) for alpha, the three betas and R-squared;
|
|
80
|
+
- compute the **t-statistics of both factor betas** — this requires the (X'X)^-1 diagonal and the residual variance, i.e. formal inference, not just point estimates;
|
|
81
|
+
- compute the annualized Sharpe (RF series), sample standard deviation, maximum drawdown, and the 3-worst-observation expected shortfall;
|
|
82
|
+
- pass the **out-of-sample test**: apply the 2024 coefficients to each 2025 month (the second year of history is no longer dead weight) and report the RMSE of the prediction errors;
|
|
83
|
+
- write a 200-450-word research note (mining method, identification evidence, out-of-sample performance, limitation) — human-reviewed.
|
|
84
|
+
|
|
85
|
+
Numeric answers are checked with per-question tolerances against an answer key computed programmatically (4x4 normal equations, matrix inverse, compounding, drawdown); percent/decimal-fraction scale confusion is tolerated. Final score = 80% x auto + 20% x note. A wrong factor subset (missing one true factor or keeping a decoy) immediately drops 12 points of auto weight, and the beta/t-stat answers become unanswerable correctly — factor identification is the gate.
|
|
86
|
+
|
|
87
|
+
### SVG Drawing
|
|
88
|
+
|
|
89
|
+
All three stages carry **machine-checked structural constraints** on the SVG reply: root `<svg>` with BOTH viewBox and explicit width/height, minimum labeled-text counts (5 / 6 / 8 per stage), font-size >= 14 everywhere, explicit arrowheads (marker or triangle) for relation/architecture stages, the picked subjects must appear as labels, and a legend/caption box must exist. Results are printed as a PASS/FAIL table in the review PDF (suggested -5 per violation, reviewer confirms). The prompts additionally demand scene composition requirements per stage (environmental props with labels + caption for riding; >= 3 intermediate dated hops for relation; >= 8 components + legend + grouping boundary for architecture).
|
|
90
|
+
|
|
91
|
+
#### Stage One
|
|
92
|
+
|
|
93
|
+
We have a bunch of nouns A and B. For Set A, there are some words referring to an animal/person, e.g. Xu Yangsheng (President) or Qin Shi Huang. For Set B, there are some words referring to a physical and biological non-animal, e.g. iPhone or Teaching Building.
|
|
94
|
+
|
|
95
|
+
The benchmark randomly selects one word from A and one word from B, and asks the model to draw an SVG of A riding B, e.g. President Xu riding GPA.
|
|
96
|
+
|
|
97
|
+
Set A includes: Xu Yangsheng (President), The First Emperor of Qin (Qin Shi Huang), Confucius, Qu Yuan (屈原), Zheng He (郑和), Zhang Heng (张衡)
|
|
98
|
+
|
|
99
|
+
Set B includes: iPhone, Fridge, Rocket, Wi-Fi, GPA, Bicycle, Cybertruck, Drone, WeChat
|
|
100
|
+
|
|
101
|
+
The benchmark does this once and moves on.
|
|
102
|
+
|
|
103
|
+
#### Stage Two
|
|
104
|
+
|
|
105
|
+
The benchmark selects two random persons in A, and lets the AI draw a COMPLETE illustration of how these two persons are indirectly related.
|
|
106
|
+
|
|
107
|
+
The AI is asked once. The output is still an SVG file.
|
|
108
|
+
|
|
109
|
+
#### Stage Three
|
|
110
|
+
|
|
111
|
+
The benchmark selects a random item in B, and lets the AI draw an architecture diagram.
|
|
112
|
+
|
|
113
|
+
The AI is asked once. The output is still an SVG file.
|
|
114
|
+
|
|
115
|
+
### Essay Writing with RUBRIC
|
|
116
|
+
|
|
117
|
+
RUBICs for the three writing tests are adapted from the school-provided RUBIC1.docx (same dimensions, weights, level bands and deduction rules); the original sheet is kept at `wl_benchmark/tasks_data/essay/_source/RUBIC1.docx`. The rubric is provided to the model as a photo (multimodal) by default; text/PDF modes are switchable.
|
|
118
|
+
|
|
119
|
+
Every writing task now carries **machine-checked hard constraints** on top of the rubric quality dimensions: language-section headings, English word-range and Chinese character-range windows, required scene/section headings, typed evidence tags, boundary conditions, method-rigor keywords. The harness verifies each constraint programmatically and the result table is printed in the review PDF (suggested -5 per violated constraint, reviewer confirms).
|
|
120
|
+
|
|
121
|
+
#### Story Telling
|
|
122
|
+
|
|
123
|
+
The benchmark asks the AI to write a story about Qin Shi Huang riding a Polar Bear and looking at his phone — in **exactly three scenes** (parallel `### Scene N —` / `### 场景 N —` headings), where the phone must create the conflict once and resolve it once, and every modern object needs an in-world explanation.
|
|
124
|
+
|
|
125
|
+
The output should be in markdown format, in both English and Chinese (中英双语): English 800-1200 words, Chinese 1200-2000 characters.
|
|
126
|
+
|
|
127
|
+
#### Argument Writing
|
|
128
|
+
|
|
129
|
+
The benchmark asks the AI to write an argument essay about why we could use smartphones while walking inside the campus.
|
|
130
|
+
|
|
131
|
+
The AI must provide **at least four typed evidences** (`**[Statistic]**`, `**[Campus observation]**`, `**[Analogy]**`, `**[Authority]**`, `**[Counterfactual]**` — at least three distinct types), a rebuttal of "走路不看手机" that states the strongest opposing version **and concedes one point** before refuting, and a boundary-conditions paragraph naming where the position does NOT hold.
|
|
132
|
+
|
|
133
|
+
The output should be in markdown format, in both English and Chinese (中英双语): English 900-1300 words, Chinese 1400-2200 characters.
|
|
134
|
+
|
|
135
|
+
#### Research Proposal Writing
|
|
136
|
+
|
|
137
|
+
The benchmark transfers the results of the previous two writings as context, and asks the AI to design research towards the topic: whether we could use smartphones while walking inside the campus.
|
|
138
|
+
|
|
139
|
+
The proposal must carry full method rigor: sampling frame and target N, operationalized IV/DV, instrument, identification strategy, a pre-registered falsifiable **H1**, at least three expected outcomes each paired with its refuting observation, the story cited as motivation plus at least two Task-2 claims converted into hypotheses tagged `[from Task 2]`, and two validity threats with mitigations.
|
|
140
|
+
|
|
141
|
+
The output should be in markdown format, in both English and Chinese (中英双语): English 1100-1600 words, Chinese 1700-2600 characters.
|
|
142
|
+
|
|
143
|
+
## Usage
|
|
144
|
+
|
|
145
|
+
The tool is self-contained (Python standard library only, no third-party dependencies). It is a pure instrument: **no provider presets are stored** — every run interactively asks for the target under test.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Connectivity check: asks for endpoint/key/model, verifies and exits
|
|
149
|
+
./wlb doctor
|
|
150
|
+
|
|
151
|
+
# List the discovered tasks
|
|
152
|
+
./wlb list-tasks
|
|
153
|
+
|
|
154
|
+
# Run the full suite: asks for endpoint -> API key (hidden) -> model
|
|
155
|
+
# (after key input it fetches the endpoint's model list, so you can pick by number)
|
|
156
|
+
# By default every finished run is uploaded to the benchmark platform
|
|
157
|
+
# (share link printed, local run data then deleted)
|
|
158
|
+
./wlb run
|
|
159
|
+
|
|
160
|
+
# Non-interactive (script-friendly), optionally restricted to some domains
|
|
161
|
+
./wlb run --endpoint https://api.example.com/v1 --key sk-xxx --model model-a \
|
|
162
|
+
--tasks essay,svg
|
|
163
|
+
|
|
164
|
+
# Keep the local run data instead of deleting it after upload
|
|
165
|
+
./wlb run --keep
|
|
166
|
+
|
|
167
|
+
# Skip the platform entirely (results stay local)
|
|
168
|
+
./wlb run --no-upload
|
|
169
|
+
|
|
170
|
+
# Re-upload a run whose upload failed (kept locally in that case)
|
|
171
|
+
./wlb publish results/<timestamp>
|
|
172
|
+
|
|
173
|
+
# Rebuild the summary of a finished run
|
|
174
|
+
./wlb report results/<timestamp>/
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Install as a global command: `pip install .` (provides `wlb`), or symlink `ln -sf $(pwd)/wlb /usr/local/bin/wlb`.
|
|
178
|
+
|
|
179
|
+
### Run output
|
|
180
|
+
|
|
181
|
+
Everything lands in `results/<timestamp>/`:
|
|
182
|
+
|
|
183
|
+
| File | Purpose |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `review.pdf` | **one consolidated human-review PDF**: summary table + every task's full output (essays, rendered SVGs, scheduling details), each scored section has a blank scoring box |
|
|
186
|
+
| `results.json` | structured results of all tasks (incrementally dumped — a crashed run keeps its data) |
|
|
187
|
+
| `summary.md` | overview table: programmatic scores; essay/svg marked "pending human review" with artifact paths |
|
|
188
|
+
| `artifacts/` | individual artifacts: essays `*.md`, drawings `*.svg` + `*.png` |
|
|
189
|
+
| `config.snapshot.json` | run-configuration snapshot (key masked) |
|
|
190
|
+
|
|
191
|
+
`review.pdf` is generated automatically at the end of every run; `./wlb report results/<timestamp>/` regenerates both files anytime.
|
|
192
|
+
|
|
193
|
+
### Human review flow
|
|
194
|
+
|
|
195
|
+
1. Open `results/<timestamp>/review.pdf` — everything is in there: the summary table, each essay with its RUBRIC, each rendered SVG, each scheduling detail, and a blank scoring box per task.
|
|
196
|
+
2. Grade each scored section against the RUBIC (Intellectual Content 25 / Organization 25 / Language Use 50, A–F bands, deductions), fill in the boxes.
|
|
197
|
+
3. If you prefer raw files, the individual artifacts stay in `artifacts/` (`*.md` essays, `*.svg`/`*.png` drawings).
|
|
198
|
+
|
|
199
|
+
### Benchmark platform (default upload + share links)
|
|
200
|
+
|
|
201
|
+
Every run is published to your own **WL-Benchmark platform** — a one-time-deployed
|
|
202
|
+
Cloudflare Worker (`site/`, KV storage, no build step). The flow:
|
|
203
|
+
|
|
204
|
+
1. `wlb run` finishes → builds one self-contained page for the run (images inlined);
|
|
205
|
+
2. `POST <site>/api/runs` uploads it (Bearer token);
|
|
206
|
+
3. the share link `https://benchmark.wulei.org/r/<run-id>` is printed — send it to anyone;
|
|
207
|
+
4. the local run directory is **deleted** (the platform is the single source of truth).
|
|
208
|
+
|
|
209
|
+
The platform accumulates all runs at `/` (index) with `/r/<id>` detail pages.
|
|
210
|
+
Setup: deploy `site/` once (see `site/README.md`), then either set
|
|
211
|
+
`WL_BENCH_URL` + `WL_BENCH_TOKEN` or answer the interactive prompt on the first
|
|
212
|
+
run (saved to `config/site.json`, gitignored).
|
|
213
|
+
|
|
214
|
+
### Run parameters
|
|
215
|
+
|
|
216
|
+
Optional file `config/bench.json` (see `config/bench.example.json`) may override: `rubric_modality` (`auto|image|doc|text`), `max_tokens`, `essay_max_tokens`, `svg_max_tokens`, `scheduling_max_tokens`, `temperature`, `timeout`, `tasks_data_root`. Provider information is never stored there.
|
|
217
|
+
|
|
218
|
+
## Task data layout
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
wl_benchmark/tasks_data/
|
|
222
|
+
├── essay/
|
|
223
|
+
│ ├── 01-storytelling/ task.md + rubric.png|md + spec.json (constraints)
|
|
224
|
+
│ ├── 02-argument/ task.md + rubric.png|md + spec.json (constraints)
|
|
225
|
+
│ ├── 03-proposal/ task.md + rubric.png|md + spec.json (context_from + constraints)
|
|
226
|
+
│ └── _source/ RUBIC1.docx (school original) + generated sheets
|
|
227
|
+
├── quant/ # fe-mining-01.json (generated by tools/gen_quant.py)
|
|
228
|
+
├── svg/ # stage1-riding / stage2-relation / stage3-architecture
|
|
229
|
+
└── scheduling/term-plan-2627t1.json # generated by tools/gen_scheduling.py
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Directory numeric prefixes define execution order (chained tasks read the outputs of earlier ones).
|
|
233
|
+
|
|
234
|
+
## Adding new tasks
|
|
235
|
+
|
|
236
|
+
- New tool scenario: drop a JSON into `tool_use/named/` or `tool_use/unlabeled/`
|
|
237
|
+
- New scheduling instance: `python3 tools/gen_scheduling.py --seed <n>`
|
|
238
|
+
- New essay task: create `essay/<NN-name>/` with `task.md` + `rubric.*`; add `spec.json` with `context_from` for chained tasks
|
|
239
|
+
- New SVG task: add a JSON under `svg/`, choosing the `stage` mode
|
|
240
|
+
|
|
241
|
+
## Roadmap
|
|
242
|
+
|
|
243
|
+
- [ ] Human Evaluation (A/B test system): after a model passes the automated tests, route it to a real-environment A/B system and collect user feedback with tools that cannot affect important messages. (not finished yet)
|
|
244
|
+
- [ ] Publish to PyPI / Homebrew.
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# WL-Benchmark
|
|
2
|
+
|
|
3
|
+
**The New AI Benchmark for General Tasks.**
|
|
4
|
+
|
|
5
|
+
A benchmark for CUHK Shenzhen with its unique context and background information, packaged as a self-contained CLI tool (`wlb`). However, it's not exclusive for a single university, since it could somehow tell the real ability of a model, regardless the background information (university).
|
|
6
|
+
|
|
7
|
+
This benchmark cares about general agent tasks, not only coding capability. It will not evaluate the output, leaving the right to human.
|
|
8
|
+
|
|
9
|
+
## What makes a good benchmark (for us)?
|
|
10
|
+
|
|
11
|
+
A Benchmark shouldn't be easily obtained by AI manufacturers or service providers. In other words, AI companies don't have to specifically pre-train with our tests. Hence, our tests should not be general to cover every user nor every field. We only care about where we, as LGUers, will use AI to solve problems.
|
|
12
|
+
|
|
13
|
+
Meanwhile, the test problems are narrowed down to the CUHKSZ context, which means every problem is made of CUHKSZ. This does not actually prevent pre-train cheats. It would be even better if they could have a domain-specific pre-train towards CUHKSZ.
|
|
14
|
+
|
|
15
|
+
As a benchmark in a "NewAPI/Sub2API/CliProxyAPI" era, we do not put too much weight on API testers like hvoy, since such providers may have special techniques to game potential problems. But we keep the possibility of using them as a reference.
|
|
16
|
+
|
|
17
|
+
## How scoring works
|
|
18
|
+
|
|
19
|
+
- **Programmatic scoring** (no model judge): tool use (count of correct operations) and scheduling (constraint solving).
|
|
20
|
+
- **Human review**: essays (graded against the RUBIC) and SVG drawings (graded from the rendered PNG). The harness only generates the artifacts and saves them; a human opens them and scores.
|
|
21
|
+
|
|
22
|
+
## Benchmark domains
|
|
23
|
+
|
|
24
|
+
### Scheduling Problems
|
|
25
|
+
|
|
26
|
+
The AI plays a Financial Engineering (Quantitative Finance stream) student planning the **2026-27 Term 1 registration**. It receives:
|
|
27
|
+
|
|
28
|
+
1. a condensed **study scheme** (major requirements, university core, GE structure and rules, CEC rule, registration rules) — grounded in the official study scheme circular and the Registry pages 选课和改选 (/page/24: term load 9-18 units) and 通识教育 (/page/21: GE = foundations GFH+GFN + one course from each area A/B/C/D; GEW does not count toward the GE core),
|
|
29
|
+
2. the **transcript through 2025-26 Term 2** (extracted from the official unofficial transcript; the 2026-27 in-progress rows are ignored — Term 1 has not been selected yet),
|
|
30
|
+
3. the **course offering list** for 2026-27 Term 1 with fully randomized session times (15-min grid starts, mixed durations). Every offered section pairs one Lecture with one Tutorial session (2-3 sessions, optionally a Lab).
|
|
31
|
+
|
|
32
|
+
This task also carries the **tool use and function calling** dimension: the four research tools are unlabeled (opaque names, no descriptions, terse parameter names — the model must infer what each does and how to use it, the same treatment once planned for a standalone tool-use domain), and the plan must be submitted through the documented `enroll` tool.
|
|
33
|
+
|
|
34
|
+
The raw materials are NOT given in the prompt. The model must gather every fact itself through four pseudo tools — `search_registry` (rule documents), `query_transcript`, `query_prerequisite`, `search_course_offering` — and the search corpus contains noise: the OLD GE rule version (2017-22 admits: "GEW counts toward the GE core") next to the current one, the FinTech-stream study scheme next to the Quantitative Finance one, and the offering search hides the not-offered courses behind explicit "not offered" responses.
|
|
35
|
+
|
|
36
|
+
After researching, the AI must audit its own remaining requirements and submit the plan through the only documented tool, `enroll` (batch or one call per course) — the opaque research tools stay undescribed, but the answer channel is explicit. The enroll tool accepts any well-formed submission blindly (no conflict/prereq validation feedback — otherwise a model could brute-force the unique solution through the SIS). A text-JSON fallback exists for models that never call `enroll`. The plan:
|
|
37
|
+
|
|
38
|
+
- retake the two withdrawn (W) courses — ECO3121 and MAT3007;
|
|
39
|
+
|
|
40
|
+
- retake the two withdrawn (W) courses — ECO3121 and MAT3007;
|
|
41
|
+
- take every offered major-required course whose prerequisites are completed — and exclude the **prerequisite trap** FIN4120 (its prereq FIN3080 is only in progress);
|
|
42
|
+
- complete the last GE foundation course **GFH1000** (与人文对话);
|
|
43
|
+
- take the remaining CEC course **CEC4000** (GEW-type: it does not count toward the GE core or the 2-GE-per-term limit);
|
|
44
|
+
- add exactly one GE-area course (area B/C/D still remaining — decoy area courses conflict with everything);
|
|
45
|
+
- fit the **full 18-unit load** with zero time conflicts.
|
|
46
|
+
|
|
47
|
+
The instance is constructed plant-then-noise with a fixed seed: the unique solution is planted first (pairwise non-overlapping sessions), then noise sections are added that deliberately overlap planted sessions — so **exactly one valid plan exists** (verified by a solver at generation time). Two more binding constraints raise the difficulty: the timetable must leave **Friday completely free** (a same-feasibility decoy area course sits entirely on Friday — dropping this rule yields 3 valid plans instead of 1, verified at generation time), and the GE-area course must be chosen under that rule. Scores are computed programmatically as ten weighted rule checks: required coverage (0.15), prerequisite-trap avoidance (0.10), no unknown/extra courses (0.10), GE foundation (0.10), CEC4000 (0.15), GE-area course (0.10), GE per-term limit (0.05), zero conflicts (0.10), exact 18-unit load (0.10), Friday-free timetable (0.05).
|
|
48
|
+
|
|
49
|
+
### Quantitative Research Practice (multi-factor mining, inference, out-of-sample test)
|
|
50
|
+
|
|
51
|
+
A math-heavy **agentic research task**, scored 80% programmatically + 20% by human review of the written note. No data is given in the prompt: the model must discover the data universe through two opaque tools (`meta_list`, `series_fetch`) — the universe contains 10 series including a revised-index decoy (SZTECH_V2), a BTC distraction, and a five-candidate factor library (MOM / VAL / SIZE / VOL / LIQ) where three factors are pure noise.
|
|
52
|
+
|
|
53
|
+
The true driver of SZTECH (estimation window 2024, 12 observations) is the market plus **exactly two** library factors (MOM + VAL) — verified at generation time (t(MOM) = 15.2, t(VAL) = 6.1, every noise factor |t| < 1.5 when appended to the true model, corr(MOM, VAL) = 0.10, seeded by rejection sampling). The model must:
|
|
54
|
+
|
|
55
|
+
- slice the 2024 window out of the 24-month histories (the fetch returns everything — window-slicing noise);
|
|
56
|
+
- mine the factor library as a **subset-selection** problem: screen candidates, keep the two real factors, exclude decoys;
|
|
57
|
+
- estimate the four-unknown OLS **by hand** (const + MKT + MOM + VAL — 4x4 normal equations) for alpha, the three betas and R-squared;
|
|
58
|
+
- compute the **t-statistics of both factor betas** — this requires the (X'X)^-1 diagonal and the residual variance, i.e. formal inference, not just point estimates;
|
|
59
|
+
- compute the annualized Sharpe (RF series), sample standard deviation, maximum drawdown, and the 3-worst-observation expected shortfall;
|
|
60
|
+
- pass the **out-of-sample test**: apply the 2024 coefficients to each 2025 month (the second year of history is no longer dead weight) and report the RMSE of the prediction errors;
|
|
61
|
+
- write a 200-450-word research note (mining method, identification evidence, out-of-sample performance, limitation) — human-reviewed.
|
|
62
|
+
|
|
63
|
+
Numeric answers are checked with per-question tolerances against an answer key computed programmatically (4x4 normal equations, matrix inverse, compounding, drawdown); percent/decimal-fraction scale confusion is tolerated. Final score = 80% x auto + 20% x note. A wrong factor subset (missing one true factor or keeping a decoy) immediately drops 12 points of auto weight, and the beta/t-stat answers become unanswerable correctly — factor identification is the gate.
|
|
64
|
+
|
|
65
|
+
### SVG Drawing
|
|
66
|
+
|
|
67
|
+
All three stages carry **machine-checked structural constraints** on the SVG reply: root `<svg>` with BOTH viewBox and explicit width/height, minimum labeled-text counts (5 / 6 / 8 per stage), font-size >= 14 everywhere, explicit arrowheads (marker or triangle) for relation/architecture stages, the picked subjects must appear as labels, and a legend/caption box must exist. Results are printed as a PASS/FAIL table in the review PDF (suggested -5 per violation, reviewer confirms). The prompts additionally demand scene composition requirements per stage (environmental props with labels + caption for riding; >= 3 intermediate dated hops for relation; >= 8 components + legend + grouping boundary for architecture).
|
|
68
|
+
|
|
69
|
+
#### Stage One
|
|
70
|
+
|
|
71
|
+
We have a bunch of nouns A and B. For Set A, there are some words referring to an animal/person, e.g. Xu Yangsheng (President) or Qin Shi Huang. For Set B, there are some words referring to a physical and biological non-animal, e.g. iPhone or Teaching Building.
|
|
72
|
+
|
|
73
|
+
The benchmark randomly selects one word from A and one word from B, and asks the model to draw an SVG of A riding B, e.g. President Xu riding GPA.
|
|
74
|
+
|
|
75
|
+
Set A includes: Xu Yangsheng (President), The First Emperor of Qin (Qin Shi Huang), Confucius, Qu Yuan (屈原), Zheng He (郑和), Zhang Heng (张衡)
|
|
76
|
+
|
|
77
|
+
Set B includes: iPhone, Fridge, Rocket, Wi-Fi, GPA, Bicycle, Cybertruck, Drone, WeChat
|
|
78
|
+
|
|
79
|
+
The benchmark does this once and moves on.
|
|
80
|
+
|
|
81
|
+
#### Stage Two
|
|
82
|
+
|
|
83
|
+
The benchmark selects two random persons in A, and lets the AI draw a COMPLETE illustration of how these two persons are indirectly related.
|
|
84
|
+
|
|
85
|
+
The AI is asked once. The output is still an SVG file.
|
|
86
|
+
|
|
87
|
+
#### Stage Three
|
|
88
|
+
|
|
89
|
+
The benchmark selects a random item in B, and lets the AI draw an architecture diagram.
|
|
90
|
+
|
|
91
|
+
The AI is asked once. The output is still an SVG file.
|
|
92
|
+
|
|
93
|
+
### Essay Writing with RUBRIC
|
|
94
|
+
|
|
95
|
+
RUBICs for the three writing tests are adapted from the school-provided RUBIC1.docx (same dimensions, weights, level bands and deduction rules); the original sheet is kept at `wl_benchmark/tasks_data/essay/_source/RUBIC1.docx`. The rubric is provided to the model as a photo (multimodal) by default; text/PDF modes are switchable.
|
|
96
|
+
|
|
97
|
+
Every writing task now carries **machine-checked hard constraints** on top of the rubric quality dimensions: language-section headings, English word-range and Chinese character-range windows, required scene/section headings, typed evidence tags, boundary conditions, method-rigor keywords. The harness verifies each constraint programmatically and the result table is printed in the review PDF (suggested -5 per violated constraint, reviewer confirms).
|
|
98
|
+
|
|
99
|
+
#### Story Telling
|
|
100
|
+
|
|
101
|
+
The benchmark asks the AI to write a story about Qin Shi Huang riding a Polar Bear and looking at his phone — in **exactly three scenes** (parallel `### Scene N —` / `### 场景 N —` headings), where the phone must create the conflict once and resolve it once, and every modern object needs an in-world explanation.
|
|
102
|
+
|
|
103
|
+
The output should be in markdown format, in both English and Chinese (中英双语): English 800-1200 words, Chinese 1200-2000 characters.
|
|
104
|
+
|
|
105
|
+
#### Argument Writing
|
|
106
|
+
|
|
107
|
+
The benchmark asks the AI to write an argument essay about why we could use smartphones while walking inside the campus.
|
|
108
|
+
|
|
109
|
+
The AI must provide **at least four typed evidences** (`**[Statistic]**`, `**[Campus observation]**`, `**[Analogy]**`, `**[Authority]**`, `**[Counterfactual]**` — at least three distinct types), a rebuttal of "走路不看手机" that states the strongest opposing version **and concedes one point** before refuting, and a boundary-conditions paragraph naming where the position does NOT hold.
|
|
110
|
+
|
|
111
|
+
The output should be in markdown format, in both English and Chinese (中英双语): English 900-1300 words, Chinese 1400-2200 characters.
|
|
112
|
+
|
|
113
|
+
#### Research Proposal Writing
|
|
114
|
+
|
|
115
|
+
The benchmark transfers the results of the previous two writings as context, and asks the AI to design research towards the topic: whether we could use smartphones while walking inside the campus.
|
|
116
|
+
|
|
117
|
+
The proposal must carry full method rigor: sampling frame and target N, operationalized IV/DV, instrument, identification strategy, a pre-registered falsifiable **H1**, at least three expected outcomes each paired with its refuting observation, the story cited as motivation plus at least two Task-2 claims converted into hypotheses tagged `[from Task 2]`, and two validity threats with mitigations.
|
|
118
|
+
|
|
119
|
+
The output should be in markdown format, in both English and Chinese (中英双语): English 1100-1600 words, Chinese 1700-2600 characters.
|
|
120
|
+
|
|
121
|
+
## Usage
|
|
122
|
+
|
|
123
|
+
The tool is self-contained (Python standard library only, no third-party dependencies). It is a pure instrument: **no provider presets are stored** — every run interactively asks for the target under test.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Connectivity check: asks for endpoint/key/model, verifies and exits
|
|
127
|
+
./wlb doctor
|
|
128
|
+
|
|
129
|
+
# List the discovered tasks
|
|
130
|
+
./wlb list-tasks
|
|
131
|
+
|
|
132
|
+
# Run the full suite: asks for endpoint -> API key (hidden) -> model
|
|
133
|
+
# (after key input it fetches the endpoint's model list, so you can pick by number)
|
|
134
|
+
# By default every finished run is uploaded to the benchmark platform
|
|
135
|
+
# (share link printed, local run data then deleted)
|
|
136
|
+
./wlb run
|
|
137
|
+
|
|
138
|
+
# Non-interactive (script-friendly), optionally restricted to some domains
|
|
139
|
+
./wlb run --endpoint https://api.example.com/v1 --key sk-xxx --model model-a \
|
|
140
|
+
--tasks essay,svg
|
|
141
|
+
|
|
142
|
+
# Keep the local run data instead of deleting it after upload
|
|
143
|
+
./wlb run --keep
|
|
144
|
+
|
|
145
|
+
# Skip the platform entirely (results stay local)
|
|
146
|
+
./wlb run --no-upload
|
|
147
|
+
|
|
148
|
+
# Re-upload a run whose upload failed (kept locally in that case)
|
|
149
|
+
./wlb publish results/<timestamp>
|
|
150
|
+
|
|
151
|
+
# Rebuild the summary of a finished run
|
|
152
|
+
./wlb report results/<timestamp>/
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Install as a global command: `pip install .` (provides `wlb`), or symlink `ln -sf $(pwd)/wlb /usr/local/bin/wlb`.
|
|
156
|
+
|
|
157
|
+
### Run output
|
|
158
|
+
|
|
159
|
+
Everything lands in `results/<timestamp>/`:
|
|
160
|
+
|
|
161
|
+
| File | Purpose |
|
|
162
|
+
|---|---|
|
|
163
|
+
| `review.pdf` | **one consolidated human-review PDF**: summary table + every task's full output (essays, rendered SVGs, scheduling details), each scored section has a blank scoring box |
|
|
164
|
+
| `results.json` | structured results of all tasks (incrementally dumped — a crashed run keeps its data) |
|
|
165
|
+
| `summary.md` | overview table: programmatic scores; essay/svg marked "pending human review" with artifact paths |
|
|
166
|
+
| `artifacts/` | individual artifacts: essays `*.md`, drawings `*.svg` + `*.png` |
|
|
167
|
+
| `config.snapshot.json` | run-configuration snapshot (key masked) |
|
|
168
|
+
|
|
169
|
+
`review.pdf` is generated automatically at the end of every run; `./wlb report results/<timestamp>/` regenerates both files anytime.
|
|
170
|
+
|
|
171
|
+
### Human review flow
|
|
172
|
+
|
|
173
|
+
1. Open `results/<timestamp>/review.pdf` — everything is in there: the summary table, each essay with its RUBRIC, each rendered SVG, each scheduling detail, and a blank scoring box per task.
|
|
174
|
+
2. Grade each scored section against the RUBIC (Intellectual Content 25 / Organization 25 / Language Use 50, A–F bands, deductions), fill in the boxes.
|
|
175
|
+
3. If you prefer raw files, the individual artifacts stay in `artifacts/` (`*.md` essays, `*.svg`/`*.png` drawings).
|
|
176
|
+
|
|
177
|
+
### Benchmark platform (default upload + share links)
|
|
178
|
+
|
|
179
|
+
Every run is published to your own **WL-Benchmark platform** — a one-time-deployed
|
|
180
|
+
Cloudflare Worker (`site/`, KV storage, no build step). The flow:
|
|
181
|
+
|
|
182
|
+
1. `wlb run` finishes → builds one self-contained page for the run (images inlined);
|
|
183
|
+
2. `POST <site>/api/runs` uploads it (Bearer token);
|
|
184
|
+
3. the share link `https://benchmark.wulei.org/r/<run-id>` is printed — send it to anyone;
|
|
185
|
+
4. the local run directory is **deleted** (the platform is the single source of truth).
|
|
186
|
+
|
|
187
|
+
The platform accumulates all runs at `/` (index) with `/r/<id>` detail pages.
|
|
188
|
+
Setup: deploy `site/` once (see `site/README.md`), then either set
|
|
189
|
+
`WL_BENCH_URL` + `WL_BENCH_TOKEN` or answer the interactive prompt on the first
|
|
190
|
+
run (saved to `config/site.json`, gitignored).
|
|
191
|
+
|
|
192
|
+
### Run parameters
|
|
193
|
+
|
|
194
|
+
Optional file `config/bench.json` (see `config/bench.example.json`) may override: `rubric_modality` (`auto|image|doc|text`), `max_tokens`, `essay_max_tokens`, `svg_max_tokens`, `scheduling_max_tokens`, `temperature`, `timeout`, `tasks_data_root`. Provider information is never stored there.
|
|
195
|
+
|
|
196
|
+
## Task data layout
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
wl_benchmark/tasks_data/
|
|
200
|
+
├── essay/
|
|
201
|
+
│ ├── 01-storytelling/ task.md + rubric.png|md + spec.json (constraints)
|
|
202
|
+
│ ├── 02-argument/ task.md + rubric.png|md + spec.json (constraints)
|
|
203
|
+
│ ├── 03-proposal/ task.md + rubric.png|md + spec.json (context_from + constraints)
|
|
204
|
+
│ └── _source/ RUBIC1.docx (school original) + generated sheets
|
|
205
|
+
├── quant/ # fe-mining-01.json (generated by tools/gen_quant.py)
|
|
206
|
+
├── svg/ # stage1-riding / stage2-relation / stage3-architecture
|
|
207
|
+
└── scheduling/term-plan-2627t1.json # generated by tools/gen_scheduling.py
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Directory numeric prefixes define execution order (chained tasks read the outputs of earlier ones).
|
|
211
|
+
|
|
212
|
+
## Adding new tasks
|
|
213
|
+
|
|
214
|
+
- New tool scenario: drop a JSON into `tool_use/named/` or `tool_use/unlabeled/`
|
|
215
|
+
- New scheduling instance: `python3 tools/gen_scheduling.py --seed <n>`
|
|
216
|
+
- New essay task: create `essay/<NN-name>/` with `task.md` + `rubric.*`; add `spec.json` with `context_from` for chained tasks
|
|
217
|
+
- New SVG task: add a JSON under `svg/`, choosing the `stage` mode
|
|
218
|
+
|
|
219
|
+
## Roadmap
|
|
220
|
+
|
|
221
|
+
- [ ] Human Evaluation (A/B test system): after a model passes the automated tests, route it to a real-environment A/B system and collect user feedback with tools that cannot affect important messages. (not finished yet)
|
|
222
|
+
- [ ] Publish to PyPI / Homebrew.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wl-benchmark"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "WL-Benchmark: the AI benchmark of CUHK Shenzhen — tool use, RUBRIC essays, scheduling, SVG"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "WL" }]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
keywords = ["llm", "benchmark", "evaluation", "function-calling", "agents"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
wlb = "wl_benchmark.cli:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
packages = ["wl_benchmark", "wl_benchmark.tasks"]
|
|
34
|
+
include-package-data = true
|
|
35
|
+
|
|
36
|
+
[tool.setuptools.package-data]
|
|
37
|
+
wl_benchmark = ["tasks_data/**/*"]
|
|
File without changes
|