001Notes

From Repeated Email to Structured Knowledge: Templates, Extraction, Facts, and Summaries

On this page24

A from-scratch tutorial following repeated email through template mining, source-linked extraction, symbolic facts, proof trees, and hierarchical summarization.

Article details
Status
Building Publicly
Subcategory
Thunderbird AI
Last reviewed
3 Sept 2026
Prerequisites
No clustering or string-algorithm knowledge required
24 sections

Many emails are machine-generated variations of the same shape:

Invoice INV-1001 for Northwind is ready
Invoice INV-1002 for Contoso is ready
Invoice INV-1003 for Fabrikam is ready

A semantic embedding may place these messages near one another, but their more interesting property is structural: constant words stay fixed while slots change.

Invoice <*> for <*> is ready

Template mining discovers that shape from observations. ThunderbirdAI uses a small Drain3-compatible online miner for repeated mail structure. It learns patterns, not truth: the original message remains the source.

1. What is a template?

A template is a sequence containing constants and variables:

constant    variable    constant    variable    constant
Invoice     INV-1001    for         Northwind   is ready

After generalization:

Invoice     <*>         for         <*>         is ready

Templates can support matching, field extraction, summaries and user-facing families. They are not the same as topics. Two invoices and a security alert may all mention “account,” yet their layouts differ.

2. Convert likely variables before clustering

The first pass tokenizes a subject or stable body line and replaces obvious variable-shaped tokens:

INV-1001             → <*>
2026-09-03           → <*>
maya@example.test    → <*>
https://...          → <*>

Ordinary words are lowercased. Punctuation is stripped carefully enough to retain meaningful characters in URLs and identifiers.

The rule must be conservative. If every hyphenated word becomes a variable, security-update available collapses into <*> available and may merge with unrelated product updates.

3. Measure compatibility with a current template

For equal-length sequences, count positions that are equal or already wildcarded:

Equal-length template similarity

similarity=matching constants + wildcard positionsnumber of token positions

A wildcard accepts a variable token, while a different constant reduces the score.

Example:

template:  invoice <*> for northwind is ready
candidate: invoice <*> for contoso   is ready

matches:   yes     yes yes no        yes yes
score:     5/6 = 0.833

With threshold 0.6, the candidate joins the family.

4. Merge by replacing disagreement

Equal-length merging is simple:

invoice <*> for northwind is ready
invoice <*> for contoso   is ready

invoice <*> for <*>       is ready

Every differing position becomes a wildcard. Repeated observations refine the boundary between invariant language and variable slots.

Best similarity
Decision

The fourth message, “Security update available,” starts a second family instead of poisoning the invoice pattern.

5. Different lengths require sequence alignment

Now compare:

invoice <*> ready
invoice <*> for northwind review is ready

Positional comparison shifts after the insertion. We need the longest common subsequence of constant tokens.

The dynamic-programming table obeys:

Longest common subsequence recurrence

L[i,j]=L[i−1,j−1]+1if tokens match; otherwisemax(L[i−1,j], L[i,j−1])

Wildcards are excluded from constant alignment. Gaps between aligned constants become bounded wildcard regions.

For the sequences above, invoice and ready anchor the alignment. The middle becomes one wildcard region:

invoice <*> ready

This is more robust than comparing absolute positions, but also more dangerous: a broad wildcard can absorb unrelated text.

6. Thresholds create two opposite errors

A high threshold produces many narrow families:

invoice for Northwind
invoice for Contoso
invoice for Fabrikam

This is under-merging. Useful repetitions remain fragmented.

A low threshold may produce:

<*> <*> ready

This is over-merging. The template matches semantically and structurally different messages.

Evaluate both pair types:

Pairwise template quality

precision=true same-template pairs joinedall pairs joined;recall=true same-template pairs joinedall true same-template pairs

One global threshold rarely fits every sender; partitioning reduces accidental competition.

7. Partition before mining

A global mailbox contains too many unrelated generators. Sender or account partitions provide a useful prior:

bank-alerts@example.test      mine together
shop-orders@example.test      mine separately
human conversation            often avoid mining

Partitioning resembles placing documents in separate workbenches before clustering. It reduces comparisons and prevents generic phrases from connecting unrelated sources.

8. Online mining must forget something

An inbox can observe unlimited shapes; memory cannot grow without bound. ThunderbirdAI caps cluster count and evicts the least useful cluster by low observation count and old recency.

This introduces a policy question:

rare but important tax notice       1 observation
frequent marketing campaign       800 observations

Frequency-based eviction keeps the campaign. Product value may prefer the tax notice. A bounded algorithm still encodes priorities.

9. Learned structure should begin in shadow mode

Automatically turning a mined pattern into a production extraction rule is risky. A safer lifecycle is:

observed family

shadow candidate
    ↓ evaluate matches without changing behaviour
suggested template
    ↓ human review
promoted template

rematch affected messages

Shadow mode answers: How many messages would match? Which unrelated examples appear? Which fields vary? Promotion is a user or quality-gate decision, not a side effect of reaching an observation count.

10. Templates can infer typed slots

Once a family is stable, variable regions can be tested for types:

INV-1001, INV-1002, INV-1003    identifier-like
INR 805, INR 950, INR 1,805     amount-like
24 Aug, 25 Aug, 26 Aug          date-like

Typed slots are more useful than anonymous wildcards. A summary template can render:

Payment of {amount} at {merchant}; reference {reference}

But inference should preserve the exact source span and allow “unknown.” A wildcard that sometimes contains an amount and sometimes a slogan is not a trustworthy amount slot.

11. Complete dry run

Observe messages sequentially:

  1. First invoice creates a cluster.
  2. The identifier is already wildcarded by shape recognition.
  3. Second invoice scores above threshold; Northwind versus Contoso becomes a wildcard.
  4. Third invoice reinforces the family and observation count.
  5. Security update scores poorly and creates a second cluster.
  6. A candidate regex is generated with bounded wildcard width rather than unbounded .*.
  7. Historical messages are shadow-matched.
  8. A reviewer inspects false matches before promotion.

The fresh synthetic run produced two clusters from four inputs: one three-message invoice family and one security-update family.

12. Regex generation has a security edge

Mined templates often become regexes. An unbounded pattern such as:

^(.*a.*)+$

can trigger catastrophic backtracking on adversarial input. ThunderbirdAI’s safe-regex boundary rejects backreferences, lookbehind, nested unbounded quantifiers and other dangerous shapes; it also bounds input length and caches compiled patterns.

The template miner therefore needs two correctness dimensions:

Does the pattern match the intended family?
Can the pattern be evaluated within a predictable resource bound?

13. Experiments to run

  • Sweep the similarity threshold and plot family precision/recall.
  • Mix messages from two senders, then partition by sender and compare over-merging.
  • Insert optional phrases and inspect the LCS table.
  • Replace a conservative variable detector with “every hyphenated word is variable.”
  • Cap clusters at three and observe which rare family is evicted.
  • Promote a weak template, rematch historical mail, and count false matches before allowing any derived action.

The template-mining lesson is broader than email:

Repeated machine-generated text often contains more usable structure than semantic similarity reveals. Learning that structure is an online clustering problem with explicit generalization, memory and review policies.

Once a template stabilizes, its variable regions become candidates for typed extraction. That moves us from “these messages share a shape” to “this exact source span may be an amount, date or reference.”

14. Information extraction with source spans

An email contains sentences; an application often needs fields:

source:
INR 805.00 was debited at Book Nook on 24 August 2026.
Reference: TXN-HC-100005.

fields:
amount       INR 805.00
merchant     Book Nook
date         24 August 2026
reference    TXN-HC-100005
direction    debit

Information extraction converts unstructured or semi-structured text into named, typed values. It is not summarization. A useful field retains raw value, normalized value, source offsets, method, confidence and message identity.

Without a type, 805 might be a price, address or error code. Without offsets, a reviewer cannot inspect it. Without method and confidence, downstream code cannot distinguish a deterministic match from a model suggestion.

15. Regex, template slots, NER and generative extraction

A simplified currency regex is \bINR\s*[\d,]+(?:\.\d{2})?\b: word boundary, literal currency, optional spaces, digits/commas, and an optional two-digit decimal suffix. Regex excels at stable shapes but misses ₹805, written-number amounts and contextual distinctions such as 805 reward points.

An approved template supplies boundaries that a general detector lacks:

Payment of {amount} at {merchant}. Reference {reference}.

Book Nook becomes a merchant because it sits in a reviewed slot between stable constants. The method is precise for a sender family and fails when that format drifts.

Named-entity recognition labels spans such as [INR 805.00]AMOUNT and [Book Nook]MERCHANT. GLiNER-style models can receive candidate labels at inference time, but flexible labels do not make output authoritative. Thunderbird’s private adapter bounds the input and accepts a candidate only when offsets are in range and the submitted text contains the exact returned span.

Source-span validation

acceptedinput[start:end] = returnedTextand0 ≤ start < end ≤ length(input)

A confidence score cannot repair an invalid location or a value absent from the submitted source.

A generative model can return flexible JSON, but adds malformed schemas, silently changed values, absent plausible fields and quoted-history confusion. Validate every value against source or mark it as a derived, unverified candidate.

16. Run the deterministic extractor

The computed fixture contains three fictional messages with amounts, references, dates and an email address. It finds all six annotations. This proves those controlled shapes and offsets, not universal locale or invoice understanding.

Raw values preserve sender text; normalization enables equality and arithmetic. INR 1,805.00 can become currency INR and integer minor units 180500. Use decimal parsing for money, retain currency, and refuse ambiguous values such as 04/05/2026 without a locale rule.

Amount normalization

minorUnits=round(majorAmount × 100)

Normalization is a second fallible operation. Preserve both raw and normalized values.

Multiple constraints must belong to one source record. An amount in one message and reference in another cannot be combined into an answer neither supports. Message identity and offsets enforce co-occurrence.

17. Extraction evaluation and hostile regex

Measure field precision, recall and F1 by type, using exact-span and normalized-value scoring where relevant. An ID differing by one digit may be more harmful than a missed broad organization hint, so thresholds and review depend on field use.

User-supplied or mined regexes also need resource bounds. Nested quantifiers such as ^(a+)+$ can trigger catastrophic backtracking on a long near-match. Reject dangerous constructs, bound pattern and input lengths, cache compiled patterns and make timeout/failure explicit. Correctness includes both intended matches and predictable runtime.

MethodStrengthMain weaknessEvidence status
RegexStable exact shapesFormat variationStrong when span-valid
Approved templateRepeated sender layoutsTemplate driftStrong when slot maps to source
NERFlexible entity phrasingType and boundary errorsCandidate until validated
Generative extractionRelations and varied proseHallucination and schema errorsDerived until source-confirmed

18. Symbolic facts, rules and proof trees

An embedding may show that two messages discuss similar projects; it cannot prove who owns one. A generated summary saying “Meera leads Atlas” remains model output until source supports it.

A symbolic fact names a relation and arguments:

owns("Meera Iyer", "Atlas")

For mail, attach message ID, source span and exact evidence. Entity co-occurrence alone is not a relation: “Meera discussed Atlas” contains both names but does not establish ownership.

Email naturally uses an open-world assumption. Missing owns(Meera, Atlas) means not proven here, not false. Bodies may be unavailable and extractors may miss unusual wording. Explicit negative evidence such as “Meera does not own Atlas” is different from absence.

19. Active voice, passive voice and Datalog

“Meera owns Atlas” and “Atlas is owned by Meera” use different surface order but express the same logical roles. A passive extraction rule swaps captured groups before emitting the predicate.

The fictional run evaluates four sentences. Three express supported relations; one only discusses an entity and emits no fact.

Datalog adds rules over facts:

works_on(Person, Project) :- owns(Person, Project).

Read :- as “is true if.” Joins connect facts through shared variables:

owns(Meera, Atlas)
has_deadline(Atlas, Friday)

person_deadline(Person, Date) :-
  owns(Person, Project),
  has_deadline(Project, Date).

The substitution Person=Meera, Project=Atlas, Date=Friday derives person_deadline(Meera, Friday).

20. Provenance must compose through inference

A derived fact needs a proof tree:

person_deadline(Meera, Friday)
├── owns(Meera, Atlas)             source M1 span 12…29
└── has_deadline(Atlas, Friday)    source M2 span 4…33

If one leaf came only from a generated summary, the conclusion inherits that weaker status. A conservative illustrative policy uses the minimum premise confidence:

Conservative proof confidence

confidence(conclusion)=min(confidence(premise₁), …, confidence(premiseₙ))

This is a policy illustration, not universal probabilistic logic. A conclusion should not become more certain than its weakest premise.

Contradictory ownership messages may represent error, co-ownership or a handover. Add source identity and validity time; never apply “newest wins” silently to legal or historical claims. Facts can render as knowledge-graph edges while Datalog supplies queries and rules over relations.

Embeddings still help retrieve flexible paraphrases. Similarity expands where we look; source-backed extraction constrains what we claim; symbolic rules expose joins and proof boundaries.

21. Hierarchical summarization with provenance

“Summarize my mailbox” cannot be one unconstrained model call. A mailbox can exceed every context window and include unavailable, duplicated, quoted, encrypted or irrelevant content. Summarization is a lossy compression system whose unit, order and coverage must remain visible.

Text compression ratio

r=summary tokenssource tokens

A smaller ratio means stronger compression, not better preservation of important facts.

Extractive summarization copies source sentences, preserving wording and direct provenance but often producing redundancy. Abstractive summarization generates concise synthesis but can omit, substitute, misattribute or invent relations. A practical system can select extractive evidence before an abstractive presentation layer.

22. Map, reduce and respect email hierarchy

If a thread has 24,000 tokens and a summarizer accepts 4,000, map bounded chunks into summaries and reduce those summaries again.

Hierarchical reduction

S(document)=reduce(S(chunk₁), S(chunk₂), …, S(chunkₙ))

Text reduction is not associative: changing chunk boundaries or reduction order can change the result.

Email offers natural levels: passage, message, thread, folder or template family, account and selected-scope digest. Thread-first reduction preserves conversation order. A flat sample cannot prove mailbox-wide totals or coverage.

Labelled facts retained

The fixture begins with four fictional messages, 2,170 words and eight labelled facts. Its 84-word digest retains all eight. That invariant demonstrates the fixture, not a claim that arbitrary prose can always compress to 3.9% without loss.

23. Chronology, coverage and resumable reductions

Proposal, concern and final decision must not collapse into one timeless statement. Use message time, quote segmentation, reply relationships and status language to distinguish superseded proposals from final decisions.

Coverage describes input completeness, not faithfulness:

Body coverage

coverage=successfully processed eligible messagesall eligible messages in frozen scope

Report unavailable, skipped, oversized, blocked and failed messages separately.

Checkpoint message maps by body fingerprint, model/endpoint, recipe version and redaction policy. If one message changes, invalidate its map and dependent thread/folder/account reductions, not unrelated work.

Every mapped fact retains source IDs. A reduced statement combining M1 and M2 carries both IDs, while remaining a derived synthesis that must be inspected against its leaves.

24. Failure and evaluation across the structured pipeline

Summaries fail through omission, value substitution, temporal collapse, attribution error, unsupported causal compression and coverage illusion. Evaluate fact recall, claim support, attribution, temporal state, source-ID validity, compression, usefulness, latency, calls and cache reuse.

Then test the complete pipeline end to end:

  • sweep template thresholds and sender partitions;
  • compare regex, approved slots, NER and generation on identical fields;
  • rewrite relations into passive voice, negation and reported speech;
  • remove a proof premise and require unknown, not false;
  • shuffle thread order and measure final-decision accuracy;
  • change chunk boundaries and compare retained facts;
  • pause, resume and verify checkpoint reuse;
  • modify one message and inspect dependent invalidation;
  • hide bodies and require visible partial coverage.

The consolidated lesson is a progression of epistemic commitments: templates propose repeated structure, extraction binds typed values to source spans, symbolic rules derive inspectable conclusions, and summaries compress those conclusions without acquiring more authority than their evidence.

Primary references

  1. He et al.: Drain — An Online Log Parsing Approach
  2. Drain3 source and persistence model
  3. GLiNER: Generalist Model for Named Entity Recognition
  4. OWASP: Regular expression denial of service
  5. BART: Denoising Sequence-to-Sequence Pre-training
  6. T5: Exploring the Limits of Transfer Learning
  7. RAPTOR: Recursive Abstractive Processing for Tree-Organized Retrieval
  8. Soufflé: A Datalog Synthesis Tool for Static Analysis
  9. Soufflé language tutorial
Diagram