// Cost Breakdown — drill-down for a single run. const { useState: useStateC, useEffect: useEffectC } = React; // ── Phase grouping ───────────────────────────────────────────────── // Phases that share a common prefix are collapsed into a group row. const PHASE_GROUP_PREFIXES = [ "Bullets Generation", "Novelty Embedding Evaluation", "Novelty Search", "Entity Grounding Check", "Relevance Score", "Concept Search", ]; function getGroupKey(label) { for (const prefix of PHASE_GROUP_PREFIXES) { if (label.startsWith(prefix) && label.length > prefix.length) return prefix; } return null; } function buildPhaseGroups(phases) { const order = []; const byKey = {}; phases.forEach(p => { const key = getGroupKey(p.label); if (key) { if (!byKey[key]) { byKey[key] = { type: "group", key, label: key, items: [], total: 0, llm: 0, embed: 0, api: 0, calls: 0, chunks: 0, requests: 0 }; order.push(byKey[key]); } const g = byKey[key]; g.items.push(p); g.total += p.total; g.llm += p.llm; g.embed += p.embed; g.api += p.api; g.calls += p.calls; g.chunks += p.chunks; g.requests += p.requests; } else { order.push({ type: "single", data: p }); } }); const grand = order.reduce((s, x) => s + (x.type === "group" ? x.total : x.data.total), 0); order.forEach(x => { if (x.type === "group") x.percent = grand > 0 ? (x.total / grand) * 100 : 0; }); return { rows: order, grand }; } function PhaseRow({ p, phaseMax, indent = false }) { return (
{p.label} ${p.total.toFixed(4)} {p.percent.toFixed(1)}%
{p.calls > 0 && {p.calls} LLM calls} {p.requests > 0 && {p.requests} API requests} {p.chunks > 0 && {p.chunks} chunks retrieved}
); } // Extract the sub-operation name from a phase label given its group prefix. // e.g. prefix="Novelty Search", label="Novelty Search Parse 9 Attempt0" → "Parse" // Returns null if the remainder is only a number (no meaningful sub-type). function getSubKey(prefix, label) { const rest = label.slice(prefix.length).trim(); const m = rest.match(/^([A-Za-z][A-Za-z\s]*?)(?=\s+\d|\s*$)/); const key = m ? m[1].trim() : ""; return key || null; } function buildSubGroups(groupPrefix, items) { const order = []; const byKey = {}; let hasSubKeys = false; items.forEach(p => { const key = getSubKey(groupPrefix, p.label); if (key) { hasSubKeys = true; if (!byKey[key]) { byKey[key] = { key, label: key, items: [], total: 0, llm: 0, embed: 0, api: 0, calls: 0, chunks: 0, requests: 0, percent: 0 }; order.push(byKey[key]); } const sg = byKey[key]; sg.items.push(p); sg.total += p.total; sg.llm += p.llm; sg.embed += p.embed; sg.api += p.api; sg.calls += p.calls; sg.chunks += p.chunks; sg.requests += p.requests; } else { order.push({ key: p.id, single: p }); } }); if (!hasSubKeys) return null; // no sub-grouping needed const grand = order.reduce((s, x) => s + (x.single ? x.single.total : x.total), 0); order.forEach(x => { if (!x.single) x.percent = grand > 0 ? (x.total / grand) * 100 : 0; }); return order; } function SubGroupRow({ sg, phaseMax }) { const [open, setOpen] = useStateC(false); const isSingle = sg.items.length === 1; return (
${sg.total.toFixed(4)} {sg.percent.toFixed(1)}%
{sg.calls > 0 && {sg.calls} LLM calls} {sg.requests > 0 && {sg.requests} API requests} {sg.chunks > 0 && {sg.chunks} chunks}
{open && (
{sg.items.map(p => )}
)}
); } function GroupRow({ g, phaseMax }) { const [open, setOpen] = useStateC(false); const subGroups = React.useMemo(() => buildSubGroups(g.key, g.items), [g.key, g.items]); return (
${g.total.toFixed(4)} {g.percent.toFixed(1)}%
{g.calls > 0 && {g.calls} LLM calls} {g.requests > 0 && {g.requests} API requests} {g.chunks > 0 && {g.chunks} chunks retrieved}
{open && (
{subGroups ? subGroups.map(x => x.single ? : ) : g.items.map(p => ) }
)}
); } function CostView({ tweaks, appCostData, appEntityRuns }) { const COMPANIES = window.DATA?.companies || []; const initial = appCostData ?? window.EXTRAS.cost; const defaultEntityId = initial?.entityId || COMPANIES[0]?.id || ""; const [costData, setCostData] = useStateC(initial); const [selectedRun, setSelectedRun] = useStateC(initial?.runId || null); const [pickEntityId, setPickEntityId] = useStateC(defaultEntityId); const [entityRuns, setEntityRuns] = useStateC(appEntityRuns || []); const [loading, setLoading] = useStateC(false); const [loadingRuns, setLoadingRuns] = useStateC(false); const [error, setError] = useStateC(null); function fetchEntityRuns(entityId, options = {}) { const autoLoadFirst = Boolean(options.autoLoadFirst); if (!entityId) { setEntityRuns([]); return Promise.resolve(); } setLoadingRuns(true); setError(null); return fetch(`/api/frontend/cost/runs-by-entity/${encodeURIComponent(entityId)}`) .then(r => r.json()) .then(data => { const runs = Array.isArray(data.runs) ? data.runs : []; setEntityRuns(runs); if (autoLoadFirst) { if (!runs.length) { setError("No pipeline runs for this company."); } else { const pick = runs.find(x => x.hasMetrics) || runs[0]; if (pick.hasMetrics) { return loadBreakdown(pick.runId); } setError("No cost metrics stored for this company’s runs yet."); } } return undefined; }) .catch(e => { setError(String(e)); setEntityRuns([]); }) .finally(() => setLoadingRuns(false)); } function loadBreakdown(runId) { setLoading(true); setError(null); const q = runId ? `?run_id=${encodeURIComponent(runId)}` : ""; return fetch(`/api/frontend/cost/breakdown${q}`) .then(r => r.json()) .then(data => { if (data.error && !data.breakdown) { setError(data.error === "no_metrics" ? "No cost metrics for this run." : data.error); setCostData(null); return; } if (data.breakdown) { setCostData(data.breakdown); setSelectedRun(data.breakdown.runId); setPickEntityId(data.breakdown.entityId); fetchEntityRuns(data.breakdown.entityId, { autoLoadFirst: false }); } else { setCostData(null); } }) .catch(e => setError(String(e))) .finally(() => setLoading(false)); } useEffectC(() => { if (appCostData && appEntityRuns?.length) return; loadBreakdown(initial?.runId || null); }, []); function onCompanyChange(entityId) { setPickEntityId(entityId); fetchEntityRuns(entityId, { autoLoadFirst: true }); } function onRunChange(runId8) { if (runId8) loadBreakdown(runId8); } const C = costData; const recentList = (C && C.recentForBreakdown) ? C.recentForBreakdown : []; if (loading && !C) { return (
Loading cost data…
); } if (!C) { return (

No cost metrics available yet. Run the pipeline to populate runs.

{error &&

{error}

}
); } const llmTotal = C.llmModels.reduce((s, m) => s + m.cost, 0); const phaseMax = Math.max(...C.phases.map(p => p.total), 0.0001); const { rows: phaseRows } = buildPhaseGroups([...C.phases].sort((a, b) => b.total - a.total)); return (
← Activity log
Cost forensics · run {C.runId}

{C.entityName} · {_tk(C.ticker)}

{C.entityId} · {C.windowStart.slice(0, 10)} → {C.windowEnd.slice(0, 10)} · · {C.durationSec}s {loading && · updating…}
Compute tokens cost
${C.summary.llm.toFixed(4)}
{C.llmModels.length} models · {C.llmModels.reduce((s, m) => s + m.calls, 0)} calls
Embeddings cost
${C.summary.embeddings.toFixed(4)}
{C.summary.embeddingTokens.toLocaleString()} tokens · {C.summary.embeddingModel}
Grounding tokens cost*
${C.summary.apiChunks.toFixed(4)}
{C.summary.chunksTotal} chunks × ${C.summary.chunkRate}
Total
${C.summary.total.toFixed(4)}
${(C.summary.total / Math.max(C.durationSec, 1) * 60).toFixed(4)} per minute of runtime
{/* Disclaimer (Change 6) */}
*Note: The Grounding Token cost does not take into account the data licences.

Compute tokens — by model

{C.llmModels.length} models · ${llmTotal.toFixed(4)} total
{[...C.llmModels].sort((a, b) => b.cost - a.cost).map(m => { const pct = llmTotal > 0 ? (m.cost / llmTotal) * 100 : 0; return ( ); })}
Model Role Calls Input tkn Output tkn Cost % of Compute
{m.model} {m.role} {m.calls} {m.promptTokens.toLocaleString()} {m.completionTokens.toLocaleString()} ${m.cost.toFixed(4)}
{pct.toFixed(1)}%

By pipeline phase

Where the dollars actually went
{phaseRows.map((row, i) => row.type === "group" ? : )}
Compute tokens Embeddings Grounding tokens
); } window.CostView = CostView;