Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/dashboard-external-records.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# External optimization records in the dashboard

A campaign with no candidate/run records is **not connected**, not a successful
comparison. `stages_declared: []` explicitly declares no applicable stages;
omitting the field leaves unobserved stages **not recorded**. Do not set an empty
list merely because a backend has no built-in collector.

For existing Ascend experiments, a caller may adapt their artifacts into native
candidate rows without manufacturing a CUDA run or evaluation. Create
`candidates/<candidate-id>/candidate.json` with `candidate_id`, `title`, and
`external_record_ref: {"path": "records/<record>.json", "sha256": "<sha256>"}`.
Paths are campaign-relative and hashes cover exact file bytes. These candidates
must not also name a harness run. The external record has this shape (illustrative
values only):

```json
{
"schema_version": 1,
"kind": "external_optimization_record",
"candidate_id": "example",
"backend": "ascend",
"protocol": "example-two-service-protocol",
"state": "completed",
"source_refs": [{"path": "sources/result.json", "sha256": "<sha256>"}],
"performance_verdict": "INCONCLUSIVE",
"quality": {"verdict": "NOT_RUN"},
"metrics": [{
"name": "example-tier", "unit": "ms/token",
"baseline": 42, "samples": [40, 38],
"aggregate": 39, "aggregation": "two_round_median", "target": 25
}],
"events": [{"stage": "validation", "time": "2026-01-01T12:00:00Z",
"summary": "Two service records captured; quality not run"}],
"note": "Recorded intermediate measurements, not final acceptance."
}
```

All source references must resolve with matching hashes. No automatic directory
scan or inference of verdicts is performed. Publish immutable content-addressed
source and record files first, then atomically replace candidate metadata. A
partial file, hash mismatch, mismatched candidate or malformed record is withheld;
the UI reports missing evidence rather than an invented success.

This version represents lower-is-better latency metrics; absolute target gaps
are aggregate minus target. Each metric supports a positive parent, up to two positive samples, a positive
aggregate and target; omitted values remain unrecorded. `two_round_median`
requires two samples and their arithmetic midpoint, accepting floating-point
serialization differences with relative tolerance `1e-9` and absolute tolerance
`1e-12` in the metric unit. This is not a measurement/noise tolerance; coarser
rounding must not be used to change a recorded aggregate. The caller value is
preserved. Records without metrics stay in candidate/event views and are counted
in the chart note; no measurement is fabricated. Keep concurrency tiers and
protocols separate. Absolute plots do not establish cross-run comparability.
Performance and quality verdicts remain separate; quality may include `correct`
and `total`. Neither an external PASS nor a source hash promotes a record into
the generic verified gain ranking. Hashes establish bytes, not the correctness
of the caller's mapping, frozen gates, execution, or experimental conclusions.
Only recorded events populate workflow stages. Summaries are explicitly distinct
from a full campaign optimization log; use `campaign log` for that history.

Optional `environment` keys `hardware`, `runtime`, `model`, `workload`, `protocol`
and `source` accept SHA-256 fingerprints for caller-declared identity completeness.
They do not certify comparable experiments. For native harness runs the environment
signature additionally accepts `backend: ascend`: verified device selection with
UUID, name and driver; host platform; target Python and package versions including
`torch`, `vllm`, `torch_npu`, `vllm_ascend`; and
`ascend: {cann_version, firmware_version}`. Existing RunSpec, workload, source and
command comparisons still apply. Missing runtime identity remains unverified.

Collectors and campaign-specific paths, targets and revision pins belong outside
the shared dashboard. Collect existing files read-only, label freshness and
missing history, and preserve failed, partial and running attempts.

Collectors can atomically update campaign metadata with
`collection: {"state": "live" or "stale", "observed_at": "<ISO-8601 timestamp>"}`.
The UI shows this source timestamp separately from the browser's connection to
the dashboard. On collection failure, mark it stale and keep the last complete
source set; a successful HTTP refresh alone does not mean the source is fresh.
4 changes: 4 additions & 0 deletions docs/dashboard.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Offline optimization dashboard

For existing Ascend experiments, see [external optimization records](dashboard-external-records.md)
to connect protocol-specific measurements, verdicts and events without fabricating a harness run.


The dashboard renders a recorded InferRSI run or an explicitly assembled
campaign as a single HTML file. It needs no web service or external assets.
It is a read-only view of recorded data; generating it does not run an
Expand Down
88 changes: 84 additions & 4 deletions src/inferrsi/data/dashboard/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
<div class="var"><span>metric</span><output id="metric-value"></output></div>
</div>
<main>
<div id="integration-note" class="panel panel-body"></div>
<div class="section-title">Overview · all candidates <small id="overview-note"></small></div>
<div id="stats" class="stats" aria-label="Overview statistics"></div>
<div class="section-title">Workflow <small>Technical events only; select a stage to filter candidates and events</small></div>
Expand Down Expand Up @@ -220,6 +221,34 @@
const liveMode = data.live === true;
const byId = id => document.getElementById(id);
const chinese = {
'stages_declared is explicitly empty: undeclared stages mean not applicable, not backend unsupported.':'stages_declared 显式声明为空:未声明的阶段表示不适用,不表示后端不受支持。',
'Source collection':'数据采集',
'live':'已连接',
'stale':'数据陈旧',
'Performance':'性能判定',
'Environment identity':'环境身份',
'protocol_specific':'按协议独立展示',
'Caller-adapted records; hashes check bytes, not experimental validity.':'调用方适配的记录;哈希验证文件字节,不证明实验结论。',
'Protocol-specific absolute measurements; recorded verdicts are not recomputed.':'按协议展示绝对测量值;保留原始判定,不重新裁决。',
'Per metric':'按指标分别查看',
'Recorded performance failures':'已记录的性能未通过',
'Native failed / regressed':'原生运行失败 / 下降',
'Recorded external performance failures':'已记录的外部性能未通过',
'Native runs only; includes failures and rollbacks':'仅统计原生运行,包含失败和回退',
'Independent axes; select a candidate for parent and two rounds':'各指标独立展示;选择候选查看父版本和双轮结果',
'Absolute target gaps appear in candidate details':'候选详情显示各档位距绝对目标的差距',
'Recorded quality passes; see individual results':'已记录的质量通过数;详见各候选',
'Caller verdicts; independent of quality':'记录中的性能判定,与质量判定分开',
'External record summaries; full optimization log not recorded':'外部记录摘要;完整优化日志尚未接入',
'Protocol measurements':'协议指标',
'Parent':'父版本',
'Round 1':'第1轮',
'Round 2':'第2轮',
'Aggregate':'聚合值',
'No comparable measurements':'暂无可比较的测量',
'Data source not connected: add candidate/run records or external_record_ref. Existing files elsewhere are not imported automatically.':'数据源未接入:请添加候选/运行记录或 external_record_ref。其他目录的实验数据不会自动导入。',
'External records connected. Protocol-specific measurements and recorded verdicts are shown separately; generic gain ranking does not validate them.':'外部记录已接入。按原协议展示测量和判定,通用提升排名不替代原协议验收。',

'Language':'语言', 'InferRSI · Optimization dashboard':'InferRSI · 优化看板',
'Dashboards › InferRSI ›':'看板 › InferRSI ›', 'SYNTHETIC DATA':'合成数据',
'READ ONLY · OFFLINE':'只读 · 离线', 'READ ONLY · LIVE':'只读 · 实时', 'Dashboard filters':'看板筛选',
Expand Down Expand Up @@ -357,6 +386,8 @@
if (typeof text !== 'string') return text;
if (language !== 'zh') return text;
if (Object.prototype.hasOwnProperty.call(chinese, text)) return chinese[text];
const protocolPrefix='Protocol-specific absolute measurements; recorded verdicts are not recomputed.';
if(text.startsWith(protocolPrefix+' '))return chinese[protocolPrefix]+' '+text.slice(protocolPrefix.length+1).replace(/(\d+) external record\(s\) have no recorded metrics; see candidate details and events\./,(_,count)=>`${count} 条外部记录未记录指标;请查看候选详情和事件。`);
const temporalPrefix='Terminal events place results; stage dots are events, not durations.';
if(text.startsWith(`${temporalPrefix} `)) {
return chinese[temporalPrefix] + ' ' + text.slice(temporalPrefix.length+1)
Expand Down Expand Up @@ -463,7 +494,8 @@
}
const stageNames = {diagnosis:'Diagnosis', knowledge:'Knowledge', search:'Candidate search', execution:'Execution', validation:'Validation', review:'Review'};
const stageSelect = byId('stage-filter'), runSelect = byId('run-filter'), candidateSelect = byId('candidate-filter');
let selected = null, jumpNotice = '';
let selected = data.candidates.findIndex(r=>r.external?.metrics?.length), jumpNotice = '';
if(selected<0)selected=null;
const node = (tag, text, cls) => { const el = document.createElement(tag); if (text !== undefined) el.textContent = text; if (cls) el.className = cls; return el; };
const narrativeNode = (tag, text, cls) => {const el=node(tag,text,cls);el.setAttribute('data-narrative','');return el;};
const clear = el => { while (el.firstChild) el.removeChild(el.firstChild); };
Expand Down Expand Up @@ -496,17 +528,44 @@
(candidateSelect.value === '' || index === Number(candidateSelect.value)) &&
(!stageSelect.value || row.events.some(event => event.stage === stageSelect.value)));
}
function renderIntegration(integration) {
const root=byId('integration-note');clear(root);
const message=integration.state==='not_connected'
? 'Data source not connected: add candidate/run records or external_record_ref. Existing files elsewhere are not imported automatically.'
: integration.external_records ? 'External records connected. Protocol-specific measurements and recorded verdicts are shown separately; generic gain ranking does not validate them.' : '';
if(message)root.appendChild(node('p',message));
if(integration.collection?.observed_at){
const line=node('p');
line.appendChild(node('span','Source collection'));
line.appendChild(node('span',': '));
line.appendChild(node('span',integration.collection.state));
line.appendChild(node('span',' · '+integration.collection.observed_at));
root.appendChild(line);
}
if(integration.stage_declaration==='explicit_empty')root.appendChild(node('p','stages_declared is explicitly empty: undeclared stages mean not applicable, not backend unsupported.'));
root.hidden=!root.firstChild;
}
function renderStats() {
renderIntegration(data.integration || {});
const root=byId('stats'); clear(root); const rows=data.candidates, o=data.overview;
const missing=rows.flatMap(missingRefs).length;
const external=rows.filter(r=>r.external?.metrics), metrics=external.flatMap(r=>r.external.metrics);
const native=rows.filter(r=>!r.external?.metrics);
const figures=[
['Best gain',value(o.best_improvement_pct,'%'),o.comparison_state === 'incompatible' ? 'Incompatible records' : o.comparison_state === 'unverified' ? 'Comparison evidence missing or unsupported' : 'Quality and source checks required','green'],
['Best gain',value(o.best_improvement_pct,'%'),o.comparison_state === 'no_data' ? 'No comparable measurements' : o.comparison_state === 'incompatible' ? 'Incompatible records' : o.comparison_state === 'unverified' ? 'Comparison evidence missing or unsupported' : 'Quality and source checks required','green'],
['Target gap',value(o.target_gap_pct,' pp'),o.target_improvement_pct === null ? 'Target not recorded' : `Target ${value(o.target_improvement_pct,'%')}`,'orange'],
['Candidate / run views',rows.length ? String(rows.length) : 'Not recorded','Recorded candidate or run views',''],
['Within noise',rows.some(r=>['noise','improved','regressed'].includes(r.outcome)) ? String(rows.filter(r => r.outcome === 'noise').length) : 'Not recorded','Uses recorded noise band','orange'],
['Failed / regressed',rows.some(r=>r.state !== 'not_recorded' || r.quality !== 'not_recorded') ? String(rows.filter(r => ['failed','quality_failed','regressed'].includes(r.outcome) || r.decision==='rolled_back').length) : 'Not recorded','Includes failures and rollbacks','red'],
[external.length ? 'Native failed / regressed' : 'Failed / regressed',native.some(r=>r.state !== 'not_recorded' || r.quality !== 'not_recorded') ? String(native.filter(r => ['failed','quality_failed','regressed'].includes(r.outcome) || r.decision==='rolled_back').length) : 'Not recorded',external.length ? 'Native runs only; includes failures and rollbacks' : 'Includes failures and rollbacks','red'],
['Missing evidence',rows.length ? String(missing) : 'Not recorded','See completeness panel','red']
];
if(external.length===rows.length && external.length){
Comment thread
jiangkuaixue123 marked this conversation as resolved.
Resolved
figures[0]=['Protocol measurements',String(metrics.length),'Independent axes; select a candidate for parent and two rounds','green'];
figures[1]=['Target gap','Per metric','Absolute target gaps appear in candidate details','orange'];
figures[3]=['Quality',String(external.filter(r=>r.external.quality_verdict==='PASS').length)+' / '+external.length,'Recorded quality passes; see individual results',''];
figures[4]=['Recorded performance failures',String(external.filter(r=>r.external.performance_verdict==='FAIL').length),'Caller verdicts; independent of quality','red'];
}
if(external.length && native.length)figures.push(['Recorded external performance failures',String(external.filter(r=>r.external.performance_verdict==='FAIL').length),'Caller verdicts; independent of quality','red']);
for(const [label,number,note,colour] of figures){const box=node('div',undefined,'panel stat');box.appendChild(node('div',label,'stat-label'));box.appendChild(node('strong',number,`stat-value ${colour}`));box.appendChild(node('small',note,'hint'));root.appendChild(box);}
byId('overview-note').textContent = data.rounds === null ? 'Rounds not recorded' : `${data.rounds.length} recorded rounds${data.corrupt_round_lines.length ? ` · corrupt lines ${data.corrupt_round_lines.join(', ')}` : ''}`;
}
Expand Down Expand Up @@ -551,6 +610,18 @@
heading.appendChild(node('small','Narrative is caller recorded; verdicts and measurements are separate evidence.'));
root.appendChild(heading);
const grid=node('div',undefined,'insight-grid');root.appendChild(grid);
if(row.external && row.external.protocol){
const e=row.external, box=insight(grid,'Protocol measurements',`${e.backend} · ${e.protocol}`,true);
detailLine(box,'Performance',e.performance_verdict);
detailLine(box,'Quality',e.quality_verdict+(e.quality_total!==null?' · '+measurement(e.quality_correct)+' / '+measurement(e.quality_total):''));
const table=node('table'), header=node('tr');
for(const h of ['Metric','Parent','Round 1','Round 2','Aggregate','Target','Target gap'])header.appendChild(node('th',h));table.appendChild(header);
for(const m of e.metrics){const tr=node('tr');for(const v of [m.name+' ('+m.unit+')',measurement(m.baseline),measurement(m.samples[0]),measurement(m.samples[1]),measurement(m.aggregate),measurement(m.target),m.aggregate!==null&&m.target!==null?measurement(m.aggregate-m.target):'Not recorded'])tr.appendChild(node('td',v));table.appendChild(tr);}box.appendChild(table);
box.appendChild(node('p',e.note));box.appendChild(node('small',e.provenance));
detailLine(box,'Environment identity',e.identity_state);
for(const ref of e.source_refs)box.appendChild(node('code',refText(ref)));
return;
}
const info=row.optimization, context=row.benchmark_context;
const optimization=insight(grid,'Change and rationale','Caller recorded',true);
detailLine(optimization,'Change type',info.kind || 'Not recorded');
Expand Down Expand Up @@ -690,7 +761,7 @@
entry.appendChild(node('pre',Object.keys(event.details).length ? JSON.stringify(event.details,null,2) : translated('No additional structured fields recorded.')));
entry.appendChild(node('code',event.refs.map(refText).join(' | ')));trace.appendChild(entry);
}
if(row.artifacts.tool_calls.state==='missing')item(trace,'MISSING · tool calls',row.artifacts.tool_calls.missing_reason).classList.add('missing-item');
if(row.artifacts.tool_calls?.state==='missing')item(trace,'MISSING · tool calls',row.artifacts.tool_calls.missing_reason).classList.add('missing-item');
if(row.agent_trace_links.unlinked.length)item(trace,'UNLINKED AGENT EVENTS',`Lines ${row.agent_trace_links.unlinked.join(', ')}`).classList.add('missing-item');
if(row.agent_trace_links.mismatched.length)item(trace,'MISMATCHED AGENT EVENTS',`Lines ${row.agent_trace_links.mismatched.join(', ')}`).classList.add('missing-item');
for(const [source,lines] of Object.entries(row.corrupt_event_sources)){if(lines.length)item(trace,`CORRUPT ${source} LINES`,lines.join(', ')).classList.add('missing-item');}
Expand Down Expand Up @@ -838,6 +909,15 @@
function renderStory(){
const root=byId('story');clear(root);const story=data.story||{state:'not_recorded',versions:[]};
const note=byId('story-note');
if(story.state!=='present' && data.candidates.some(r=>r.external?.metrics)){
note.textContent='External record summaries; full optimization log not recorded';
for(const row of data.candidates.filter(r=>r.external?.metrics)){
const box=node('section',undefined,'item');box.appendChild(node('h3',row.title));
box.appendChild(narrativeNode('p',row.external.note || 'Not recorded'));
box.appendChild(node('small',row.external.provenance));root.appendChild(box);
}
return;
}
if(story.state!=='present'){
note.textContent=story.state==='not_applicable'?'Single runs have no campaign log':'Not recorded';
root.appendChild(node('p',story.state==='not_applicable'?'A single run has no optimization log. Record a campaign to explain why each optimization was chosen.':`No usable optimization log (${story.state.replaceAll('_',' ')}). Record one with: inferrsi campaign log --directory <CAMPAIGN> --file <LOG.json>`,'empty'));
Expand Down
Loading
Loading