# Traçage de contexte fuzzy restreint: Qu'on se souvient

<!-- category -- AI,Patterns,Architecture,LLM,DiSE -->
<datetime class="hidden">2026-01-06T16:00</datetime>

L’une des façons les plus faciles de faire échouer un système AI est d’en laisser trop de mémoire.

La plupart des "manifestations contextuelles" approches se résument à l’une des deux erreurs

- **Faire en sorte que tout soit inscrit dans la prompt.** et nous espérons que le modèle déterminera ce qui importe
- **Réponse répétée-résumer les résumés** et accepter la dérive comme un fait de vie

Les deux approches sont coûteuses, opaque , et instables à long termeM SK2

Il y a un meilleur modèle - qui reflète la façon dont les systèmes biologiques mesurent réellement la cognition.

Je l'appelle **Traçage de contexte fuzzy restreint** (CFCDM SK1

[TOC]

---


## Le modèle dans une seule phrase

> **Traçage de contexte fuzzy restreint** est un modèle dans lequel les modèles probabilistes proposent ce qui constitue une salience, mais seulement des règles déterministes sont autorisées à faire avancer cette salience pour influer sur le raisonnement futur ou la génération.

Ou plus franchement:

> *Les modèles peuvent remarquer. L’ingénierie décide ce qui persiste .*

Il s'agit de la même fracture philosophique que [Fuzziness restreinte](/blog/constrained-fuzziness-pattern) et [MoM Fuzzy restreint](/blog/constrained-mom-mixture-of-models) - a été appliquée tout juste le long du **axe du temps** au lieu de **axe de décision**.

---


## L’erreur fondamentale: Traiter le contexte comme un texte

Les LLM ne sont pas "remmember". Ils ont un modèleM SK2compliant sur les tokens .

Lorsque nous traitons le contexte comme "just plus de texte ", on obtient

- dérive silencieuse
- terminologie incohérente
- le coût de l'évacuation
- Résumés qui contredisent les résumés antérieurs
- traductions qui rebaptisent la même chose cinq fois
- le contexte devient une dépendance non convertie ( personne ne sait ce qui a changéM SK1 mais les résultats ont changé )

Les fenêtres contextuelles plus longues ne règlent pas ce problème. Elles retardent simplement l’échec.

La véritable question n'est pas *• le nombre d’années de vie* context pour conserver, maisM SK1

> **Ce qui mérite de survivre?**

---


## Règle de la CFC

CFCD impose une séparation dure:

| Rôle | Permis d'être floueM SK2 | Permission de devenir une contrainte à l'avenir
|------|---------------------|--------------------------------------|
| Détection de la salience MSC1 Oui MSC2 Non SMC3
| Promotion dans le contexte | Non MSC2 Oui MSC3
| Génération | Oui MSC2 Non MSC3
| Entreposage des ancres ( entrepôt d'ancrage) MSC3 Non SMC4 Oui ESC5

La probabilité peut *Suggérer*. Le déterminisme détermine ce qui fait progresser

Moyens déterministes: **Les mêmes intrants + la même politique ⇒ les mêmes ancrages**. Vous pouvez toujours utiliser les cotes probabilistes ; vous pouvez simplement les faire passer par une promotion fixe M SK2 fonctions d'expiration

CFCD est la façon dont vous obtiendrez les avantages du contexte sans payer le prix du contexte.

---


## Exemple 1: Sommaire ( Dragage verticalM SK2

### L'approche naïve

- Documents en gros
- Résumer chaque tronçon
- Résumer les résumés
- Accepter la dérive

Cela échoue parce:

- Composé des erreurs précoces
- L'accent est déplacé arbitrairement.
- les contradictions sont cachées

### Approche du CFCD

Le point de vue clé: **La détection de la salience n’exige pas une LLM**. Vous pouvez utiliser le ML déterministe (embeddings, TFMSC3IDFM SK4 BMMska5 pour trouver ce qui importeMske6 puis restreindre le LLM afin de voir seulement ce que la sélection a survécuMSKA7

[DocSummarizer](/blog/docsummarizer-advanced-concepts) met en œuvre ce

1. **Parler le document en segments** (énoncésM SK1entêtes,listesMSC3blocs de code )
2. **Générer des embeddings** en utilisant la phrase ONNX-transformateurs (ML, non LLMM SK3
3. **Calculer les points de salience** en utilisant:
   - La similitude des cosine avec la centroïde du document
   - TF-IDF pour l'importance du terme
   - Pondérations de position (introduction/accroissement de la conclusionM SK2
   - Contenu-ajustements de type M SK1narrative vs expository)
4. **Choisissez le haut-K en utilisant MMR** (Relevance marginale maximaleM SK1
   - Équilibrage de la pertinence (similarité avec le centroïdeM SK1 avec la diversité
   - Déterministe: les mêmes intrants → la même sélection
5. **LLM ne synthétise que des segments sélectionnés**

Le LLM ne voit jamais le document complet.

```csharp
// From DocSummarizer: SegmentExtractor.cs
public class SegmentExtractor
{
    private readonly OnnxEmbeddingService _embeddingService;  // ML, not LLM

    public async Task<ExtractionResult> ExtractAsync(string docId, string markdown)
    {
        // 1. Parse document into typed segments
        var segments = ParseToSegments(docId, markdown);

        // 2. For large docs: semantic pre-filtering with multi-anchor approach
        //    - Guaranteed coverage: first/last sentences per section, constraints
        //    - BM25 candidate generation with pseudo-query from TF-IDF terms
        //    - Topic anchors via k-means clustering on sample embeddings
        if (segments.Count > _config.MaxSegmentsToEmbed)
        {
            (segmentsToEmbed, centroid) = await SemanticPreFilterAsync(segments, targetCount);
        }
        else
        {
            await GenerateEmbeddingsAsync(segments);
            centroid = CalculateCentroid(segments);
        }

        // 3. Score by salience using MMR (deterministic)
        //    Salience = lambda * sim(segment, centroid) * position_weight * content_weight
        //             - (1 - lambda) * max_sim(segment, higher_ranked_segments)
        ComputeSalienceScores(segments, centroid, contentType);

        // 4. Return top-K as anchors for synthesis
        var topBySalience = segments
            .OrderByDescending(s => s.SalienceScore)
            .Take(Math.Max(_config.FallbackBucketSize, targetCount))
            .ToList();

        return new ExtractionResult
        {
            AllSegments = segments,
            TopBySalience = topBySalience,
            Centroid = centroid,
            ContentType = contentType
        };
    }

    /// <summary>
    /// Greedy MMR selection: balances relevance with diversity
    /// </summary>

    private void ComputeSalienceScores(List<Segment> segments, float[] centroid, ContentType contentType)
    {
        var candidates = new HashSet<Segment>(segments.Where(s => s.Embedding != null));
        var ranked = new List<Segment>();

        // Pre-compute centroid similarities with content-type adjustments
        foreach (var segment in candidates)
        {
            var baseSim = CosineSimilarity(segment.Embedding!, centroid);
            var contentWeight = ComputeContentTypeWeight(segment, contentType);
            segment.SalienceScore = baseSim * segment.PositionWeight * contentWeight;
        }

        // Greedy MMR: pick best, penalise similar, repeat
        while (candidates.Count > 0)
        {
            var best = candidates
                .Select(c => new {
                    Segment = c,
                    Score = _config.MmrLambda * c.SalienceScore
                          - (1 - _config.MmrLambda) * MaxSimToRanked(c, ranked)
                })
                .OrderByDescending(x => x.Score)
                .First();

            best.Segment.SalienceScore = 1.0 - ((double)ranked.Count / segments.Count);
            ranked.Add(best.Segment);
            candidates.Remove(best.Segment);
        }
    }
}
```

### Selection adaptative: Context Window Awareness

Comme le résultat est un **collecte classée**, vous pouvez adapter le nombre d'ancres au modèle de synthèse en temps réel

```csharp
public class AdaptiveSynthesizer
{
    public int ComputeAnchorBudget(ModelProfile model, ExtractionResult extraction)
    {
        // Larger context windows → more anchors
        var baseTokenBudget = model.ContextWindow / 4;  // Reserve 25% for output

        // More powerful models → can handle more complex synthesis
        var complexityMultiplier = model.Tier switch
        {
            ModelTier.Small => 0.5,   // tinyllama: fewer, simpler anchors
            ModelTier.Medium => 1.0,  // llama3.2:3b: standard
            ModelTier.Large => 1.5,   // llama3.1:8b+: more context, nuanced synthesis
            _ => 1.0
        };

        var anchorBudget = (int)(baseTokenBudget * complexityMultiplier / _avgTokensPerSegment);

        // Never exceed what we have
        return Math.Min(anchorBudget, extraction.TopBySalience.Count);
    }

    public async Task<Summary> SynthesizeAsync(
        ExtractionResult extraction,
        ModelProfile model)
    {
        var budget = ComputeAnchorBudget(model, extraction);

        // Take top-K from already-ranked segments
        var anchors = extraction.TopBySalience.Take(budget).ToList();

        // Synthesis model only sees what survived selection + adaptation
        return await _llm.SynthesizeAsync(anchors, model);
    }
}
```

Cela est encore déterministe: **Les mêmes entrées + le même profil de modèle → les mêmes ancrages**. Le classement se fait une fois ; L’adaptation n’est qu’une tranche

Cela signifie que vous pouvez:

- Utiliser un petit modèle rapide avec des ancrages 5 pour les résumés rapides
- Utiliser un modèle puissant avec des ancres 50 pour une analyse approfondie
- Adjuster dynamiquement le mid-pipeline si la première tentative manque de couverture

Le point de vue clé: **les ancres sont de structure, non de prose**. Les embeddings et la MMR sont déterministesM SK1 Le LLM ne fait que la synthèse finale, restreint par ce qui a survécu

**Contrat d’ancrage:** génération peut varier le phrasing, mais ne doit pas contredire les ancragesM SK1 Si les ancres sont insuffisantes , il faut s’assurer et/ou demander plus de preuvesMSC4

Représentation d'un ancre en béton:

```json
{
  "policyVersion": "cfcd-v1",
  "segments": [
    {"id":"seg-12","text":"Reset requires holding button 10s","salience":0.92},
    {"id":"seg-45","text":"Factory reset clears all settings","salience":0.88}
  ],
  "coverage": "3.2% semantic sample",
  "hedging": "sampled 3% - avoid definitive conclusions"
}
```

---


## Exemple 2: Traduction

La traduction expose ce modèle encore plus clairement.

### Mode de défaillance

Translate sentence-byM SK1sentence et vous obtiendrez

- terminologie incohérente
- entités renouvelées
- dérive sémantique subtile

Même avec une grande fenêtre contextuelle, les modèles , demeurent libres de modifier le libellé des termes "

### Approche du CFCD

1. Au début du document, extrait **candidats à la terminologie**:
   - Nom propre
   - conditions techniques
   - phrases répétées
2. Établissement d'un **Compte tenu de l'évolution de la situation financière des États-Unis, il n'y a pas lieu d'établir une liste détaillée.**:
   - source → cartographie cible
   - Confiance
   - première-localisation visible
3. Pour chaque phrase:
   - autoriser la traduction floue
   - **Constraints** choix à l'aide du livret
   - autoriser la déviation uniquement avec des preuves locales solides
4. Mise à jour déterministe du livret si:
   - une meilleure cartographie apparaît à maintes reprises
   - ou un suppression explicite est déclaré

**Ce qui compte comme des preuves locales solides?**

- Le terme apparaît dans un glossaire, tableauM SK1 ou bloc de définition (cue structurelleMSC3
- Utilisateur explicite surride dans la configuration
- Répéter à l'intérieur des derniers chunks W (sliding window) avec un usage cohérent

Cette méthode est déterministe: les signes structurels sont détectés par classification par modèle ou par analyseur , non par jugement modélisé M SK2

Politique par défaut: Δ =0.08 Gap de confiance, WM SK3 tronçons MST4tune par domaineMSC5

```csharp
public class TermLedger
{
    private readonly Dictionary<string, TermMapping> _mappings = new();

    public record TermMapping(
        string SourceTerm,
        string TargetTerm,
        float Confidence,
        string FirstSeenChunkId,
        int LastSeenChunkIndex,               // Track recency
        int VotesForCurrentTarget,
        int TotalVotes,                       // Preserve history
        string? ChallengerTarget = null,
        int ChallengerVotes = 0,
        float ChallengerConfidence = 0);

    public void ProposeMapping(string source, string target, float confidence, string chunkId, int chunkIndex)
    {
        source = source.ToLowerInvariant().Trim();

        if (_mappings.TryGetValue(source, out var existing))
        {
            if (existing.TargetTerm == target)
            {
                // Same as current: accumulate votes
                _mappings[source] = existing with
                {
                    Confidence = Math.Max(existing.Confidence, confidence),
                    VotesForCurrentTarget = existing.VotesForCurrentTarget + 1,
                    TotalVotes = existing.TotalVotes + 1,
                    LastSeenChunkIndex = chunkIndex
                };
            }
            else if (existing.ChallengerTarget == target)
            {
                // Same as challenger: accumulate challenger votes
                var newChallengerVotes = existing.ChallengerVotes + 1;
                var newChallengerConfidence = Math.Max(existing.ChallengerConfidence, confidence);

                // Switch if challenger has >= 2 votes AND higher confidence
                if (newChallengerVotes >= 2 && newChallengerConfidence > existing.Confidence)
                {
                    // Swap: old current becomes challenger, challenger becomes current
                    _mappings[source] = existing with
                    {
                        TargetTerm = target,
                        Confidence = newChallengerConfidence,
                        VotesForCurrentTarget = newChallengerVotes,
                        TotalVotes = existing.TotalVotes + 1,
                        LastSeenChunkIndex = chunkIndex,
                        ChallengerTarget = existing.TargetTerm,  // Preserve old mapping as challenger
                        ChallengerVotes = existing.VotesForCurrentTarget,
                        ChallengerConfidence = existing.Confidence
                    };
                }
                else
                {
                    _mappings[source] = existing with
                    {
                        ChallengerVotes = newChallengerVotes,
                        ChallengerConfidence = newChallengerConfidence,
                        TotalVotes = existing.TotalVotes + 1,
                        LastSeenChunkIndex = chunkIndex
                    };
                }
            }
            else if (confidence > existing.ChallengerConfidence)
            {
                // New challenger replaces old challenger
                _mappings[source] = existing with
                {
                    ChallengerTarget = target,
                    ChallengerVotes = 1,
                    ChallengerConfidence = confidence,
                    TotalVotes = existing.TotalVotes + 1,
                    LastSeenChunkIndex = chunkIndex
                };
            }
        }
        else
        {
            _mappings[source] = new TermMapping(
                source, target, confidence, chunkId, chunkIndex,
                VotesForCurrentTarget: 1, TotalVotes: 1);
        }
    }

    public string? GetCanonicalTranslation(string source)
    {
        source = source.ToLowerInvariant().Trim();
        return _mappings.TryGetValue(source, out var mapping)
            ? mapping.TargetTerm
            : null;
    }
}
```

Dans la pratique, vous voulez aussi une dégradation du vote.

**Pourquoi cela est important pour le débugging:** Si la traduction tourne "factory reset " midM SK2document, vous pouvez différer le livret et voir exactement quand et pourquoi

```
chunk-12: "factory reset" → "Werkseinstellungen" (votes: 3, conf: 0.82)
chunk-47: challenger "Zurücksetzen" reaches 2 votes, conf: 0.91
chunk-47: SWITCH - "factory reset" → "Zurücksetzen" (old mapping preserved as challenger)
```

Aucune hypothèse. Non M SK1le modèle vient de décider ". Inspéctable, déterministeMST4 vérifiableM ST5

Cela vous donne:

- fluence locale (modèle manipule le phrasingM SK1
- cohérence globale (le preneur exécute la terminologieM SK1
- Coût limité (il n'est pas nécessaire de remanier -transmettre pour la cohérenceM SK2
- Décisions vérifiables (le preneur est inspectableM SK1

C'est pourquoi **cohérence terminologique** ne peut pas être résolu par "just plus de contexteM SK1

---


## Ce n'est pas la mémoire - Il s'agit d'une propagation de contraintes

Le CFCD le fait **non pas** donner la mémoire du modèle.

Il donne le *Systèmes* mémoire.

Le modèle:

- n'a pas d'État
- ne décide pas ce qui persiste
- ne possède pas le contexte

Le système:

- stockage des ancres
- applique les limites
- Date d'expiration de la salience
- contrôle explicitement la durée de vie

**Règles d'expiration** (déterministeMSC1 non modèleM SK2décided):

- **Temps-based:** les ancres expirent après `T` sans être renvoyé
- **Utiliser-based:** ancrages à impacts zéro `N` les fragments subséquents se détruisent
- **Contradiction-based:** Le contestant a ≥2 de votes ET dépasse la confiance actuelle par ΔM SK1 dans une fenêtre descendante des tronçons W

Cette distinction est tout .

```mermaid
flowchart TB
    subgraph Model["Probabilistic Model"]
        M1[Detect Salience]
        M2[Generate Output]
    end

    subgraph System["Deterministic System"]
        S1[Promote Anchors]
        S2[Store in Ledger]
        S3[Enforce on Generation]
        S4[Expire Stale Context]
    end

    M1 --> S1 --> S2
    S2 --> S3 --> M2
    S2 --> S4

    style Model stroke:#f59e0b,stroke-width:2px
    style System stroke:#22c55e,stroke-width:3px
```

### Le pipeline du CFCD

Voici le modèle avec le livret comme premier objet de la classe -:

```mermaid
flowchart LR
    S[Stream: chunks/sentences] --> M[Model proposes salience]
    M --> P[Promotion rules]
    P --> L[Ledger / Anchors]
    L --> G[Generation constrained by anchors]
    G --> O[Output]
    L --> E[Expiry rules]
    E -.-> L

    style L stroke:#22c55e,stroke-width:3px
    style P stroke:#22c55e,stroke-width:2px
    style E stroke:#22c55e,stroke-width:2px
    style M stroke:#f59e0b,stroke-width:2px
    style G stroke:#f59e0b,stroke-width:2px
```

Les boîtes vertes sont déterministes; les boîtes oranges sont probabilistes; le livret se trouve entre elles.

### Les changements dans la pratique?

Trois postes:

- Vous cessez de faire preuve d'une prose persistante.
- Vous persistez *Types d'ancrage*
- Vous traitez le livret comme une API, et non comme un prompt

Le prompt devient un *Voir* de la comptabilité publique, non le compte courant lui-mêmeM SK1

Ce n’est pas le contexte du livret; c’est un contrat.

### Qu’est-ce qui compte comme ancre?

Les ancres ne sont pas "texte important". Elles sont **typed, faits structurels** qui restreigne la génération:

- **Mappings terminologiques**: `factory reset` → `restore factory settings`
- **Entités et ID**: `ProductName`, `ModelNumber`, `UserID`
- **Constraints invariantes /**: "Le réglage requiert le bouton de maintout.
- **Préférences des utilisateurs / contraintes de style**: "Use formal toneM SK2 |
- **Les métadonnées de couverture**Échantillon sémantique
- **Versionnement**: `policyVersion: "cfcd-v1"`, `anchorSchemaVersion: 2`

Le point est que les ancrages ne sont pas de prose, ils sont de structure et le modèle écrit autour d’eux.

---


## L'alignement biologique

*Il s’agit d’une analogie.*

Les cerveaux ne reproductent pas l’ensemble du flux sensoriel.

Ils:

- Détecter la salience
- consolider de façon sélective
- Inhiber le bruit
- congeler les représentations une fois stable

Langue, Compétences motoriques, et perception reposent tous sur **transport restreint-à l'avant**, non récupération bruteM SK1

CFCD est le même principe, appliqué mécaniquementM SK1

| Système biologique
|------------------|-----------------|
| Attention (Qu'il faut prendre en considération) | Détection de la solitude MSC4fuzzyMSC5 |
| Consolidation ( ce qu'il faut se rappeler) | Promotion de l'ancrage
| Inhibition (Qu'est-ce qui doit être ignoré) | Règles d'expiration
| Rappeler (Qu'est-ce qu'il faut récupérer) | Enquête sur le livret

---


## Unification des paramètres

CFMoM et CFCD sont la même idée, vue de différents angles:

| Dimensions
|-----------|---------|
| Propriétaire unique | [Fuzziness restreinte](/blog/constrained-fuzziness-pattern) |
| Plusieurs soumissionnaires | [MoM Fuzzy restreint](/blog/constrained-mom-mixture-of-models) |
| LongM SK1Contexte horizontal | Dragage de contexte fuzzy restreint SSK3

Tous les trois respectent la même règle:

> **Probabilité propose. Le déterminisme persisteM SK1**

Une fois que vous avez internalisé cette règle, la plupart des systèmes "AI design " cessent d’être mystérieux

```mermaid
flowchart LR
    subgraph CFP["Part 1: Constrained Fuzziness"]
        P1[Single Proposer] --> C1[Constrainer] --> O1[Output]
    end

    subgraph CFMoM["Part 2: Constrained Fuzzy MoM"]
        P2A[Proposer A] --> CS[Consensus Space]
        P2B[Proposer B] --> CS
        P2C[Proposer C] --> CS
        CS --> C2[Coordination Constrainer] --> O2[Output]
    end

    subgraph CFCD["Part 3: Context Dragging"]
        T1[Time T] --> A1[Anchors]
        T2[Time T+1] --> A1
        A1 --> C3[Constrained Generation] --> O3[Output]
    end

    style CFP stroke:#22c55e,stroke-width:2px
    style CFMoM stroke:#3b82f6,stroke-width:2px
    style CFCD stroke:#8b5cf6,stroke-width:2px
```

---


## Pourquoi ce n'est pas le courant principal

Parce qu’il:

- Réduction des dépenses de calcul (pas de reprocessage -de traitement pour la cohérence
- Travaille avec de petits modèles (les ancrages font l’élévation lourde
- Il semble amusant dans une démonstration.
- produit moins de défaillances dramatiques (les faillites sont explicitesM SK1
- Il faut une réflexion sur les systèmes réels (et non pas seulement l’ingénierie rapide)

En d’autres termes, il optimise la production.

---


## Anti-Patterns ce remplace

| Anti--Pattern
|--------------|---------|---------------|
| **Faire fonctionner tout dans le contexte** | Coût non limitéM SK1 dilution de l’attention | Promouvoir uniquement ce qui surviendra à la sélection
| **Résumé récursif** | DriftM SK1 contradictions | Les ancrages sont structures, non prose |
| **J'espère que le modèle se souvient** | Aucune garantie | Le système possède la persistance |
| **Per-request full re-processing** | Les barèmes des coûts avec l'historique | Le livret persiste à travers les demandes
| **Langue naturelle "mémoire"** | Diffusion sémantique | Ancrages typed, cartographies explicites MSC3
| **One-sizeM SK1fits-all context** | Modèle de récupération des déchets ou d'alimentation en amidons | Établissement adaptatif provenant de la collecte classée

---


## Sous-strate de mise en œuvre: Éphemaire

[La plupart du temps, il est clair.Éphemaire](https://github.com/scottgal/mostlylucid.atoms) est le substrat qui rend pratique la CFCD. Si vous n’avez pas lu les articles de fond'

- [Fire and Don't Quite Forget](/blog/fire-and-dont-quite-forget-ephemeral-execution) - la philosophie
- [Bibliothèque d'exécution éphémère](/blog/ephemeral-execution-library) - la mise en œuvre
- [Signales éphémères](/blog/ephemeral-signals) Coordination dirigée par le signal -
- [Apprentissage des LRU](/blog/learning-lrus-when-capacity-makes-systems-better) - pourquoi la mémoire limitée est importante

| Primitif éphémère | Rôle du CFCD
|--------------------|-----------|
| **Signales** | Précision des candidats ( Modèle proposé
| **fenêtres limitées** | Aucune marge de manœuvre.
| **Règles d'évacuation** | L'oubli est explicite |
| **L'expiration des Sliding** | Le contexte inchangé expire automatiquement |
| **Propagation de signaux** | Les ancrages se déplacent sans mutation |

Épheméral ne "remmèreM SK1 Il **Décide ce qui est permis de se rappeler, et pour combien de temps**.

C’est exactement ce que demande le CFCD.

```csharp
public class CFCDCoordinator
{
    private readonly SignalSink _sink;
    private readonly TermLedger _ledger;
    private readonly TimeSpan _anchorLifetime = TimeSpan.FromHours(1);

    public void PromoteAnchor(string term, string translation, string chunkId, int chunkIndex)
    {
        _ledger.ProposeMapping(term, translation, 0.8f, chunkId, chunkIndex);

        // Emit signal for observability (key = chunkId for correlation)
        _sink.Raise($"anchor.promoted:{term}", key: chunkId);
    }

    public void ExpireStaleAnchors()
    {
        var cutoff = DateTimeOffset.UtcNow - _anchorLifetime;

        // Ledger entries older than cutoff without recent usage are removed
        // This is deterministic, not model-decided
        _ledger.ExpireOlderThan(cutoff);
        _sink.Raise("anchors.expired");
    }
}
```

---


## Sketch de mise en œuvre: Traduction des documents

La mise en place d’un pipeline de traduction complète des documents:

```csharp
public class CFCDTranslationPipeline
{
    private readonly ILlmService _llm;
    private readonly TermLedger _ledger;
    private readonly SignalSink _sink;
    private readonly int _seedChunks = 3;  // K: configurable seed window

    public async Task<TranslatedDocument> TranslateAsync(
        Document source,
        string targetLanguage)
    {
        var chunks = Chunker.Chunk(source, maxTokens: 500).ToList();
        var translated = new List<TranslatedChunk>();

        // Phase 1: Extract terminology candidates (first pass, fuzzy)
        // Seed from first K chunks: front-loads terminology, avoids churn later
        for (var i = 0; i < Math.Min(_seedChunks, chunks.Count); i++)
        {
            var chunk = chunks[i];
            var candidates = await _llm.ExtractTerminologyAsync(chunk);
            foreach (var term in candidates)
            {
                _ledger.ProposeMapping(
                    term.Source,
                    term.ProposedTranslation,
                    term.Confidence,
                    chunkId: chunk.Id,
                    chunkIndex: i);
            }
        }

        _sink.Raise("terminology.seeded");

        // Phase 2: Translate with ledger constraints
        for (var i = 0; i < chunks.Count; i++)
        {
            var chunk = chunks[i];

            // Get canonical translations for terms in this chunk
            var constraints = ExtractConstraints(chunk, _ledger);

            // Translate with constraints (model must respect ledger)
            var result = await _llm.TranslateWithConstraintsAsync(
                chunk,
                targetLanguage,
                constraints);

            // Update ledger with any new terms (deterministic rules)
            foreach (var newTerm in result.NewTerminology)
            {
                if (ShouldPromote(newTerm, _ledger))
                {
                    _ledger.ProposeMapping(
                        newTerm.Source,
                        newTerm.Target,
                        newTerm.Confidence,
                        chunkId: chunk.Id,
                        chunkIndex: i);

                    _sink.Raise($"anchor.promoted:{newTerm.Source}");
                }
            }

            translated.Add(result.Chunk);
        }

        return new TranslatedDocument(translated, _ledger.GetAllMappings());
    }

    private bool ShouldPromote(TermCandidate term, TermLedger ledger)
    {
        // Deterministic rules, not model judgment:
        // - Proper nouns always promoted
        // - Technical terms promoted if repeated
        // - Common words never promoted
        return term.Type == TermType.ProperNoun ||
               (term.Type == TermType.Technical && term.OccurrenceCount >= 2);
    }
}
```

---


## Conclusion de la réflexion

L'erreur que la plupart des systèmes d'AI font est de supposer que l'intelligence s'améliorera en se rappelant *plus*.

Dans la pratique, l’intelligence se mesure en décidant ce qu’il faut faire **n'avoir plus à réfléchir**.

La CFCD est la façon de le faire sans vous tromper.

---


## La série

| Partie | Pattern MSC2 Axe MSC3
|------|---------|------|
| 1 | [Fuzziness restreinte](/blog/constrained-fuzziness-pattern) Composante unique |
| 2 | [MoM Fuzzy restreint](/blog/constrained-mom-mixture-of-models) | Composantes multiples |
| 3 ≥| Traçage de contexte fuzzy restreint C'est ( cet article
| 4 | [Sommaire de l'image](/blog/constrained-fuzzy-image-intelligence) | Mise en œuvre pratique |

Les trois modèles partagent la même invariante: **Les composantes probabilistes proposent; les systèmes déterministes persistent**.

L'article 5 de la Loi sur l'immigration et le statut des réfugiés [Dix commandements de l'utilisation du LLM](/blog/tencommandments) . La [Architecture DiSE](/blog/dise-architecture-overview) les met en œuvre pour l'évolution du code. [Détection des bottes](/blog/botdetection-introduction) les met en œuvre pour la classification des demandes. [DocSummarizer](/blog/docsummarizer-advanced-concepts) les met en œuvre pour la recherche de documents. [ImageSummarizer](/blog/constrained-fuzzy-image-intelligence) les met en œuvre pour l'analyse d'images.

Domaines différents. Le même modèle. La même règleM SK2 [Les appareils de sauvetage du Doom](/blog/doomsummarizer-deep-research) implements context dragging for parallel long-form document generation - running summaries, negative promptsM SK3 entity continuityMska4 and drift detection maintain coherence across concurrent LLM calls Mska5

---


## Suivant: Mise en œuvre pratique

**Partie 4** est maintenant disponible: [Image Summarizer : Un moteur RAG d'images Fuzzy restreint](/blog/constrained-fuzzy-image-intelligence). Il met en œuvre tous les trois patrons dans une onde - basée sur un pipeline d’analyse de l’image M SK2ColorWave calcule les faits , VisionLlmWave propose MSC4 ImageLedger accumule des caractéristiques saillantes МSK5 et la sélection déterministe restreint le résultat [github.comM SK1scottgal/lucidrag](https://github.com/scottgal/lucidrag).