dsh-livebench-panel 0.1.6 → 0.1.7
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.
- package/lib/client.js +73 -48
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -99,9 +99,9 @@ window.__ModuleLoader__.load({
|
|
|
99
99
|
const [exitCode, setExitCode] = useState(null);
|
|
100
100
|
const [startError, setStartError] = useState(null);
|
|
101
101
|
const [results, setResults] = useState(null);
|
|
102
|
-
const [
|
|
103
|
-
const [
|
|
104
|
-
try { return JSON.parse(localStorage.getItem("
|
|
102
|
+
const [pickedTasks, setPickedTasks] = useState(() => new Set());
|
|
103
|
+
const [taskOrder, setTaskOrder] = useState(() => {
|
|
104
|
+
try { return JSON.parse(localStorage.getItem("dlb_task_order_v1")) ?? []; } catch { return []; }
|
|
105
105
|
});
|
|
106
106
|
const dragKey = useRef(null);
|
|
107
107
|
const logRef = useRef(null);
|
|
@@ -265,52 +265,78 @@ window.__ModuleLoader__.load({
|
|
|
265
265
|
});
|
|
266
266
|
};
|
|
267
267
|
|
|
268
|
-
// ----
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
268
|
+
// ---- 成绩矩阵:task 为行(含 category 行标)、model 为列 ----
|
|
269
|
+
// 附带:time 列(该任务评测开始时间 = 行内最早判分时间)、
|
|
270
|
+
// 行拖拽排序(localStorage 持久化)、行选择与单行/批量删除。
|
|
271
|
+
const taskKey = (category, task) => `${category}/${task}`;
|
|
272
|
+
const matrix = useMemo(() => {
|
|
273
|
+
if (!results) return null;
|
|
274
|
+
const models = [...new Set(results.rows.map((r) => r.model))].sort();
|
|
275
|
+
const byTask = new Map(); // `${cat}/${task}` -> {category, task, cells: Map(model->row), startTime}
|
|
276
|
+
for (const row of results.rows) {
|
|
277
|
+
const key = taskKey(row.category, row.task);
|
|
278
|
+
const entry = byTask.get(key) ?? { category: row.category, task: row.task, cells: new Map(), startTime: Infinity };
|
|
279
|
+
entry.cells.set(row.model, row);
|
|
280
|
+
if (row.time && row.time < entry.startTime) entry.startTime = row.time;
|
|
281
|
+
byTask.set(key, entry);
|
|
282
|
+
}
|
|
283
|
+
return { models, tasks: [...byTask.entries()] };
|
|
284
|
+
}, [results]);
|
|
285
|
+
const sortedTasks = useMemo(() => {
|
|
286
|
+
if (!matrix) return [];
|
|
287
|
+
const indexOf = new Map(taskOrder.map((key, index) => [key, index]));
|
|
288
|
+
return [...matrix.tasks].sort((a, b) => {
|
|
289
|
+
const ia = indexOf.has(a[0]) ? indexOf.get(a[0]) : Number.MAX_SAFE_INTEGER;
|
|
290
|
+
const ib = indexOf.has(b[0]) ? indexOf.get(b[0]) : Number.MAX_SAFE_INTEGER;
|
|
276
291
|
if (ia !== ib) return ia - ib;
|
|
277
|
-
return (b
|
|
292
|
+
return a[0].localeCompare(b[0]);
|
|
278
293
|
});
|
|
279
|
-
}, [
|
|
294
|
+
}, [matrix, taskOrder]);
|
|
280
295
|
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
try { localStorage.setItem("
|
|
296
|
+
const persistTaskOrder = (keys) => {
|
|
297
|
+
setTaskOrder(keys);
|
|
298
|
+
try { localStorage.setItem("dlb_task_order_v1", JSON.stringify(keys)); } catch { /* private mode */ }
|
|
284
299
|
};
|
|
285
300
|
|
|
286
301
|
const onRowDrop = (targetKey) => {
|
|
287
302
|
const sourceKey = dragKey.current;
|
|
288
303
|
dragKey.current = null;
|
|
289
304
|
if (!sourceKey || sourceKey === targetKey) return;
|
|
290
|
-
const keys =
|
|
305
|
+
const keys = sortedTasks.map(([key]) => key);
|
|
291
306
|
const from = keys.indexOf(sourceKey);
|
|
292
307
|
const to = keys.indexOf(targetKey);
|
|
293
308
|
if (from < 0 || to < 0) return;
|
|
294
309
|
keys.splice(to, 0, keys.splice(from, 1)[0]);
|
|
295
|
-
|
|
310
|
+
persistTaskOrder(keys);
|
|
296
311
|
};
|
|
297
312
|
|
|
298
|
-
const togglePicked = (key) =>
|
|
313
|
+
const togglePicked = (key) => setPickedTasks((prev) => {
|
|
299
314
|
const next = new Set(prev);
|
|
300
315
|
if (next.has(key)) next.delete(key); else next.add(key);
|
|
301
316
|
return next;
|
|
302
317
|
});
|
|
303
318
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (!
|
|
319
|
+
// 删除一个任务行 = 删除该任务下所有模型的判分与答案记录
|
|
320
|
+
const deleteTasks = async (keys) => {
|
|
321
|
+
if (!results || keys.length === 0) return;
|
|
322
|
+
const serverRows = [];
|
|
323
|
+
for (const key of keys) {
|
|
324
|
+
const [category, task] = key.split("/");
|
|
325
|
+
for (const row of results.rows) {
|
|
326
|
+
if (row.category === category && row.task === task) {
|
|
327
|
+
serverRows.push({ model: row.model, category, task });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (serverRows.length === 0) return;
|
|
332
|
+
if (!window.confirm(`确认删除所选 ${keys.length} 个任务的全部评测成绩(共 ${serverRows.length} 条模型记录,含答案)?不可恢复。`)) return;
|
|
307
333
|
await api("/delete", {
|
|
308
334
|
method: "POST",
|
|
309
335
|
headers: { "content-type": "application/json" },
|
|
310
|
-
body: JSON.stringify({ rows:
|
|
336
|
+
body: JSON.stringify({ rows: serverRows }),
|
|
311
337
|
});
|
|
312
|
-
|
|
313
|
-
|
|
338
|
+
setPickedTasks(new Set());
|
|
339
|
+
persistTaskOrder(taskOrder.filter((key) => !keys.includes(key)));
|
|
314
340
|
await loadResults();
|
|
315
341
|
};
|
|
316
342
|
|
|
@@ -405,32 +431,29 @@ window.__ModuleLoader__.load({
|
|
|
405
431
|
),
|
|
406
432
|
h("pre", { className: c("log"), ref: logRef }, log || "(暂无输出)"),
|
|
407
433
|
),
|
|
408
|
-
|
|
434
|
+
sortedTasks.length > 0 && h("div", { className: c("card") },
|
|
409
435
|
h("div", { className: c("row") },
|
|
410
|
-
h("span", { className: c("label") }, "评测成绩(分数 = 平均分 ×100
|
|
436
|
+
h("span", { className: c("label") }, "评测成绩(分数 = 平均分 ×100,括号内为 已判/总题数;行首可拖动排序,顺序保存在本机)"),
|
|
411
437
|
h("button", {
|
|
412
438
|
className: c("btn") + " " + c("btnDanger"),
|
|
413
|
-
disabled:
|
|
414
|
-
onClick: () =>
|
|
415
|
-
}, `删除所选(${
|
|
439
|
+
disabled: pickedTasks.size === 0,
|
|
440
|
+
onClick: () => deleteTasks([...pickedTasks]),
|
|
441
|
+
}, `删除所选(${pickedTasks.size})`),
|
|
416
442
|
),
|
|
417
443
|
h("table", { className: c("table") },
|
|
418
444
|
h("thead", null, h("tr", null,
|
|
419
|
-
h("th", { style: { width: "
|
|
445
|
+
h("th", { style: { width: "26px" } }, "⠿"),
|
|
420
446
|
h("th", { style: { width: "30px" } },
|
|
421
|
-
h("input", { type: "checkbox", checked:
|
|
422
|
-
onChange: (event) =>
|
|
423
|
-
h("th", null, "time"),
|
|
424
|
-
h("th", null, "model"),
|
|
425
|
-
h("th", null, "category"),
|
|
447
|
+
h("input", { type: "checkbox", checked: pickedTasks.size > 0 && pickedTasks.size === sortedTasks.length,
|
|
448
|
+
onChange: (event) => setPickedTasks(event.target.checked ? new Set(sortedTasks.map(([key]) => key)) : new Set()) })),
|
|
426
449
|
h("th", null, "task"),
|
|
427
|
-
h("th",
|
|
428
|
-
h("th", null, "
|
|
450
|
+
matrix.models.map((model) => h("th", { key: model }, model)),
|
|
451
|
+
h("th", null, "删除"),
|
|
452
|
+
h("th", null, "time"),
|
|
429
453
|
)),
|
|
430
454
|
h("tbody", null,
|
|
431
|
-
|
|
432
|
-
const
|
|
433
|
-
const checked = pickedRows.has(key);
|
|
455
|
+
sortedTasks.map(([key, entry]) => {
|
|
456
|
+
const checked = pickedTasks.has(key);
|
|
434
457
|
return h("tr", {
|
|
435
458
|
key,
|
|
436
459
|
draggable: true,
|
|
@@ -440,15 +463,17 @@ window.__ModuleLoader__.load({
|
|
|
440
463
|
},
|
|
441
464
|
h("td", { className: c("drag"), title: "拖动排序" }, "⠿"),
|
|
442
465
|
h("td", null, h("input", { type: "checkbox", checked, onChange: () => togglePicked(key) })),
|
|
443
|
-
h("td", null,
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
466
|
+
h("td", null, h("span", { title: `${entry.category} / ${entry.task}` }, `${entry.category} / ${entry.task}`)),
|
|
467
|
+
matrix.models.map((model) => {
|
|
468
|
+
const row = entry.cells.get(model);
|
|
469
|
+
return h("td", { key: model, className: c("score") },
|
|
470
|
+
row ? `${row.score.toFixed(1)} (${row.judged}/${row.total})` : "—");
|
|
471
|
+
}),
|
|
448
472
|
h("td", null, h("button", {
|
|
449
|
-
className: c("btnGhost") + " " + c("btn"), title: "
|
|
450
|
-
onClick: () =>
|
|
473
|
+
className: c("btnGhost") + " " + c("btn"), title: "删除该任务下所有模型的评测成绩",
|
|
474
|
+
onClick: () => deleteTasks([key]),
|
|
451
475
|
}, "删除")),
|
|
476
|
+
h("td", null, fmtTime(entry.startTime === Infinity ? null : entry.startTime)),
|
|
452
477
|
);
|
|
453
478
|
})),
|
|
454
479
|
),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-livebench-panel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "DSH web plugin: a LiveBench tab in the Trajectory view (right of 对话/轨迹). Run LiveBench evaluations against every model configured in the DeepSeek Harness — pick provider/model, category, task, release and question range from dropdowns, watch progress, and read scores in place.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|