Embedding Analyzer
Finally, a Look Inside the HunyuanVideo Black Box
- analysis_results
- visualization
The one-line pitch
This is the analysis half of the fblissjr/ComfyUI-EmbeddingPipelineAnalytics pack. Feed it a run_id captured by EmbeddingPipelineCapture and it tells you what's actually going on inside those prompt embeddings: basic statistics, a dimensionality-reduction scatter plot (UMAP, PCA, or t-SNE), and - if you point it at a second run - a cosine-similarity number saying how alike the two prompts were in embedding space. It's the closest thing HunyuanVideo prompt engineers have to an x-ray.
Why you'd reach for it
HunyuanVideo's text encoder is a closed box between your prompt and the sampler. This node is the pack's stated answer to that: "for a given target generation, what captions need to be added, left out, expanded, reordered…" - the workflow being, capture a run with a prompt that worked and one that didn't, then compare their embeddings and see where the two diverge. It's also genuinely handy if you're building prompt datasets or sanity-checking whether a LoRA's training captions actually occupy a similar region of embedding space to the prompts you generate with. Keep your expectations calibrated: it's an early-stage node from a solo dev, so you get numbers and a matplotlib scatter, not a pretty dashboard.
How it works
It pulls the run back from the pack's data store on disk - which means you can analyze a run in a different session than the one that captured it, as long as the data/ folder survived. For every stage it always computes mean/std/min/max/shape per embedding tensor. If you pick umap, pca, or tsne, it flattens each tensor to 2D and reduces it, then renders a matplotlib scatter (one subplot per stage) that it both saves to your output_path as a PNG and returns as an IMAGE you can preview right in the graph. If you set compare_run_id, it also reports cosine similarity between the two runs' mean embeddings per stage - high similarity means your prompt change barely moved the needle, which is itself useful information.
The inputs that matter
- run_id - required. Must exactly match a run captured by EmbeddingPipelineCapture; nothing happens without it.
- analysis_type - the menu:
umap,pca,tsne, orstatistics. Start withpca: it's fast and deterministic. UMAP is the pretty one but it's stochastic (re-running gives slightly different plots) and slow, because it's fitting on raw tensor data with default settings. t-SNE is the classic but finicky. - compare_run_id - optional; a second captured run to diff against. Leave blank for a single-run analysis.
- output_path - where the PNG gets saved (default
embedding_analysis). Cosmetic if you only care about the IMAGE output.
Outputs: analysis_results (a STRING of pretty-printed JSON with per-stage stats, reduced coordinates, and any comparison similarity) and visualization (IMAGE - wire it to a Preview Image node).
Installing it
Same pack as the capture node - ComfyUI Manager (search "ComfyUI-EmbeddingPipelineAnalytics") or:
cd ComfyUI/custom_nodes
git clone https://github.com/fblissjr/ComfyUI-EmbeddingPipelineAnalytics
then restart. No models to download. Heavy lifting is in requirements.txt: umap-learn (pulls numba + llvmlite), scikit-learn, matplotlib, pandas - the first install is slow, afterwards it's fine.
Gotchas
- You need the capture node first. No captured run, no analysis. This node is pointless in a graph by itself.
statisticsmode produces no scatter data, so the visualization comes back as empty axes. Pick it for the JSON numbers, not the picture.- The config trap: the capture node resolves its own
config.json, but the analyzer reads a relativeconfig.jsonfrom ComfyUI's working directory. If ComfyUI throws a FileNotFoundError aboutconfig.jsonthe moment you add this node, that's why - there needs to be a config.json reachable from the launch directory. - Because the data store lives in the
data/folder relative to where ComfyUI was launched, renaming or moving that folder orphans every run_id. - The README's bigger ambitions (parquet/jsonl output, LLM-powered interpretation) are future work. Today you get this node and its sibling capture node, and that's the whole pack.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| run_id | STRING | — | |
| analysis_type | COMBO | 4 options: umap, pca, tsne, statistics | |
| config_path | STRING | config.json | — |
| compare_run_idopt | STRING | — | |
| output_pathopt | STRING | embedding_analysis | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| analysis_results | STRING | — |
| visualization | IMAGE | — |