A real-time LLM stream guard that catches LLM hallucinations mid generation HAL-X AI researchers F. Aghayev and E. Ahmadbayli released SIMURG, a streaming integrity monitor that detects LLM decoding corruption in real time, cutting the stream mid-flight to prevent users from seeing corrupted output. The tool processes 197,632 characters per second on a laptop CPU, detects corruption within ~590 characters of onset, and requires no model, GPU, or training, using only numpy. SIMURG is designed for production LLMs, especially quantized or small models, and offers a zero-leak guarantee by holding the stream's opening in a buffer until verified clean. Streaming Integrity Monitor & Universal Regeneration Guard Catch LLM decoding corruption while the answer is still being generated and cut the stream mid-flight : corruption that starts in the hold window never reaches the user, and mid-stream corruption is aborted within a few hundred characters of onset, so the host regenerates the answer. | throughput | detection latency | false-alarm budget | footprint | setup | |---|---|---|---|---| 197,632 chars/sec on a laptop CPU | ~590 chars past corruption onset | configurable, conformal-calibrated | numpy only, no model, no GPU | 3 lines, zero training | The guard runs hundreds of times faster than a typical LLM produces text, so it is never the bottleneck: a model streaming at 50 tokens/sec writes ~250 chars/sec, and SIMURG reads 197,000. Table of contents When you run an LLM in production, especially a quantized, small, or self-hosted model, it sometimes derails mid-generation . The decoded stream stops doing the task and collapses into one of a handful of pathologies: | failure mode | what it looks like | |---|---| repetition collapse | the same phrase, list, or token repeated until the token budget runs out | cross-lingual drift | an English answer that quietly slides into Chinese, Arabic, or Cyrillic | regurgitation | the model dumps a README, boilerplate, or training text | structural breakdown | REF -0.00 -0.00 ... 0.00 : number and symbol garbage | template leakage | < | This is not factual hallucination. A fluent-but-wrong sentence see What SIMURG is NOT what-simurg-is-not has no statistical scar. What is shown above is decoding corruption , and it leaves a statistical signature in the token stream : repetition rate, lexical variety, script distribution, compressibility, and predictive surprise all move in measurable ways. SIMURG watches that signature character by character, decides in real time whether the stream has gone bad, tells you where it started, and lets you abort and retry before the user ever sees the corruption. The full technical report, with the complete evaluation, per-class analysis, onset-localization study, and the zero-leak protocol specification: SIMURG: Zero-Leak Online Detection of LLM Decoding Corruption in Production Streams, F. Aghayev, E. Ahmadbayli, HAL-X AI, 2026. Read the paper PDF, 13 pages SIMURG | post-hoc linter | LLM-as-judge | perplexity threshold | | |---|---|---|---|---| | when it fires | mid-generation, ~590 chars past onset | after the full answer | after the full answer | post-hoc, or needs logprob access | | what the user sees | zero bad tokens when onset is in the hold window; otherwise the clean prefix plus a bad tail of at most ~900 chars, replaced by the retry | the whole corrupt answer | the whole corrupt answer | varies | | why it fired | a named, human-readable reason on every alarm | a pattern list | the judge's opinion, if any | one number | | model-agnostic | any OpenAI-compatible endpoint, or any stream you feed | any | any | needs a logprob-capable backend | | overhead | numpy-only, ~197k chars/sec on one CPU core | trivial | one extra LLM call per answer | per-token logprobs | The zero-leak property is the point: post-hoc checks can only tell you that the answer was bad after the user read it . SIMURG holds the opening of every stream in a buffer, releases it only once it is verified clean, keeps re-checking, and cuts the stream the moment it crosses the calibrated threshold. SIMURG makes one O 1 -per-character pass over the stream, maintaining a set of incremental features digit fraction, foreign-script fraction, repetition rate, compressibility, type-token ratio, script-switch rate, structural-artifact density, ... , and feeds a pluggable detector ensemble on top of them: php flowchart TD A "token stream" -- B "stream features