dsh-livebench-panel 0.1.1 → 0.1.3
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 +2 -2
- package/lib/index.js +85 -7
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -78,7 +78,7 @@ window.__ModuleLoader__.load({
|
|
|
78
78
|
function LiveBenchView() {
|
|
79
79
|
const [config, setConfig] = useState(null);
|
|
80
80
|
const [configError, setConfigError] = useState(null);
|
|
81
|
-
const [sel, setSel] = useState({ provider: "", model: "", category: "", task: "", release: "2024-11-25", begin: "", end: "", maxTokens: "
|
|
81
|
+
const [sel, setSel] = useState({ provider: "", model: "", reasoning: "default", category: "", task: "", release: "2024-11-25", begin: "", end: "", maxTokens: "32000" });
|
|
82
82
|
const [busy, setBusy] = useState(false);
|
|
83
83
|
const [running, setRunning] = useState(false);
|
|
84
84
|
const [log, setLog] = useState("");
|
|
@@ -273,7 +273,7 @@ window.__ModuleLoader__.load({
|
|
|
273
273
|
),
|
|
274
274
|
),
|
|
275
275
|
h("div", { className: c("field") },
|
|
276
|
-
h("label", { className: c("label") }, "max-tokens"),
|
|
276
|
+
h("label", { className: c("label") }, "max-tokens(默认 32000)"),
|
|
277
277
|
h("input", { className: c("input"), type: "number", min: 256, max: 32768, value: sel.maxTokens, onChange: setField("maxTokens") }),
|
|
278
278
|
),
|
|
279
279
|
),
|
package/lib/index.js
CHANGED
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
import { spawn } from "node:child_process";
|
|
28
28
|
import { readdirSync, readFileSync, existsSync, statSync, writeFileSync } from "node:fs";
|
|
29
29
|
import { createRequire } from "node:module";
|
|
30
|
+
import { delimiter, dirname, join } from "node:path";
|
|
30
31
|
import { homedir } from "node:os";
|
|
31
|
-
import { join } from "node:path";
|
|
32
32
|
import { fileURLToPath } from "node:url";
|
|
33
33
|
|
|
34
34
|
/** Stable Cordis plugin name. */
|
|
@@ -115,9 +115,70 @@ function readProviders(profileDir) {
|
|
|
115
115
|
keyEnv: typeof dsCfg.apiKeyEnv === "string" && dsCfg.apiKeyEnv.length > 0 ? dsCfg.apiKeyEnv : "DEEPSEEK_API_KEY",
|
|
116
116
|
models: dsModels,
|
|
117
117
|
});
|
|
118
|
+
|
|
119
|
+
// Providers without an explicit baseURL may still be OpenAI-compatible with
|
|
120
|
+
// a well-known endpoint: resolve it from the pi-ai provider registry
|
|
121
|
+
// (@earendil-works/pi-ai, the same source the harness serves from).
|
|
122
|
+
const piAiData = resolvePiAiDataDir(profileDir);
|
|
123
|
+
if (piAiData !== null) {
|
|
124
|
+
for (const provider of providers) {
|
|
125
|
+
if (provider.baseURL === null) {
|
|
126
|
+
const base = builtinBaseUrl(piAiData, provider.id);
|
|
127
|
+
if (base !== null) {
|
|
128
|
+
provider.baseURL = base;
|
|
129
|
+
provider.api = provider.api ?? "openai-completions";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
118
134
|
return providers;
|
|
119
135
|
}
|
|
120
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Locate the pi-ai provider data directory (providers/data/*.json).
|
|
139
|
+
* @returns {string|null} directory path, or null when pi-ai cannot be found.
|
|
140
|
+
*/
|
|
141
|
+
function resolvePiAiDataDir(profileDir) {
|
|
142
|
+
const candidates = [];
|
|
143
|
+
// 1) resolvable from the profile's own dependency tree
|
|
144
|
+
try {
|
|
145
|
+
const requireFromProfile = createRequire(join(profileDir, "package.json"));
|
|
146
|
+
candidates.push(join(dirname(requireFromProfile.resolve("@earendil-works/pi-ai/package.json")), "dist", "providers", "data"));
|
|
147
|
+
} catch { /* not in the profile tree */ }
|
|
148
|
+
// 2) the dsh installation the web process booted from (process.argv[1] = .../dsh/lib/bin.js)
|
|
149
|
+
const bin = process.argv[1];
|
|
150
|
+
if (typeof bin === "string" && bin.includes("@deepseek-ai")) {
|
|
151
|
+
const dshRoot = dirname(dirname(bin));
|
|
152
|
+
candidates.push(join(dshRoot, "node_modules", "@earendil-works", "pi-ai", "dist", "providers", "data"));
|
|
153
|
+
}
|
|
154
|
+
// 3) the default global npm layout on Windows
|
|
155
|
+
const appdata = process.env.APPDATA;
|
|
156
|
+
if (appdata) {
|
|
157
|
+
candidates.push(join(appdata, "npm", "node_modules", "@deepseek-ai", "dsh", "node_modules", "@earendil-works", "pi-ai", "dist", "providers", "data"));
|
|
158
|
+
}
|
|
159
|
+
for (const candidate of candidates) {
|
|
160
|
+
if (existsSync(candidate)) return candidate;
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Read one provider's built-in OpenAI-compatible baseUrl from pi-ai data. */
|
|
166
|
+
function builtinBaseUrl(piAiDataDir, providerId) {
|
|
167
|
+
if (!/^[a-z0-9-]+$/.test(providerId)) return null;
|
|
168
|
+
const file = join(piAiDataDir, `${providerId}.json`);
|
|
169
|
+
if (!existsSync(file)) return null;
|
|
170
|
+
try {
|
|
171
|
+
const data = JSON.parse(readFileSync(file, "utf8"));
|
|
172
|
+
const openai = data?.["openai-completions"];
|
|
173
|
+
if (openai && typeof openai === "object") {
|
|
174
|
+
for (const entry of Object.values(openai)) {
|
|
175
|
+
if (entry && typeof entry.baseUrl === "string" && entry.baseUrl.length > 0) return entry.baseUrl;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
} catch { /* unreadable data file — treat as unknown */ }
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
121
182
|
/** Reasoning efforts offered by the built-in DeepSeek route. */
|
|
122
183
|
const DEEPSEEK_EFFORTS = ["off", "low", "high", "max"];
|
|
123
184
|
/** Fallback catalog when settings.yaml has no llm-deepseek.models section. */
|
|
@@ -342,7 +403,7 @@ function apply(ctx) {
|
|
|
342
403
|
/** The single run slot. */
|
|
343
404
|
let run = null;
|
|
344
405
|
|
|
345
|
-
const startRun = (body) => {
|
|
406
|
+
const startRun = async (body) => {
|
|
346
407
|
const layout = livebenchLayout();
|
|
347
408
|
if (!layout.available) {
|
|
348
409
|
return { status: 409, payload: { ok: false, error: `LiveBench venv not found under ${layout.root}` } };
|
|
@@ -390,7 +451,7 @@ function apply(ctx) {
|
|
|
390
451
|
"--model-display-name", displayName,
|
|
391
452
|
"--bench-name", benchParts.join("/"),
|
|
392
453
|
"--livebench-release-option", release,
|
|
393
|
-
"--max-tokens", String(asInt(body.maxTokens, 256, 32768,
|
|
454
|
+
"--max-tokens", String(asInt(body.maxTokens, 256, 32768, 32000)),
|
|
394
455
|
"--parallel-requests", String(asInt(body.parallel, 1, 8, 2)),
|
|
395
456
|
"--mode", "single",
|
|
396
457
|
];
|
|
@@ -406,13 +467,29 @@ function apply(ctx) {
|
|
|
406
467
|
...process.env,
|
|
407
468
|
HF_HOME: join(layout.root, ".hf_cache"),
|
|
408
469
|
HF_HUB_DISABLE_SYMLINKS_WARNING: "1",
|
|
470
|
+
// run_livebench.py shells out to bare `python`; without the venv on
|
|
471
|
+
// PATH that resolves to the system interpreter and dies on the first
|
|
472
|
+
// livebench import (shortuuid etc.).
|
|
473
|
+
PATH: `${join(layout.root, ".venv", "Scripts")}${delimiter}${process.env.PATH ?? ""}`,
|
|
409
474
|
};
|
|
410
475
|
// Only OpenAI-compatible providers can be routed with --api-base; for
|
|
411
|
-
// those, hand the key over via env (never the command line).
|
|
476
|
+
// those, hand the key over via env (never the command line). The key is
|
|
477
|
+
// resolved through the harness credential seam when available (values may
|
|
478
|
+
// live encrypted in .credentials.yaml rather than in the process env),
|
|
479
|
+
// falling back to the plain environment variable.
|
|
412
480
|
if (provider && provider.api === "openai-completions" && provider.baseURL) {
|
|
413
481
|
args.push("--api-base", provider.baseURL);
|
|
414
|
-
if (provider.keyEnv
|
|
415
|
-
|
|
482
|
+
if (provider.keyEnv) {
|
|
483
|
+
let key;
|
|
484
|
+
try {
|
|
485
|
+
const credentials = ctx.get ? ctx.get("credentials") : undefined;
|
|
486
|
+
if (credentials && typeof credentials.resolve === "function") {
|
|
487
|
+
const resolved = await credentials.resolve(provider.keyEnv);
|
|
488
|
+
if (resolved && typeof resolved.value === "string" && resolved.value.length > 0) key = resolved.value;
|
|
489
|
+
}
|
|
490
|
+
} catch { /* credential seam unavailable — fall through to env */ }
|
|
491
|
+
if (!key && process.env[provider.keyEnv]) key = process.env[provider.keyEnv];
|
|
492
|
+
if (key) env.LIVEBENCH_API_KEY = key;
|
|
416
493
|
}
|
|
417
494
|
}
|
|
418
495
|
|
|
@@ -486,6 +563,7 @@ function apply(ctx) {
|
|
|
486
563
|
id,
|
|
487
564
|
name: pname,
|
|
488
565
|
routable: api === "openai-completions" && typeof baseURL === "string" && baseURL.length > 0,
|
|
566
|
+
baseURL: baseURL ?? null,
|
|
489
567
|
models,
|
|
490
568
|
})),
|
|
491
569
|
});
|
|
@@ -515,7 +593,7 @@ function apply(ctx) {
|
|
|
515
593
|
sendJson(res, 409, { ok: false, error: "another evaluation is already running" });
|
|
516
594
|
return;
|
|
517
595
|
}
|
|
518
|
-
const result = startRun(body);
|
|
596
|
+
const result = await startRun(body);
|
|
519
597
|
sendJson(res, result.status, result.payload);
|
|
520
598
|
},
|
|
521
599
|
}), `${name}: start route`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-livebench-panel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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",
|