Litzy619's picture
Upload Cosmos3 latent reasoning probe
45442d3 verified
Raw
History Blame Contribute Delete
18.5 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cosmos3 Latent Reasoning Probe</title>
<style>
:root {
color-scheme: light;
--bg: #f7f7f4;
--panel: #ffffff;
--text: #222222;
--muted: #6f6f67;
--line: #d8d8ce;
--accent: #0b6b57;
--soft: #eef3ef;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: var(--bg);
color: var(--text);
}
header {
padding: 28px 32px 18px;
border-bottom: 1px solid var(--line);
background: var(--panel);
}
h1 {
margin: 0 0 8px;
font-size: 28px;
line-height: 1.2;
letter-spacing: 0;
}
.subtitle {
margin: 0;
color: var(--muted);
max-width: 920px;
line-height: 1.45;
}
main {
display: grid;
grid-template-columns: minmax(280px, 360px) minmax(0, 1fr);
gap: 18px;
padding: 18px;
}
aside, section {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
}
aside {
padding: 16px;
align-self: start;
position: sticky;
top: 12px;
max-height: calc(100vh - 24px);
overflow: auto;
}
section {
padding: 16px;
min-width: 0;
}
label {
display: block;
color: var(--muted);
font-size: 12px;
margin: 12px 0 6px;
text-transform: uppercase;
}
select, input, textarea, button {
width: 100%;
min-height: 36px;
border: 1px solid var(--line);
border-radius: 6px;
background: #fff;
color: var(--text);
padding: 6px 8px;
font-size: 14px;
}
textarea {
min-height: 84px;
resize: vertical;
font-family: inherit;
line-height: 1.4;
}
button {
cursor: pointer;
background: var(--accent);
color: #fff;
border-color: var(--accent);
font-weight: 650;
}
button.secondary {
background: #fff;
color: var(--accent);
}
.manual-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 10px;
}
.manual-actions {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
margin-top: 12px;
}
.status {
color: var(--muted);
font-size: 12px;
margin-top: 8px;
min-height: 18px;
}
#videoList {
min-height: 240px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
}
video {
width: 100%;
max-height: 62vh;
background: #111;
border-radius: 6px;
border: 1px solid var(--line);
}
.badges {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 12px 0;
}
.badge {
background: var(--soft);
color: #173b32;
border: 1px solid #c9d8d0;
border-radius: 999px;
padding: 5px 9px;
font-size: 12px;
}
.grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
margin-top: 12px;
}
.block {
border-top: 1px solid var(--line);
padding-top: 12px;
min-width: 0;
}
.block.full { grid-column: 1 / -1; }
h2 {
margin: 0 0 6px;
font-size: 15px;
line-height: 1.35;
}
pre {
margin: 0;
white-space: pre-wrap;
overflow-wrap: anywhere;
background: #fbfbf9;
border: 1px solid var(--line);
border-radius: 6px;
padding: 10px;
max-height: 360px;
overflow: auto;
font-size: 12px;
line-height: 1.45;
}
.scores {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px;
margin: 12px 0;
}
.score {
background: #fbfbf9;
border: 1px solid var(--line);
border-radius: 6px;
padding: 8px;
}
.score span {
display: block;
color: var(--muted);
font-size: 11px;
margin-bottom: 3px;
}
.score strong { font-size: 15px; }
@media (max-width: 900px) {
main { grid-template-columns: 1fr; }
aside { position: static; max-height: none; }
.grid, .scores, .manual-grid, .manual-actions { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header>
<h1>Cosmos3 Latent Reasoning Probe</h1>
<p class="subtitle">Clean, corrupted, and corrective prompt variants for inspecting whether Cosmos3 video generation recovers from language-space physical errors.</p>
</header>
<main>
<aside>
<label for="benchmarkFilter">Benchmark</label>
<select id="benchmarkFilter"></select>
<label for="conditionFilter">Condition</label>
<select id="conditionFilter"></select>
<label for="errorFilter">Error type</label>
<select id="errorFilter"></select>
<label for="videoList">Video</label>
<select id="videoList" size="14"></select>
</aside>
<section>
<video id="video" controls playsinline></video>
<div class="badges" id="badges"></div>
<div class="scores" id="scores"></div>
<div class="grid">
<div class="block full">
<h2>Original Prompt</h2>
<pre id="original"></pre>
</div>
<div class="block">
<h2>Automatic Evaluation</h2>
<pre id="evaluation"></pre>
</div>
<div class="block full">
<h2>Manual Evaluation</h2>
<p class="subtitle">Mark only whether this video is a world-prior success. Saved in this browser; export JSONL/CSV after labeling.</p>
<div class="manual-grid">
<div>
<label for="manualWorldPrior">World-prior success?</label>
<select id="manualWorldPrior"></select>
</div>
</div>
<div class="manual-actions">
<button id="saveManual">Save Current</button>
<button id="clearManual" class="secondary">Clear Current</button>
<button id="exportJsonl" class="secondary">Export JSONL</button>
<button id="exportCsv" class="secondary">Export CSV</button>
</div>
<div id="manualStatus" class="status"></div>
</div>
<div class="block">
<h2>Metadata</h2>
<pre id="metadata"></pre>
</div>
<div class="block">
<h2>Clean Upsampled Prompt</h2>
<pre id="clean"></pre>
</div>
<div class="block">
<h2>Generation Prompt</h2>
<pre id="generation"></pre>
</div>
</div>
</section>
</main>
<script>
let items = [];
let filtered = [];
let manualReviews = {};
const REVIEW_STORAGE_KEY = "cosmos3_reasoning_probe_manual_reviews_v1";
const ids = [
"benchmarkFilter", "conditionFilter", "errorFilter", "videoList", "video",
"badges", "scores", "original", "evaluation", "metadata", "clean", "generation",
"manualWorldPrior", "saveManual", "clearManual", "exportJsonl", "exportCsv",
"manualStatus"
];
const el = Object.fromEntries(ids.map((id) => [id, document.getElementById(id)]));
function pretty(value) {
if (value === null || value === undefined || value === "") return "";
if (typeof value === "string") {
try { value = JSON.parse(value); } catch (_) { return value; }
}
return JSON.stringify(value, null, 2);
}
function unique(field) {
const values = [...new Set(items.map((item) => item[field]).filter(Boolean).map(String))].sort();
return ["All", ...values];
}
function fillSelect(select, values) {
select.innerHTML = "";
for (const value of values) {
const option = document.createElement("option");
option.value = value;
option.textContent = value;
select.appendChild(option);
}
}
function fillManualControls() {
const tri = ["", "true", "false", "unclear"];
fillSelect(el.manualWorldPrior, tri);
}
function parseTriState(value) {
if (value === "true") return true;
if (value === "false") return false;
if (value === "unclear") return "unclear";
return null;
}
function triStateToValue(value) {
if (value === true) return "true";
if (value === false) return "false";
if (value === "unclear") return "unclear";
return "";
}
function itemKey(item) {
return [
item.file || "",
item.output_stem || "",
item.seed ?? "",
item.num_inference_steps ?? "",
].join("::");
}
function loadManualReviews() {
try {
manualReviews = JSON.parse(localStorage.getItem(REVIEW_STORAGE_KEY) || "{}");
} catch (_) {
manualReviews = {};
}
}
function persistManualReviews() {
localStorage.setItem(REVIEW_STORAGE_KEY, JSON.stringify(manualReviews));
}
function currentItem() {
if (!filtered.length) return null;
return filtered[Number(el.videoList.value || 0)] || null;
}
function setManualStatus(text) {
el.manualStatus.textContent = text;
}
function loadManualForm(item) {
const review = item ? manualReviews[itemKey(item)] : null;
const manual = review?.manual || {};
el.manualWorldPrior.value = triStateToValue(manual.world_prior_success_signal);
setManualStatus(review ? `Loaded saved manual review from ${review.updated_at}.` : "No manual review saved for this video.");
}
function buildManualReview(item) {
const evaluation = item.evaluation || {};
return {
review_key: itemKey(item),
updated_at: new Date().toISOString(),
row_number: item.row_number,
benchmark: item.benchmark,
source_index: item.source_index,
condition: item.condition,
error_type: item.error_type,
seed: item.seed ?? null,
num_inference_steps: item.num_inference_steps ?? null,
file: item.file,
output_stem: item.output_stem,
original_prompt: item.original_prompt || "",
expected_physical_outcome: item.expected_physical_outcome || "",
withheld_physical_law: item.withheld_physical_law || "",
target_violation: item.target_violation || "",
auto_evaluation: evaluation,
manual: {
world_prior_success_signal: parseTriState(el.manualWorldPrior.value),
},
};
}
function saveCurrentManualReview() {
const item = currentItem();
if (!item) return;
const review = buildManualReview(item);
manualReviews[review.review_key] = review;
persistManualReviews();
setManualStatus(`Saved manual review at ${review.updated_at}. Total saved: ${Object.keys(manualReviews).length}.`);
renderItem(item);
}
function clearCurrentManualReview() {
const item = currentItem();
if (!item) return;
delete manualReviews[itemKey(item)];
persistManualReviews();
loadManualForm(item);
renderItem(item);
}
function downloadText(filename, text, mime) {
const blob = new Blob([text], {type: mime});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
link.remove();
URL.revokeObjectURL(url);
}
function exportManualJsonl() {
const rows = Object.values(manualReviews);
const text = rows.map((row) => JSON.stringify(row)).join("\n") + (rows.length ? "\n" : "");
downloadText("cosmos3_manual_reviews.jsonl", text, "application/jsonl");
setManualStatus(`Exported ${rows.length} manual reviews as JSONL.`);
}
function csvCell(value) {
if (value === null || value === undefined) return "";
const text = typeof value === "string" ? value : JSON.stringify(value);
return `"${text.replaceAll('"', '""')}"`;
}
function exportManualCsv() {
const rows = Object.values(manualReviews);
const header = [
"updated_at", "source_index", "condition", "error_type", "seed",
"num_inference_steps", "manual_world_prior_success_signal",
"auto_world_prior_success_signal", "auto_target_law_violation_present", "file"
];
const lines = [header.join(",")];
for (const row of rows) {
const manual = row.manual || {};
const auto = row.auto_evaluation || {};
lines.push([
row.updated_at,
row.source_index,
row.condition,
row.error_type,
row.seed,
row.num_inference_steps,
manual.world_prior_success_signal,
auto.world_prior_success_signal,
auto.target_law_violation_present,
row.file,
].map(csvCell).join(","));
}
downloadText("cosmos3_manual_reviews.csv", lines.join("\n") + "\n", "text/csv");
setManualStatus(`Exported ${rows.length} manual reviews as CSV.`);
}
function label(item) {
const parts = [
String(item.source_index).padStart(3, "0"),
item.condition,
item.error_type,
];
if (item.seed !== undefined && item.seed !== null) parts.push(`seed ${item.seed}`);
if (item.num_inference_steps !== undefined && item.num_inference_steps !== null) {
parts.push(`step ${item.num_inference_steps}`);
}
return parts.join(" | ");
}
function applyFilters() {
const benchmark = el.benchmarkFilter.value;
const condition = el.conditionFilter.value;
const errorType = el.errorFilter.value;
filtered = items.filter((item) => {
if (benchmark !== "All" && item.benchmark !== benchmark) return false;
if (condition !== "All" && item.condition !== condition) return false;
if (errorType !== "All" && item.error_type !== errorType) return false;
return true;
});
el.videoList.innerHTML = "";
filtered.forEach((item, index) => {
const option = document.createElement("option");
option.value = String(index);
option.textContent = label(item);
el.videoList.appendChild(option);
});
if (filtered.length) {
el.videoList.value = "0";
renderItem(filtered[0]);
} else {
renderEmpty();
}
}
function scoreCard(labelText, value) {
return `<div class="score"><span>${labelText}</span><strong>${value ?? "NA"}</strong></div>`;
}
function renderItem(item) {
const evaluation = item.evaluation || {};
const hasManual = Boolean(manualReviews[itemKey(item)]);
const relativeVideoUrl = `${item.file}?v=${encodeURIComponent(item.asset_version || "1")}`;
el.video.src = item.file_url || relativeVideoUrl;
el.video.load();
el.badges.innerHTML = [
["Benchmark", item.benchmark],
["Source", item.source_index],
["Condition", item.condition],
["Error", item.error_type],
["Seed", item.seed],
["Steps", item.num_inference_steps],
["Injected error", evaluation.injected_error_present],
["Target violation", evaluation.target_law_violation_present],
["World-prior success", evaluation.world_prior_success_signal],
["Manual saved", hasManual],
["Corrected", evaluation.corrected_in_video],
["Black-box signal", evaluation.black_box_correction_signal],
].map(([k, v]) => `<span class="badge">${k}: ${v ?? ""}</span>`).join("");
el.scores.innerHTML = [
scoreCard("Physical plausibility", evaluation.physical_plausibility),
scoreCard("Task completion", evaluation.task_completion),
scoreCard("Object permanence", evaluation.object_permanence),
scoreCard("Contact / support", evaluation.contact_support),
scoreCard("Causal order", evaluation.causal_order),
scoreCard("Confidence", evaluation.confidence),
].join("");
el.original.textContent = item.original_prompt || "";
el.evaluation.textContent = pretty(evaluation);
el.metadata.textContent = pretty({
source_path: item.source_path,
file_url: item.file_url,
seed: item.seed,
num_inference_steps: item.num_inference_steps,
expected_physical_outcome: item.expected_physical_outcome,
target_violation: item.target_violation,
withheld_physical_law: item.withheld_physical_law,
injected_error: item.injected_error,
trajectory_probe: item.trajectory_probe,
seed_sweep: item.seed_sweep,
causal_intervention: item.causal_intervention,
benchmark_metadata: item.metadata,
});
el.clean.textContent = pretty(item.clean_upsampled_prompt);
el.generation.textContent = pretty(item.generation_prompt);
loadManualForm(item);
}
function renderEmpty() {
el.video.removeAttribute("src");
el.badges.textContent = "No videos match the selected filters.";
el.scores.innerHTML = "";
for (const key of ["original", "evaluation", "metadata", "clean", "generation"]) {
el[key].textContent = "";
}
loadManualForm(null);
}
async function main() {
const response = await fetch("metadata.json");
items = await response.json();
loadManualReviews();
fillManualControls();
fillSelect(el.benchmarkFilter, unique("benchmark"));
fillSelect(el.conditionFilter, unique("condition"));
fillSelect(el.errorFilter, unique("error_type"));
for (const select of [el.benchmarkFilter, el.conditionFilter, el.errorFilter]) {
select.addEventListener("change", applyFilters);
}
el.videoList.addEventListener("change", () => {
renderItem(filtered[Number(el.videoList.value)]);
});
el.saveManual.addEventListener("click", saveCurrentManualReview);
el.clearManual.addEventListener("click", clearCurrentManualReview);
el.exportJsonl.addEventListener("click", exportManualJsonl);
el.exportCsv.addEventListener("click", exportManualCsv);
applyFilters();
}
main().catch((error) => {
console.error(error);
el.badges.textContent = `Failed to load metadata: ${error}`;
});
</script>
</body>
</html>