feat(webapp): add optimization advice section to report UI

- index.html: add section ⑤ advice block (hidden by default, shown when advice_markdown present)
- report.js: add renderAdvice() called in render(), simple Markdown→HTML converter
- app.js: add noise_sensitivity / factual_correctness / semantic_similarity to shortMetric map
- app.css: add .advice-panel, .advice-badge, .advice-md styles (purple left-border theme)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-16 17:26:37 +08:00
parent 91c0dab4f9
commit 1a2cc534b8
4 changed files with 72 additions and 2 deletions

View File

@@ -301,3 +301,27 @@ table.group-table td { border-bottom: 1px solid #f1f5f9; font-variant-numeric: t
.llm-role-row { display: flex; align-items: center; gap: 14px; }
.llm-role-label { font-size: 13px; font-weight: 600; min-width: 180px; color: var(--ink); }
.llm-role-select { min-width: 240px; }
/* ---------- ⑤ 优化建议面板 ---------- */
.advice-panel { border-left: 3px solid #7c3aed; }
.advice-header {
display: flex; align-items: center; gap: 10px;
margin-bottom: 14px;
}
.advice-badge {
background: #7c3aed; color: #fff;
font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
padding: 3px 8px; border-radius: 4px; text-transform: uppercase;
}
.advice-model { font-size: 12px; color: var(--slate); }
.advice-body { line-height: 1.7; color: var(--ink); }
.advice-md h1 { font-size: 16px; font-weight: 700; margin: 16px 0 8px; color: var(--ink); }
.advice-md h2 {
font-size: 14px; font-weight: 700; margin: 20px 0 8px;
padding-bottom: 4px; border-bottom: 1px solid var(--line); color: var(--ink-soft);
}
.advice-md h3 { font-size: 13px; font-weight: 600; margin: 12px 0 6px; color: var(--slate); }
.advice-md hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }
.advice-md ul { padding-left: 20px; margin: 6px 0; }
.advice-md li { margin: 3px 0; font-size: 13px; }
.advice-md strong { color: var(--ink); font-weight: 600; }

View File

@@ -135,6 +135,18 @@
<!-- ④ 最低分样本逐条复核 -->
<div class="section-label">④ 最低分样本(点击展开逐条复核)</div>
<div class="lowest-table" id="lowest-table"></div>
<!-- ⑤ 优化建议optimization_advisor: true 时显示) -->
<div id="advice-section" hidden>
<div class="section-label">⑤ 优化建议 OPTIMIZATION ADVICE</div>
<div class="panel advice-panel">
<div class="advice-header">
<span class="advice-badge">AI 诊断报告</span>
<span class="advice-model" id="advice-model-label"></span>
</div>
<div class="advice-body" id="advice-body"></div>
</div>
</div>
</div>
</section>

View File

@@ -119,6 +119,9 @@ const App = {
answer_relevancy: "ans.rel.",
context_recall: "ctx.recall",
context_precision: "ctx.prec.",
noise_sensitivity: "noise.sens.",
factual_correctness: "fact.corr.",
semantic_similarity: "sem.sim.",
};
return map[name] || name;
},

View File

@@ -26,6 +26,7 @@ const Report = {
Report.renderDistribution(detail.report);
Report.renderGroupings(detail.report);
Report.renderLowest(detail.report);
Report.renderAdvice(detail.summary, detail.report);
content.style.opacity = "1";
} catch (err) {
empty.hidden = false;
@@ -186,8 +187,7 @@ const Report = {
},
// ④ 最低分样本逐条复核表(点击展开)。
renderLowest(report) {
const wrap = document.getElementById("lowest-table");
renderLowest(report) { const wrap = document.getElementById("lowest-table");
const samples = report.lowest_samples || [];
wrap.innerHTML = "";
if (samples.length === 0) {
@@ -255,4 +255,35 @@ const Report = {
</div>
`;
},
// ⑤ 优化建议(仅 optimization_advice.md 存在时渲染)。
renderAdvice(summary, report) {
const section = document.getElementById("advice-section");
const body = document.getElementById("advice-body");
const modelLabel = document.getElementById("advice-model-label");
const md = report.advice_markdown || "";
if (!md.trim()) {
section.hidden = true;
return;
}
section.hidden = false;
modelLabel.textContent = summary.judge_model ? `judge: ${summary.judge_model}` : "";
// 简单 Markdown → HTML 转换(标题、列表、分隔线、粗体)
const escaped = md
.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
const html = escaped
.replace(/^#{3}\s+(.+)$/gm, "<h3>$1</h3>")
.replace(/^#{2}\s+(.+)$/gm, "<h2>$1</h2>")
.replace(/^#{1}\s+(.+)$/gm, "<h1>$1</h1>")
.replace(/^---+$/gm, "<hr>")
.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
.replace(/^- (.+)$/gm, "<li>$1</li>")
.replace(/(<li>[^]*?<\/li>\n?)+/g, (m) => `<ul>${m}</ul>`)
.replace(/\n\n+/g, "\n<br>\n");
body.innerHTML = `<div class="advice-md">${html}</div>`;
},
};