File size: 8,006 Bytes
5db30ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# ELBench Architecture

This document describes the engineering design of ELBench: the registry, the
provider abstraction, the execution model, and how to extend the framework.
For an overview of the benchmark and the leaderboard, see the top-level
[README](../README.md).

ELBench is built as an engineering system, not a one-off script. Four benchmark
modules are kept in one consistent framework:

- `ๅฎ‰ๅ…จๅฏไฟก` / Safety & Trustworthiness
- `้ซ˜้˜ถ่‚ฒไบบ` / High-Level Educational Cultivation
- `ๅŸบๆœฌๆ•™่‚ฒ` / Basic Education
- `้€š็”จๆจกๅž‹` / General Capability

## Principles

- Registry-driven loading instead of hardcoded file logic
- Provider adapters instead of provider-specific branches in the runner
- Rule-based judging for objective tasks
- `LLM-as-a-Judge` for subjective and open-ended tasks
- Stable machine-readable outputs, logs, checkpoints, and summaries
- Resume support after interruption
- Configurable concurrency with a default global cap of `100`

## What Is Actually Wired Today

### Registered benchmark files

`configs/file_registry.yaml` currently resolves these files:

- `ๅฎ‰ๅ…จๆ‹’็ญ”.jsonl`
- `ๅฎ‰ๅ…จๅผ•ๅฏผ.jsonl`
- `ๅฎ‰ๅ…จๅ›ž็ญ”.jsonl`
- `SATAs.xlsx`
- `adversarial_prompts.xlsx`
- `้ซ˜้˜ถ่‚ฒไบบ-edu.jsonl`
- `้ซ˜้˜ถ่‚ฒไบบ-omni.jsonl`
- `knowledge.yaml`
- `question.yaml`
- `cross.yaml`
- `config_guided_task.yaml`
- `mmlu_pro_sampled.jsonl`
- `ceval_sampled.jsonl`
- `ifeval_sampled.jsonl`
- `math_500_sampled.jsonl`
- `aime24_sampled.jsonl`
- `aime25.jsonl`
- `aime26.jsonl`
- `gsm8k_sampled.jsonl`

Files are only considered active benchmark inputs after they are registered.
Data files not present in `configs/file_registry.yaml` are not part of the
runnable benchmark.

### Current judge strategy

Objective tasks use rule or reference matching:

- `SATAs.xlsx`
- `้ซ˜้˜ถ่‚ฒไบบ-omni.jsonl`
- `mmlu_pro_sampled.jsonl`
- `ceval_sampled.jsonl`
- `ifeval_sampled.jsonl`
- `math_500_sampled.jsonl`
- `aime24_sampled.jsonl`
- `aime25.jsonl`
- `aime26.jsonl`
- `gsm8k_sampled.jsonl`

Subjective or open-ended tasks use `LLM-as-a-Judge`:

- `ๅฎ‰ๅ…จๆ‹’็ญ”.jsonl`
- `ๅฎ‰ๅ…จๅผ•ๅฏผ.jsonl`
- `ๅฎ‰ๅ…จๅ›ž็ญ”.jsonl`
- `adversarial_prompts.xlsx`
- `้ซ˜้˜ถ่‚ฒไบบ-edu.jsonl`

The repository still treats external provider integration as pluggable.
`mock.default` and `mock.judge` are included so the full pipeline can be
validated locally without real API access.

## Repository Layout

```text
.
โ”œโ”€โ”€ configs/
โ”‚   โ”œโ”€โ”€ app.yaml
โ”‚   โ”œโ”€โ”€ basic_education.yaml
โ”‚   โ”œโ”€โ”€ field_mappings.yaml
โ”‚   โ”œโ”€โ”€ file_registry.yaml
โ”‚   โ”œโ”€โ”€ judges.yaml
โ”‚   โ”œโ”€โ”€ models.yaml
โ”‚   โ”œโ”€โ”€ module_registry.yaml
โ”‚   โ””โ”€โ”€ providers.yaml
โ”œโ”€โ”€ data/
โ”‚   โ””โ”€โ”€ benchmark_root/
โ”‚       โ”œโ”€โ”€ ๅฎ‰ๅ…จๅฏไฟก/
โ”‚       โ”œโ”€โ”€ ้ซ˜้˜ถ่‚ฒไบบ/
โ”‚       โ”œโ”€โ”€ ๅŸบๆœฌๆ•™่‚ฒ/
โ”‚       โ””โ”€โ”€ ้€š็”จ/
โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ TEAM_MAINTENANCE_GUIDE.zh-CN.md
โ”œโ”€โ”€ results/
โ”œโ”€โ”€ scripts/
โ”‚   โ””โ”€โ”€ run_benchmark.py
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ elbench/
โ”‚       โ”œโ”€โ”€ basic_education_runtime/
โ”‚       โ”œโ”€โ”€ cli.py
โ”‚       โ”œโ”€โ”€ config/
โ”‚       โ”œโ”€โ”€ execution/
โ”‚       โ”œโ”€โ”€ judges/
โ”‚       โ”œโ”€โ”€ loaders/
โ”‚       โ”œโ”€โ”€ persistence/
โ”‚       โ”œโ”€โ”€ providers/
โ”‚       โ”œโ”€โ”€ registry/
โ”‚       โ”œโ”€โ”€ schemas/
โ”‚       โ”œโ”€โ”€ summary/
โ”‚       โ””โ”€โ”€ utils/
โ””โ”€โ”€ tests/
```

`scripts/run_benchmark.py` is intentionally a thin entrypoint. The actual
benchmark logic lives under `src/elbench/`.

## Core Architecture

### Registry and schema adaptation

- `configs/file_registry.yaml` maps files to module, subset, task, loader, and
  canonical name.
- `configs/field_mappings.yaml` maps raw dataset fields into ELBench's unified
  internal schema.
- JSONL, XLSX, and basic-education YAML inputs are normalized into the same
  `Sample` structure.

### Unified sample/result schema

Loaded records are normalized into a stable schema with fields such as:

- `sample_id`
- `source_file`
- `module`
- `subset`
- `task`
- `dimension`
- `prompt`
- `reference`
- `metadata`

Execution output includes:

- `provider_name`
- `model_id`
- `model_name`
- `model_response`
- `judge_result`
- `score`
- `judge_reason`
- `judge_metadata`
- `latency_ms`
- `retry_count`
- `timestamp`

### Provider abstraction

- `ModelClient` is the common interface for model execution.
- Provider-specific API differences are isolated under `src/elbench/providers/`.
- The main runner does not care whether a model comes from OpenAI, Anthropic,
  Gemini, or another vendor once the adapter exists.

### Execution, concurrency, and recovery

The runner supports:

- global concurrency control
- provider/model-level concurrency limits
- retry with exponential backoff
- failure logging
- checkpoint-based resume
- raw-response persistence
- judged-result persistence
- summary generation

Default global max concurrency is `100` in `configs/app.yaml`.

### Basic Education runtime

`ๅŸบๆœฌๆ•™่‚ฒ` differs from the other modules only in execution style, not in data
governance:

- benchmark data stays under `data/benchmark_root/ๅŸบๆœฌๆ•™่‚ฒ/`
- file discovery still goes through `configs/file_registry.yaml`
- runtime execution is handled by `src/elbench/execution/basic_education.py`
- the internal runtime implementation lives under
  `src/elbench/basic_education_runtime/`

This internal runtime was adapted from the ELMES project, but it is now packaged
and maintained as part of ELBench itself.

## Output Layout

```text
outputs/
โ”œโ”€โ”€ raw_responses/
โ”œโ”€โ”€ judged_results/
โ”œโ”€โ”€ summaries/
โ””โ”€โ”€ logs/
```

These directories are runtime artifacts and are intentionally ignored by Git.
Curated leaderboards and audit summaries are committed under `results/`.

## Configuration Surface

### `configs/models.yaml`

Concrete evaluated-model and judge-model instances, including timeout, retry,
rate limits, and provider kwargs.

### `configs/providers.yaml`

Provider adapter registry plus default provider capabilities. Current built-in
adapters:

- `mock`
- `openai_compatible`

### `configs/judges.yaml`

Task-to-judge routing:

- `rule`
- `llm`

### `configs/basic_education.yaml`

Scenario-level runtime settings for the internal basic education runtime. This
file does not replace the registry; it complements it.

## Extending ELBench

### Add a new provider

1. Implement an adapter under `src/elbench/providers/`.
2. Register it in `configs/providers.yaml`.
3. Add concrete models in `configs/models.yaml`.

### Add a new benchmark file

1. Put the data file under `data/benchmark_root/`.
2. Register it in `configs/file_registry.yaml`.
3. Add field mappings in `configs/field_mappings.yaml`.
4. Route judging in `configs/judges.yaml`.
5. Add or reuse tests.

### Add a future module

ELBench already reserves space for further modules. The intended path remains:

1. add module registration
2. add file registration
3. add field mappings
4. add judge routing
5. add task-specific logic only if configuration cannot express the behavior

No main-runner rewrite should be required.

## Maintenance

The canonical team maintenance guide is
[`docs/TEAM_MAINTENANCE_GUIDE.zh-CN.md`](TEAM_MAINTENANCE_GUIDE.zh-CN.md). That
document explains what each maintained directory is for, which paths are
runtime-only, and what should or should not be committed.

## Status

Implemented:

- config system
- file registry
- JSONL/XLSX/YAML loaders
- unified sample/result schema
- provider abstraction
- concurrent runner
- retries and checkpoint resume
- raw/judged/summary/log outputs
- rule judges for objective tasks
- `LLM-as-a-Judge` execution path for subjective tasks
- built-in basic-education bridge on top of the internal runtime module

Still intentionally unfinished:

- production-grade adapters for every external vendor
- finalized subjective judge rubrics and prompts
- complete future-module integration beyond the current registered files