Token Counter (GGUF)
Know Your Budget Before You Blow the Context
- config
- token_count
- char_count
- info
Every GGUF LLM in your graph has a context window, and the usual way to find out you've blown it is mid-generation - the model starts forgetting your system prompt or the reply gets cut off at max_tokens. Token Counter counts your tokens before you generate, with no model load and no VRAM, so you can budget a prompt against a model's n_ctx like an adult instead of discovering it by accident.
How it counts without loading the model
The trick is a vocab-only load. It uses the same worker as the pack's Local LLM (GGUF) node, but loads just the tokenizer - no weights, no VRAM, no forward pass. If a model with the same path is already loaded for generation, it reuses that instead, so counting never disturbs a warm model and never kicks one out.
You wire a config (only its model is used - the tokenizer) and a text (type it or wire a STRING in). Outputs are token_count, char_count, and an info line like 42 tokens · 180 chars. There's also a per-node unload_after_run selector - config default follows the Settings node, unload after run frees VRAM, keep loaded stays warm - same as the other config-driven LLM nodes in the pack.
Why you'll want it
This is the honest answer to "does my prompt fit?" - and it's a different number from character count, which is the trap. A long English prompt and a long tag-soup prompt tokenize very differently, and every model's tokenizer splits things its own way. Token Counter uses the actual tokenizer for the model in your config, so the number you get is the number the model will spend. Feed that into a budget check, or pair it with the pack's Context Sizer (GGUF) when you want the full request sized (prompt + images + max_tokens + margin) and a suggested n_ctx back.
Where people get burned: counting with a different model's tokenizer and assuming it's close. Tokenizers vary enough that a 180-char prompt can be 42 tokens on one model and 60 on another. Always count against the model you're actually running. And remember this counts text only - vision tokens are the model's job to add, and they're not cheap, which is exactly what Context Sizer exists for.
Install
Part of the Kinburg-Nodes pack, so install is the pack install: ComfyUI Manager (search "Kinburg-Nodes"), or cd ComfyUI/custom_nodes && git clone https://github.com/Kinburg/Kinburg-Nodes, then restart. The LLM nodes need llama-cpp-python (CUDA build) - ComfyUI Manager runs the pack's install.py automatically on install, which matches the wheel to your torch's CUDA version. By hand:
<ComfyUI>/.venv/Scripts/python.exe <ComfyUI>/custom_nodes/Kinburg-Nodes/install.py
If you only use Token Counter and never generate, you still need that install - the tokenizer comes from the same llama-cpp binding. It's a genuinely thin node, but "count tokens with the real tokenizer, zero VRAM" is a job nothing in core ComfyUI does.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| config | KINBURG_LLM_CONFIG | A 'Local LLM Settings (GGUF)' node — only its model is used (for the tokenizer). | |
| text | STRING | Text to tokenize (type here or wire a STRING in). | |
| unload_after_runopt | COMBO | config default | Free the model from VRAM after THIS node runs, without touching the shared config. 'config default' follows the Settings node; 'unload after run' frees VRAM (a different model runs next); 'keep loaded' stays warm (the same model counts and then works). |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| token_count | INT | — |
| char_count | INT | — |
| info | STRING | — |