docs: architecture map (initial 5-slice generation, 105 pages)

Five-slice navigable map of the entire codebase under
docs/architecture-map/. Each slice is a self-contained
breadcrumbed sub-tree:

  01-frontend (16)              Svelte/SvelteKit UI
  02-tauri-runtime (26)         src-tauri commands + lifecycle
  03-audio-transcription (16)   audio + transcription crates
  04-llm-formatting-mcp (19)    llm, ai-formatting, mcp, cloud
  05-core-storage-hotkey-build  core, storage, hotkey, workspace,
                          (26) CI, dev glue

Plus master README.md and data-flow-end-to-end.md tracing
audio bytes from microphone to FTS5 search to MCP read.

Generated by 5 parallel subagents on 2026/05/09 against
HEAD 3c47000. Each page has YAML frontmatter, file:line code
refs, sibling cross-links, plain-English summaries.

Aggregated debt surfaced (full lists in master README):
RB-08 macOS power assertion, schema head drift v14 vs v15,
VAD blocked on ort version conflict, streaming primitives
not wired into live.rs, no prompt versioning, MCP has no
auth, cloud-providers in-memory keystore, SettingsPage
2 484 LOC, commands/live.rs 1 737 LOC, dual theme system,
brand rename to Lumenote pending across the codebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jars
2026-05-09 14:04:13 +01:00
parent 3c47000ea9
commit a1f3f3f134
105 changed files with 11266 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
---
name: Anti-hallucination filter
type: architecture-map-page
slice: 04-llm-formatting-mcp
last_verified: 2026/05/09
---
# Anti-hallucination filter
> **Where you are:** [Architecture map](../README.md) → [LLM, Formatting, MCP](README.md) → Anti-hallucination
**Plain English summary.** Whisper hallucinates on silence. It produces things like `[blank_audio]`, `Thanks for watching!`, `♪♪♪`, or a single token cascading 8 times in a row. `is_hallucination` returns true on any of those, and the pipeline drops the segment entirely. Three independent passes — bracketed markers, exact-match subtitle leakage, and a token-repetition detector.
## At a glance
- Crate: `magnotia-ai-formatting`
- Path: `crates/ai-formatting/src/rule_based.rs:374`
- LOC: ~50 for `is_hallucination` and the helper, plus ~70 lines of pattern tables
- Public surface: `pub fn is_hallucination(text: &str) -> bool` (`crates/ai-formatting/src/rule_based.rs:374`)
- External deps that matter: none — pure `str` work
- Tauri command that calls this (slice 2, best guess): not called directly. Reaches Tauri only via `post_process_segments`'s anti-hallucination retain-loop (`crates/ai-formatting/src/pipeline.rs:43`).
## What's in here
### Three passes (the function body)
1. **Empty-after-trim → true.** A blank segment is, by convention, treated as a hallucination so it gets dropped.
2. **Contains-match on `HALLUCINATION_MARKERS`** (`crates/ai-formatting/src/rule_based.rs:282`). Substring match on the lowercased trimmed text, so `[Music]`, `[MUSIC]`, and `[blank_audio]` all hit. Markers covered:
- Bracketed annotations: `[blank_audio]`, `[blank audio]`, `[silence]`, `[music]`, `[applause]`, `[laughter]`, `[laughs]`, `[inaudible]`, `[background noise]`, `[sounds]`, `(music)`, `(silence)`, `(applause)`, `(laughter)`.
- Musical notation: `♪`, `♫` — Whisper interprets sustained room tone as song.
- The contains-match catches `♪♪♪ thanks for watching ♪♪♪` even though neither half alone is exact.
3. **Exact-match on `HALLUCINATION_TRAIL_PHRASES`** (`crates/ai-formatting/src/rule_based.rs:312`). The full lowercased trimmed text must equal one of the phrases. Used for the YouTube / subtitle-training leakage that Whisper imports from its training data:
- Minimalist false-positives on silence: `thank you.`, `thank you`, `thanks.`, `thanks`, `you.`, `you`, `bye.`, `bye`.
- YouTube subtitle sign-offs: `thank you for watching.`, `thanks for watching!`, `thanks for watching, bye.`, `thanks for listening.`, `please subscribe.`, `please subscribe to our channel.`, `don't forget to subscribe.`, `don't forget to like and subscribe.`, `like and subscribe.`, `see you in the next video.`, `see you next time.`.
- Subtitle-credit leakage: `subtitles by the amara.org community`, `subtitles by the`, `subtitled by`, `subtitles by`, `translated by`.
- Non-English sign-offs: Japanese `ご視聴ありがとうございました`, `字幕作成者`, `字幕by`, `字幕`, Korean `mbc 뉴스 김수영입니다`. Lowercase exact-match consistency is preserved across scripts.
Exact-match is deliberate: a real sentence containing "thanks for the heads up on the migration" must pass.
4. **Consecutive-repetition detector** (`crates/ai-formatting/src/rule_based.rs:403`). Whisper's prompt-loop failure mode (ufal/whisper_streaming #161) is a single token cascading 510+ times. Threshold is 4 — caught at `REPETITION_RUN_THRESHOLD = 4` (`:358`). Three-in-a-row is common in natural speech ("no no no, that's wrong"), four-in-a-row almost never is. Case-insensitive token comparison.
### Provenance of the pattern lists
The trail phrases trace back to specific upstream issues:
- WhisperLive #185 and #246 — silence triggering `Thank you for watching` and similar.
- ufal/whisper_streaming #121 — caption-dataset leakage on room tone.
- ufal/whisper_streaming #161 — prompt-loop cascade.
Comments on each pattern list cite the exact source so a future contributor knows where each entry came from and why removing it might let the failure mode return.
### `has_consecutive_repetition` (`crates/ai-formatting/src/rule_based.rs:403`)
Linear pass. Walk whitespace-separated tokens, lowercase each, increment a `run` counter when the current matches the previous, reset when it does not. Return true the moment `run >= min_run`.
Tests at `crates/ai-formatting/src/rule_based.rs:551` cover:
- The cascade case: `"I I I I I I I I I"`, `"hello hello hello hello world"`, `"the the the the quick brown fox"`.
- The case-insensitive case: `"Hello HELLO hello hello"`.
- The legitimate-triple case: `"no no no, that's wrong"` (returns false — three is below threshold).
- Alternating patterns: `"I am I am I am I am"` (returns false — never four-in-a-row).
## Data flow
```
text: &str
→ trimmed = text.trim().to_lowercase()
→ empty? → true
→ for marker in HALLUCINATION_MARKERS:
if trimmed.contains(marker) → true
→ for phrase in HALLUCINATION_TRAIL_PHRASES:
if trimmed == phrase → true
→ has_consecutive_repetition(&trimmed, 4) → true if any run >= 4
→ otherwise false
post_process_segments behaviour: segments.retain(|s| !is_hallucination(&s.text))
— segments returning true are dropped from the output list entirely.
```
## Watch-outs
- **Drop is permanent.** A segment removed by anti-hallucination is gone before any other filter or LLM cleanup runs. If a real-world transcript ever has a legitimate segment that exactly matches "Thanks." (e.g. in a meeting where someone said only "Thanks." in response to a question), it gets dropped. The exact-match policy on `HALLUCINATION_TRAIL_PHRASES` is the trade-off — substring-match would have a much larger false-positive rate.
- **Threshold of 4 for repetition is conservative.** Some Whisper failures cascade to dozens of tokens, well past the threshold; the detector catches those easily. The risk is on the other side: legitimate four-in-a-row chants ("go go go go", "yes yes yes yes!") get dropped. Acceptable for dictation; would be wrong for music transcription, but Magnotia's scope is dictation.
- **Multi-token phrase repetition is not yet detected.** "thank you thank you thank you thank you thank you" (five `thank you` in a row) does not trigger the detector — the comparison is per-token, not per n-gram. The test comment at `crates/ai-formatting/src/rule_based.rs:553` calls this out explicitly as a future enhancement requiring sliding n-gram matching.
- **Non-English sign-offs are lowercased trimmed exact match.** A future Japanese ASR engine that uses different sign-off phrasing would slip through. Update the table when new ASR backends are added.
- **No alphabet-class detection.** A long burst of mojibake (`<60> <20> <20> <20> <20>`) where every char is the replacement codepoint would not trigger any of the three passes. Whisper does not produce this in practice; if a future codec change made it possible, a fourth pass would be needed.
- **`HALLUCINATION_MARKERS` is contains-match.** A real meeting transcript containing the phrase "the team will [music]play in October" would be dropped. Markers are deliberately niche enough that real text containing them is improbable; the cost of substring match is accepted.
## See also
- [Pipeline overview — anti-halluc as a drop step](formatting-pipeline.md)
- [Filler removal and British English (sibling functions in same file)](formatting-filler-and-british.md)
- [Slice README](README.md)