Skip to content

Comments

Add optional detailed token counts#4657

Draft
awsr wants to merge 2 commits intovladmandic:devfrom
awsr:detailed-token-counts
Draft

Add optional detailed token counts#4657
awsr wants to merge 2 commits intovladmandic:devfrom
awsr:detailed-token-counts

Conversation

@awsr
Copy link
Contributor

@awsr awsr commented Feb 20, 2026

  • Add option to also show token counts split up by segment markers (BREAK and, if enabled, line break).
    • Detailed display format is `[#, #, #] {sum}/{max_length}"
  • Minor changes:
    • Change "tokenizer busy" state display to "--/--"
    • Add error state display "??/{max_length}"

PR created as draft to await feedback regarding other tokenizers (I don't have any models set up that use different tokenizers, or available free space at the moment).

"sd_textencoder_cache_size": OptionInfo(4, "Text encoder cache size", gr.Slider, {"minimum": 0, "maximum": 16, "step": 1}),
"sd_textencder_linebreak": OptionInfo(True, "Use line break as prompt segment marker", gr.Checkbox),
"diffusers_zeros_prompt_pad": OptionInfo(False, "Use zeros for prompt padding", gr.Checkbox),
"prompt_detailed_tokens": OptionInfo(False, "Show detailed token counts", gr.Checkbox),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think we need this as tunable. if it works, it should be on and thats it.


try:
try:
ids = getattr(tokenizer(prompt_list), 'input_ids', [])
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this assumes that tokenizer works with list as input, that's the only thing i'm not sure about for all different tokenizers, but ok for now and if needed, it can be changed later.

for p in prompt_list:
ids.append(getattr(tokenizer(p), 'input_ids', []))
except Exception as e:
shared.log.warning("Token counter:", e)
Copy link
Owner

@vladmandic vladmandic Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be guarded with warn_once so its not flooding the log?
(similar to how preview reports first error but then stays silent)

@vladmandic
Copy link
Owner

vladmandic commented Feb 20, 2026

minor nitpicks in comments.
big one is that entire concept with BREAK only works on some models and only if enhanced prompt parsing is enabled, so its a mistake to present broken down token count if that is not the case.

see check in

if (prompt_attention != 'fixed') and ('Onnx' not in cls) and ('prompt' not in p.task_args) and (
('StableDiffusion' in cls) or
('StableCascade' in cls) or
('Flux' in cls and 'Flux2' not in cls) or
('Chroma' in cls) or
('HiDreamImagePipeline' in cls)

@awsr
Copy link
Contributor Author

awsr commented Feb 22, 2026

Yeah, it's a little confusing to untangle which instances are valid for BREAK because processing_prompt.py makes calls to prompt_parser_diffusers.py which also makes calls to prompt_parser.py. For example, parse_prompt_attention in prompt_parser.py includes a check to replace instances of \n with BREAK based on the setting. I've got no idea if that's because other parsers automatically do that or if BREAK doesn't work with the other parsers. I'm still looking into it.

@vladmandic
Copy link
Owner

any case where prompt parser is not native (so either fixed, a1111 or compel), do not trigger your logic. lets not go into total border cases. sdnext has native and native is what matters.

what i highlighted is that BREAK only has meaning for some MODEL TYPES, not just if parser is set to native or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants