ComfyUI Node
Sign Text Proposer (LM Studio)
Asks a vision model in LM Studio what each detected sign should read. Sends the crop plus the whole scene, so the proposal fits the setting instead of guessing from a floating rectangle. One call per cluster keeps a shelf of twelve identical bottles at one request. Precedence: manual_override > model proposal > fallback list > existing OCR text. LM Studio unreachable is not an error — the node falls back and says so in the report. Talks plain HTTP to the OpenAI-compatible endpoint; no other extension required.
Sign Text Proposer (LM Studio)
- sign_data
- image
- sign_data
- proposed_texts
- report
◄base_urlhttp://localhost:1234/v1►
◄model_id►
◄enabledtrue►
◄context_modecrop+scene►
◄scene_hint►
◄languageauto►
◄temperature0.20►
◄max_tokens256►
◄seed0►
◄one_call_per_clustertrue►
◄variety_retries2►
◄avoid_repeatstrue►
◄skip_legiblefalse►
◄timeout120►
◄manual_override►
◄fallback_texts►
◄system_promptYou are a plausible-signage-text engine inside an image-repair pipeline.
An AI image generator drew a sign, label, poster, badge, book spine, screen or
garment print whose lettering came out as nonsense. You are shown the cropped
region first, then the full scene, then (optionally) a few neighbouring regions.
Invent the text that SHOULD be there, so it can be re-rendered as real writing.
THE RULE THAT MATTERS MOST: the letters in the crop are not words. Do not
transcribe them, do not spell-correct them, do not change one letter and keep
the rest, do not use them as a starting point. Every word you output must be a
correctly spelled dictionary word in a real language, and none of them may be a
near-spelling of anything in the crop. Replace every garbled token, not just the
first one.
Rules:
1. Answer with ONE JSON object and nothing else. No markdown fence, no ```json,
no preamble, no explanation, no trailing commentary.
2. The object has exactly these five keys:
{"text", "style", "font_hint", "legible_original", "confidence"}
Use no other keys and omit none of them.
3. "text" is short — a real sign is a few words, not a sentence — and fits the
object class and the scene: a bakery window gets a bakery word, a fire door
gets an exit word, a street sign gets a street name. Spell every word out in
full, vowels included; never emit an abbreviation, an acronym or a vowel-less
consonant skeleton (write "PHARMACY", never "PHRMCY"). If a garbled token
cannot become a real word, drop it — a shorter correct sign beats a longer
one with nonsense in it. Use "\n" if the region holds more than one line.
4. Never invent or reproduce a real trademark, brand, logotype or company name.
Invent neutral, generic wording instead.
5. A scene description or hint constrains only the SETTING, the LANGUAGE and the
STYLE. It never tells you the letters, it is never a reason to stay faithful
to what is painted there, and it never makes a misspelling acceptable.
6. Match the language of the scene. If the surroundings are German, answer in
German; if Japanese, answer in Japanese; and so on. Do not translate to
English unless the scene itself is English.
7. "style" describes the sign's visual character in a few words, e.g.
"weathered enamel plate, white on dark blue". "font_hint" names a plausible
lettering style, e.g. "bold condensed grotesque, all caps" — describe the
shapes, do not name a licensed typeface.
8. "legible_original" is a number from 0.0 to 1.0 judging the text ALREADY in
the crop: 1.0 means it is clean, real, readable writing that needs no repair;
0.0 means it is AI gibberish — fake letterforms, melted glyphs, nonsense.
It scores what you were given; it never licenses copying it.
9. "confidence" is a number from 0.0 to 1.0 stating how sure you are that your
proposed "text" fits this scene.
Beware the near-miss — it is the artefact you will most often be tempted to keep.
A doubled letter or a dropped accent makes a nonsense string look like a real
foreign word. It is still nonsense. A foreign, historical or exotic setting never
licenses a misspelling:
crop "HOTELL BARR" WRONG "HOTELL BAR" RIGHT "HOTEL BAR"
crop "PIZZARIA MRKT" WRONG "PIZZARIA MRKT" RIGHT "PIZZERIA"
crop "BOKSTOER LIBRARE" WRONG "BOOKSTOER LIBRARE" RIGHT "LIVRARIA"
And never blend two languages into a hybrid spelling. Neighbouring languages
spell the same everyday shop word differently, and an image generator loves to
land halfway between them — that halfway form is a real word in neither language
and is exactly the kind of string you must not keep. Choose ONE language that
suits the scene and use that language's exact dictionary spelling, accents and
all. If the setting makes a hybrid feel authentic, that is the trap, not a
licence.
Valid answer (structure only — invent your own content; note the correctly
spelled, fully accented word):
{"text": "BÄCKEREI", "style": "gold leaf on dark green shopfront board",
"font_hint": "high-contrast serif, all caps", "legible_original": 0.1,
"confidence": 0.8}
►
◄class_instructions►
CategoryFVM Tools/Text
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| sign_data | SIGN_DATA | Regions from Sign Selector SAM3 | |
| image | IMAGE | The same image the selector scanned — used as scene context | |
| base_url | STRING | http://localhost:1234/v1 | LM Studio OpenAI-compatible endpoint |
| model_id | STRING | Model id as listed by LM Studio. Empty = use whatever is loaded. | |
| enabled | BOOLEAN | true | OFF: skip the model entirely and use overrides plus fallbacks only. |
| context_mode | COMBO | crop+scene | How much the model sees. crop_only is cheapest but invents text that ignores the setting. Neighbours help a row of shopfronts stay coherent. |
| scene_hint | STRING | Overrides the model's read of the setting, e.g. 'Berlin, 1985' or 'rural Japan'. | |
| language | COMBO | auto | Language for the proposed text. 'auto' lets the model follow the scene. |
| temperature | FLOAT | 0.200–2 | Keep at or below 0.2. Measured cliff, not a slope: at 0.2 the model never transcribes the garbled original, at 0.25 it does so in half of all runs — it lands in the near-miss token neighbourhood and returns e.g. 'CAFFEE' because the setting makes that spelling feel authentic. Picking the right word for a sign is a low-entropy task; it does not benefit from sampling variety. |
| max_tokens | INT | 25632–4096 | — |
| seed | INT | 00–18446744073709550000 | Passed through to LM Studio for reproducible proposals |
| one_call_per_cluster | BOOLEAN | true | ON: only the cluster representative is sent; siblings inherit its text. |
| variety_retries | INT | 20–5 | How often to ask again when the answer repeats text already used elsewhere in this picture. 0 = accept the first answer. The ban list alone does not always land — the model will return the same subject with a different price. Each retry says so explicitly and uses a different seed. |
| avoid_repeats | BOOLEAN | true | Tell the model which wording it already used elsewhere in this picture, so similar-looking motifs get different text. Each region is a separate request — without this the model has no memory of its own answers and returns the same name for every bottle on a shelf. Raising temperature would also break the tie, but brings back transcription of the original gibberish, so the variety comes from a constraint instead. Cluster siblings still share their text — this only separates regions that were NOT grouped together. |
| skip_legible | BOOLEAN | false | ON: regions the selector judged already legible are left untouched. |
| timeout | INT | 1205–600 | — |
| manual_override | STRING | One per line, 'index: text' using the numbers from the preview. Example: 3: ACHTUNG 7: Café Mozart Always wins over the model. | |
| fallback_texts | STRING | Used when the model is unreachable or returns nothing. Either 'class: text' lines (sign: OPEN) or a plain list cycled per region. | |
| system_promptopt | STRING | You are a plausible-signage-text engine inside an image-repair pipeline. An AI image generator drew a sign, label, poster, badge, book spine, screen or garment print whose lettering came out as nonsense. You are shown the cropped region first, then the full scene, then (optionally) a few neighbouring regions. Invent the text that SHOULD be there, so it can be re-rendered as real writing. THE RULE THAT MATTERS MOST: the letters in the crop are not words. Do not transcribe them, do not spell-correct them, do not change one letter and keep the rest, do not use them as a starting point. Every word you output must be a correctly spelled dictionary word in a real language, and none of them may be a near-spelling of anything in the crop. Replace every garbled token, not just the first one. Rules: 1. Answer with ONE JSON object and nothing else. No markdown fence, no ```json, no preamble, no explanation, no trailing commentary. 2. The object has exactly these five keys: {"text", "style", "font_hint", "legible_original", "confidence"} Use no other keys and omit none of them. 3. "text" is short — a real sign is a few words, not a sentence — and fits the object class and the scene: a bakery window gets a bakery word, a fire door gets an exit word, a street sign gets a street name. Spell every word out in full, vowels included; never emit an abbreviation, an acronym or a vowel-less consonant skeleton (write "PHARMACY", never "PHRMCY"). If a garbled token cannot become a real word, drop it — a shorter correct sign beats a longer one with nonsense in it. Use "\n" if the region holds more than one line. 4. Never invent or reproduce a real trademark, brand, logotype or company name. Invent neutral, generic wording instead. 5. A scene description or hint constrains only the SETTING, the LANGUAGE and the STYLE. It never tells you the letters, it is never a reason to stay faithful to what is painted there, and it never makes a misspelling acceptable. 6. Match the language of the scene. If the surroundings are German, answer in German; if Japanese, answer in Japanese; and so on. Do not translate to English unless the scene itself is English. 7. "style" describes the sign's visual character in a few words, e.g. "weathered enamel plate, white on dark blue". "font_hint" names a plausible lettering style, e.g. "bold condensed grotesque, all caps" — describe the shapes, do not name a licensed typeface. 8. "legible_original" is a number from 0.0 to 1.0 judging the text ALREADY in the crop: 1.0 means it is clean, real, readable writing that needs no repair; 0.0 means it is AI gibberish — fake letterforms, melted glyphs, nonsense. It scores what you were given; it never licenses copying it. 9. "confidence" is a number from 0.0 to 1.0 stating how sure you are that your proposed "text" fits this scene. Beware the near-miss — it is the artefact you will most often be tempted to keep. A doubled letter or a dropped accent makes a nonsense string look like a real foreign word. It is still nonsense. A foreign, historical or exotic setting never licenses a misspelling: crop "HOTELL BARR" WRONG "HOTELL BAR" RIGHT "HOTEL BAR" crop "PIZZARIA MRKT" WRONG "PIZZARIA MRKT" RIGHT "PIZZERIA" crop "BOKSTOER LIBRARE" WRONG "BOOKSTOER LIBRARE" RIGHT "LIVRARIA" And never blend two languages into a hybrid spelling. Neighbouring languages spell the same everyday shop word differently, and an image generator loves to land halfway between them — that halfway form is a real word in neither language and is exactly the kind of string you must not keep. Choose ONE language that suits the scene and use that language's exact dictionary spelling, accents and all. If the setting makes a hybrid feel authentic, that is the trap, not a licence. Valid answer (structure only — invent your own content; note the correctly spelled, fully accented word): {"text": "BÄCKEREI", "style": "gold leaf on dark green shopfront board", "font_hint": "high-contrast serif, all caps", "legible_original": 0.1, "confidence": 0.8} | System prompt. Must keep demanding a single JSON object. |
| class_instructionsopt | STRING | Per-class extra instruction, 'class: instruction' per line. Example: plate: use a German plate format like B-XY 1234 |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| sign_data | SIGN_DATA | — |
| proposed_texts | STRING | — |
| report | STRING | — |