feat: add LLM role-assignment panel to 新建评估 view
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
// runner.js — 新建评估视图:列出场景、触发评估、轮询任务状态与日志。
|
// runner.js — 新建评估视图:列出场景、LLM角色配置、触发评估、轮询任务状态与日志。
|
||||||
|
|
||||||
const Runner = {
|
const Runner = {
|
||||||
selectedScenario: null,
|
selectedScenario: null,
|
||||||
pollTimer: null,
|
pollTimer: null,
|
||||||
|
lastRunId: null,
|
||||||
|
|
||||||
// 绑定运行按钮。
|
// 绑定运行按钮。
|
||||||
init() {
|
init() {
|
||||||
@@ -32,6 +33,27 @@ const Runner = {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
list.innerHTML = `<p class="muted">加载失败:${App.escape(err.message)}</p>`;
|
list.innerHTML = `<p class="muted">加载失败:${App.escape(err.message)}</p>`;
|
||||||
}
|
}
|
||||||
|
// 同时加载 profiles 供角色选择
|
||||||
|
Runner._populateProfileSelects();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 填充三个角色下拉框
|
||||||
|
async _populateProfileSelects() {
|
||||||
|
const cached = Profiles.getAll();
|
||||||
|
const profiles = cached.length > 0
|
||||||
|
? cached
|
||||||
|
: (await API.profiles().catch(() => ({ profiles: [] }))).profiles;
|
||||||
|
|
||||||
|
["role-judge", "role-answer", "role-dataset"].forEach(id => {
|
||||||
|
const sel = document.getElementById(id);
|
||||||
|
sel.innerHTML = '<option value="">— 使用场景原始配置 —</option>';
|
||||||
|
profiles.forEach(p => {
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = p.profile_id;
|
||||||
|
opt.textContent = `${p.name} (${p.model})`;
|
||||||
|
sel.appendChild(opt);
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 构造单个场景条目。
|
// 构造单个场景条目。
|
||||||
@@ -64,12 +86,14 @@ const Runner = {
|
|||||||
Runner.selectedScenario = sc.path;
|
Runner.selectedScenario = sc.path;
|
||||||
document.getElementById("selected-scenario").textContent = sc.path;
|
document.getElementById("selected-scenario").textContent = sc.path;
|
||||||
document.getElementById("run-btn").disabled = false;
|
document.getElementById("run-btn").disabled = false;
|
||||||
|
// 显示 LLM 角色面板
|
||||||
|
document.getElementById("llm-assignment-panel").hidden = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
|
|
||||||
// 触发评估并开始轮询。
|
// 触发评估:先 apply profiles(若选了),再触发任务。
|
||||||
async trigger() {
|
async trigger() {
|
||||||
if (!Runner.selectedScenario) return;
|
if (!Runner.selectedScenario) return;
|
||||||
const runBtn = document.getElementById("run-btn");
|
const runBtn = document.getElementById("run-btn");
|
||||||
@@ -85,15 +109,41 @@ const Runner = {
|
|||||||
Runner._setStatus(statusBadge, "queued");
|
Runner._setStatus(statusBadge, "queued");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Step 1: apply LLM profiles to YAML if any selected
|
||||||
|
await Runner._applyProfilesIfNeeded(logBox);
|
||||||
|
|
||||||
|
// Step 2: trigger evaluation
|
||||||
const resp = await API.triggerEvaluation(Runner.selectedScenario);
|
const resp = await API.triggerEvaluation(Runner.selectedScenario);
|
||||||
Runner.poll(resp.task_id);
|
Runner.poll(resp.task_id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Runner._setStatus(statusBadge, "failed");
|
Runner._setStatus(statusBadge, "failed");
|
||||||
logBox.textContent = `触发失败:${err.message}`;
|
logBox.textContent = (logBox.textContent ? logBox.textContent + "\n" : "") + `触发失败:${err.message}`;
|
||||||
runBtn.disabled = false;
|
runBtn.disabled = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 如果用户选了 profile,就先 apply 写回 YAML
|
||||||
|
async _applyProfilesIfNeeded(logBox) {
|
||||||
|
const judgeId = document.getElementById("role-judge").value;
|
||||||
|
const answerId = document.getElementById("role-answer").value;
|
||||||
|
const datasetId = document.getElementById("role-dataset").value;
|
||||||
|
|
||||||
|
if (!judgeId && !answerId && !datasetId) return; // 全空,跳过
|
||||||
|
|
||||||
|
logBox.textContent = "正在将 LLM 配置写入场景文件…\n";
|
||||||
|
const body = {
|
||||||
|
scenario_path: Runner.selectedScenario,
|
||||||
|
judge_profile_id: judgeId || null,
|
||||||
|
answer_profile_id: answerId || null,
|
||||||
|
dataset_profile_id: datasetId || null,
|
||||||
|
};
|
||||||
|
const result = await API.applyProfiles(body);
|
||||||
|
const fields = (result.patched_fields || []).join(", ");
|
||||||
|
logBox.textContent += fields
|
||||||
|
? `✓ 已更新字段:${fields}\n`
|
||||||
|
: "(未找到可更新的字段,继续运行)\n";
|
||||||
|
},
|
||||||
|
|
||||||
// 周期性轮询任务状态,刷新日志与徽标。
|
// 周期性轮询任务状态,刷新日志与徽标。
|
||||||
poll(taskId) {
|
poll(taskId) {
|
||||||
const logBox = document.getElementById("task-log");
|
const logBox = document.getElementById("task-log");
|
||||||
|
|||||||
Reference in New Issue
Block a user