Summary
Proposal: a new desktop surface that renders an open-weight LLM's HuggingFace modeling_*.py source as an interactive, drill-downable block diagram, bidirectionally synced with the code pane, plus a hyperparameter inspector and a VRAM estimator.
Design reference: LLMForge's 模型架构 (model architecture) feature — screenshots below. This issue proposes borrowing its interaction and information design, re-expressed in TermiPod's existing dark token system (see "Visual-design stance" — explicitly not a palette import).
Why this fits TermiPod
TermiPod is positioning as an agent control plane and workbench. Users running/serving open-weight models through agents (SSH hosts, remote hubs) currently have no in-app way to answer: what is inside this checkpoint, and will it fit on my GPU? A visual architecture reader strengthens the workbench story: inspect a model's real source, navigate its structure, estimate deployment VRAM for the target host — without leaving the app.
Reference (LLMForge)
Three-pane workbench + config inspector:

Canvas drill-down detail (nested layer card, ×N repeat frame, tensor-shape edges, minimap, zoom rail):

What to borrow — interaction & information design
- Three-pane IDE layout — left:
nn.Module hierarchy tree with per-node param counts and search; center: infinite canvas; right: code viewer (代码/笔记 tabs, file breadcrumb). Clicking a graph node scrolls the code to that class; the mapping is bidirectional.
- Drill-down as stacked floating cards — expanding a composite module opens a child card on the canvas (own title bar: breadcrumb + ×N + param total + close), not a page zoom. Keeps parent context visible.
×N repeat-collapse — N identical decoder layers render as ONE framed container with × 61 and an aggregate badge (≈666B). The single most important readability trick for transformer graphs.
- Honest dataflow — tensor shapes on edges (
[B, S, 7168]); residual adds drawn as ⊕ circles, not boxes; auxiliary inputs (Causal Mask, loss) as dashed-gray chips.
- Categorical node colors — pastel-coded by layer kind (Embedding/Norm/Attention/MLP-MoE/RoPE/Linear). See the visual-design stance below for how to adapt this to dark.
- Provenance badge —
解析质量 · 9 实证 · 1 近似 (9 verified / 1 inferred). Every number on screen declares whether it was measured or estimated. Cheap to implement, huge for trust.
- Floating collapsible stat chips over the canvas (
架构 ≈668B, 算力·显存 1244 GiB, 图例) — glanceable totals that expand into detail.
- Inspector panel — sectioned key-value rows (attention/pos-enc/norm/FFN/embedding), a dense mono hyperparameter grid, a layer-schedule strip (per-layer segments colored by type), a param breakdown bar, and batch/context-length chips that recompute VRAM live.
- Canvas furniture — minimap, zoom rail (+/−/fit/fullscreen), layout-direction toggle.
Visual-design stance (patterns, not palette)
Compared against the desktop's current design system (design-tokens/tokens.json + 01-base-shell.css): TermiPod's dark-first, Linear/Radix-grounded language (hairline separation, shadow-less cards, single accent, AA-measured contrast) is the more modern base and should be kept. LLMForge's light surfaces, per-card drop shadows and pastel fills should not be imported.
The one sanctioned extension to the single-accent rule: categorical node colors as dark-theme tints, e.g. fill color-mix(in srgb, <hue> 12–16%, var(--surface)) + 1px hue-tinted border + hue-shifted text, sourced from existing token hues (--color-info, --color-secondary, --color-success, --color-violet, terminal cyan/magenta). Category coding is functional here (6+ layer kinds), which the single accent cannot carry; the tint approach keeps the dark elevation discipline intact.
Proposed implementation architecture
1. Ingestion → graph IR (JSON, cacheable per model+version). Two complementary routes, which is exactly what the provenance badge implies:
- Static: parse the Python AST — class tree → module hierarchy;
forward() body → dataflow edges between submodules. Yields verified structure and the code-sync source spans.
- Numeric: infer shapes/params from
config.json analytically (or optionally run a one-shot torch.fx trace / forward hooks on a dummy input for measured shapes). Anything inferred is flagged approximate.
2. Layout — ELK (elkjs, layered/Sugiyama): proper support for compound/nested graphs, ports, orthogonal edge routing. (@hpcc-js/wasm-graphviz is already shipped and is an acceptable M1 fallback, but it handles compound nesting poorly.) Expanding a card re-layouts only that subgraph.
3. Canvas — React Flow (XYFlow), new dep (~50 kB): custom node components, subflows/containers, minimap, zoom controls and edge labels out of the box. Custom Canvas/WebGL only if node counts exceed ~1–2k.
4. Code pane — CodeMirror (already a dependency), read-only, with sourceSpan ranges for node↔code highlighting.
5. Inspector + VRAM estimator — pure TypeScript arithmetic from config.json per architecture family (MLA/GQA attention, dense/MoE FFN, embeddings): params per layer type; VRAM = weights (params × dtype bytes) + KV cache (layers × kv-heads × head-dim × ctx × batch × bytes) + activation estimate. Config profiles (默认配置 vs overrides) recompute client-side, instant.
Execution location: analysis is a small Python worker (AST extraction, stdlib-only for M1) runnable over SSH on the agent host or as a hub-side job; the IR JSON is cached per (model, version) so re-opens are instant.
Phasing
- M1 — structure: AST module tree (left pane) + ELK-laid-out top-level graph on a React Flow canvas, read-only, one local model dir. Provenance flag on every number from day one.
- M2 — depth: drill-down stacked cards,
×N repeat-collapse, node↔code bidirectional sync, tensor-shape edge labels.
- M3 — inspector: config inspector panel, layer-schedule strip, param breakdown, batch/ctx VRAM estimator with config profiles.
Open questions for the maintainer
- Analysis runtime: ship the Python AST worker for SSH hosts only, or also hub-side for browser-build users?
- React Flow as a new dependency vs. extending the existing
CanvasEditor stack? (React Flow's subflow/minimap primitives map 1:1 to the drill-down design; CanvasEditor is a document canvas, not a graph renderer.)
- Model-family coverage order — deepseek / llama / qwen first (single
modeling_*.py files, well-structured), MoE families later?
- Where does the surface live in the IA: a new surface next to Read, or a mode of the Library?
Non-goals
- No model execution/training integration, no live activation inspection (M-beyond).
- Not a general Netron replacement — scoped to HF
modeling_*.py source reading.
Summary
Proposal: a new desktop surface that renders an open-weight LLM's HuggingFace
modeling_*.pysource as an interactive, drill-downable block diagram, bidirectionally synced with the code pane, plus a hyperparameter inspector and a VRAM estimator.Design reference: LLMForge's 模型架构 (model architecture) feature — screenshots below. This issue proposes borrowing its interaction and information design, re-expressed in TermiPod's existing dark token system (see "Visual-design stance" — explicitly not a palette import).
Why this fits TermiPod
TermiPod is positioning as an agent control plane and workbench. Users running/serving open-weight models through agents (SSH hosts, remote hubs) currently have no in-app way to answer: what is inside this checkpoint, and will it fit on my GPU? A visual architecture reader strengthens the workbench story: inspect a model's real source, navigate its structure, estimate deployment VRAM for the target host — without leaving the app.
Reference (LLMForge)
Three-pane workbench + config inspector:
Canvas drill-down detail (nested layer card, ×N repeat frame, tensor-shape edges, minimap, zoom rail):
What to borrow — interaction & information design
nn.Modulehierarchy tree with per-node param counts and search; center: infinite canvas; right: code viewer (代码/笔记tabs, file breadcrumb). Clicking a graph node scrolls the code to that class; the mapping is bidirectional.×Nrepeat-collapse — N identical decoder layers render as ONE framed container with× 61and an aggregate badge (≈666B). The single most important readability trick for transformer graphs.[B, S, 7168]); residual adds drawn as ⊕ circles, not boxes; auxiliary inputs (Causal Mask, loss) as dashed-gray chips.解析质量 · 9 实证 · 1 近似(9 verified / 1 inferred). Every number on screen declares whether it was measured or estimated. Cheap to implement, huge for trust.架构 ≈668B,算力·显存 1244 GiB,图例) — glanceable totals that expand into detail.Visual-design stance (patterns, not palette)
Compared against the desktop's current design system (
design-tokens/tokens.json+01-base-shell.css): TermiPod's dark-first, Linear/Radix-grounded language (hairline separation, shadow-less cards, single accent, AA-measured contrast) is the more modern base and should be kept. LLMForge's light surfaces, per-card drop shadows and pastel fills should not be imported.The one sanctioned extension to the single-accent rule: categorical node colors as dark-theme tints, e.g. fill
color-mix(in srgb, <hue> 12–16%, var(--surface))+ 1px hue-tinted border + hue-shifted text, sourced from existing token hues (--color-info,--color-secondary,--color-success,--color-violet, terminal cyan/magenta). Category coding is functional here (6+ layer kinds), which the single accent cannot carry; the tint approach keeps the dark elevation discipline intact.Proposed implementation architecture
1. Ingestion → graph IR (JSON, cacheable per model+version). Two complementary routes, which is exactly what the provenance badge implies:
forward()body → dataflow edges between submodules. Yields verified structure and the code-sync source spans.config.jsonanalytically (or optionally run a one-shottorch.fxtrace / forward hooks on a dummy input for measured shapes). Anything inferred is flaggedapproximate.{ "model": "deepseek_v2", "version": "v5.13.1", "nodes": [{ "id": "model.layers.0.self_attn", "kind": "attention", // embedding|norm|attention|mlp|moe|rope|linear|aux "class": "DeepseekV2Attention", "attrs": { "heads": 128, "kv_heads": 128 }, "params": 138000000, "paramsProvenance": "verified", // or "approximate" "repeat": 61, "span": { "file": "modeling_deepseek.py", "start": 812, "end": 1040 }, "children": [ /* nested graph */ ] }], "edges": [{ "from": "…", "to": "…", "shape": "[B,S,7168]", "kind": "residual|data|aux" }] }2. Layout — ELK (
elkjs, layered/Sugiyama): proper support for compound/nested graphs, ports, orthogonal edge routing. (@hpcc-js/wasm-graphvizis already shipped and is an acceptable M1 fallback, but it handles compound nesting poorly.) Expanding a card re-layouts only that subgraph.3. Canvas — React Flow (XYFlow), new dep (~50 kB): custom node components, subflows/containers, minimap, zoom controls and edge labels out of the box. Custom Canvas/WebGL only if node counts exceed ~1–2k.
4. Code pane — CodeMirror (already a dependency), read-only, with
sourceSpanranges for node↔code highlighting.5. Inspector + VRAM estimator — pure TypeScript arithmetic from
config.jsonper architecture family (MLA/GQA attention, dense/MoE FFN, embeddings): params per layer type; VRAM = weights (params × dtype bytes) + KV cache (layers × kv-heads × head-dim × ctx × batch × bytes) + activation estimate. Config profiles (默认配置vs overrides) recompute client-side, instant.Execution location: analysis is a small Python worker (AST extraction, stdlib-only for M1) runnable over SSH on the agent host or as a hub-side job; the IR JSON is cached per (model, version) so re-opens are instant.
Phasing
×Nrepeat-collapse, node↔code bidirectional sync, tensor-shape edge labels.Open questions for the maintainer
CanvasEditorstack? (React Flow's subflow/minimap primitives map 1:1 to the drill-down design; CanvasEditor is a document canvas, not a graph renderer.)modeling_*.pyfiles, well-structured), MoE families later?Non-goals
modeling_*.pysource reading.