Back to "DoomSummarizer: DocSum marizer 's YoungerM SK2 Smarter Brother"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

AI C# Deep Research Knowledge Graph LLM Lucene RAG Time Boxed Tool

DoomSummarizer: DocSum marizer 's YoungerM SK2 Smarter Brother

Thursday, 29 January 2026

Recherche approfondie sans poches profondes.

Lorsque "Deep Research" a débarqué dans les outils d’AI de qualité supérieure , J’ai été curieuxM SK3 ce qu’est-ce que c’est?

DoomSummarizer exploite un flux de travail similaire,, mais sa conception optimise le "read + réduisantM SK3 le processus pour être principalement déterministe et localiséMSC4 avec le Modèle langage large (LLMMST6 employé principalement à la synthèseMSL7

Dans cette approche, la force de l’étape de réduction élimine le besoin d’un modèle gros et coûteux pour produire des résultats satisfaisants.

En particulier, J’avais déjà plusieurs éléments de base essentiels, y compris des graphiques de connaissances multiples - la récupération de sources M SK3 l’extraction d’entités , les graphes de savoir MSC5 et le classement fondé sur - qui sont partagés avec lucidRAG et la série DocSummarizer

La composante manquante n’était pas un manque de capacités, mais plutôt une compréhension de la façon d’appliquer efficacement ces éléments existants.

Dans les outils commerciaux, le terme « recherche approfondie » signifie habituellement un processus de travail qui prévoit une approche de recherche.

Une grande partie de la valeur est attribuable à l’amélioration des sources d’entrées :

Exemples: Recherche approfondie OpenAI, Recherche approfondie sur les gémins, et Recherche approfondie sur la perplexité (appelé aussi “Mode de recherche” dans leur interface

DoomSummarizer suit le même processus de travail, mais ilM SK1 est conçu de telle sorte que la plupart des “ lectures + réductionsMSC4 travaux sont déterministes et locauxMST5 et le LLM est utilisé principalement pour la synthèseMSL6

Si l’étape de réduction est forte, vous n’avez pas besoin d’un modèle gros et coûteux pour obtenir un bon résultat.

Entre lucidRAG et la série DocSummarizer, J'ai déjà eu la plupart des éléments de base: multiM SK2 recherche de sourcesMSC3 extraction d'entitésMST4 graphiques de connaissancesMSV5 emplacementMSS6 classement fondé sur le MSV7

La pièce manquante était't capacité. Elle était orchestration. Comment prendre tous ces signaux et les fusionner en quelque chose cohérent avec un petit modèle?

Que's DoomSummarizer . Nomné après le scrolling du doom, parce qu’il tourne de la sorte que vous n’avez pas à le faire.

Mais cet article ne traite pas de l’outil, mais des idées qui le font fonctionner.

Mise à jour de GitHub

Il s'agit de Partie 5 de la série DocSummarizer.

Si vous voulez les travaux de fond d’abord:

Il s’agit également d’un Outil encadré du temps.


L’idée de base: RAG réduit

Le RAG standard fait déjà la récupération sémantique des documents de tronçons.

La douleur est le dernier pas.

Qu'arrive-t-il si vous faites plus de travail? précédemment Le LLM voit quelque chose.

Il s’agit de l’exemple suivant : Réduire avant de produire. Prendre les documents bruts et les réduire de façon déterministe à leurs signaux essentielsM SK1 embeddings , ranks

flowchart TD
    subgraph REDUCE["REDUCE: Distil to Signals"]
        Q[Query] --> Decompose[Composite Decomposition]
        Decompose --> S1[Subquery 1]
        Decompose --> S2[Subquery 2]
        S1 & S2 --> Fetch[Multi-Source Fetch]
        Fetch --> Embed[ONNX Embed Each Item]
        Embed --> Rank[6-Signal RRF Fusion]
        Rank --> TextRank[TextRank Extraction]
        TextRank --> NER[Entity Extraction]
        NER --> Profile[Entity Profile Vectors]
        Profile --> Segments[Salient Segment Extraction]
    end

    subgraph SYNTH["SYNTHESIZE"]
        Segments --> Standard["Standard Path - 1 LLM Call"]
        Segments --> LongForm["Long-Form Path - N+3 LLM Calls"]
    end

    style REDUCE fill:#1a1a2e,color:#e0e0e0
    style SYNTH fill:#162447,color:#e0e0e0

La phase de réduction est déterministe: embeddings , ranking, extraction d’entitésMSC3 TextRankM SK4 cotation des segmentsMST5 Aucun appel LLMMSL6

La synthèse est la seule étape du LLM. Pour une demande standard, les signaux réduits sont suffisamment propres pour Un seul appel Doit le travail. Pour les documents longsM SK1form document, un sentinel planifie la structure et le modèle principal génère des sections parallèlesN+3 appels pour les sections N).

Pour plus de détails sur ce modèle, voir RAG réduit.

Phase de la carte: De la demande à des sources

Avant que rien ne soit réduit, la demande doit devenir des actions de recherche.

Un petit modèle sentinel local (0.6B dans mon casM SK1 mode JSON, température 0.1) interprète la demande brute en une intention structurée.

flowchart TD
    Q["User Query"] --> Sentinel["Sentinel: JSON Interpretation - categories, intent, entities, - temporal hints, tone"]
    Sentinel --> Router["Source Router - YAML category → source mapping"]
    Router --> S1["gnews:AI safety"]
    Router --> S2["search:AI regulation"]
    Router --> S3["bbc:technology"]
    Router --> S4["reddit • hn"]
    S1 & S2 & S3 & S4 --> Fetch["Parallel Fetch - circuit breaking + rate limiting"]
    Fetch --> Merge["Merge + Deduplicate - → reduce phase"]

    style Sentinel fill:#1e3a5f,color:#e0e0e0
    style Router fill:#0d3b2e,color:#e0e0e0

Le sentinel extrait des champs structurés:

  • Catégories thématiques (avec pondérations de confianceM SK1
  • Tendance de la demande (nouvelles, QCM SK2 rechercheMST3 comparaisonMSS4 commentMSSS5
  • Sensibilité temporelle (breaking / aujourd’hui / semaineMSC3
  • Entités désignées
  • Pour les questions composées: sous-questions décomposées M SK1avec pronons résolus )

Choix de la source se produit en six phases:

  1. Sources explicites: l'utilisateur a dit "from HackerNews" → hn va directement dans
  2. Demandes de recherche: le sentinel ' les termes de recherche optimisés deviennent vibes- les appels API admissiblesM SK3DuckDuckGoMSC4 BraveMST5 Google News RSSMst6
  3. Répartition des catégories: les pondérations thématiques des flux RSS par l'entremise de la configuration YAML . Une demande concernant " la réglementation AI " les voies vers les flux techniques et Programmes d'information sur les politiques
  4. Enrichissement de la recherche: research ou deep_dive intentions ajouter archive
  5. Enrichissement de l'entité: les entités désignées de l'NER obtiennent leurs propres demandes gnews | gnews:OpenAI)
  6. Étage de la diversité: si les sources choisies sont inférieures à 3 les défauts de remplir

Les identifiants de source sont obtenus parallèlement à la rupture du circuit de source.

Vibes modifient les termes de recherche avant qu’ils ne soient saisis par une API. Par exemple, --vibe doom Questions de préfixes avec "concernant les problèmes risque d’entraîner des problèmes dans le, remanier ce qui revient avant tout classement

Si vous voulez l'arrière-plan des bits de résilience, voir Utilisation de Polly pour les retraités (blocateurs de circuits ) et Pression arrière dans les systèmes d'attente (limitation du taux et pression de reculM SK1

Déconstruire la demande

La plupart des systèmes de recherche traitent : "Qu'est-ce qui est nouveau dans le domaine de la sécurité de l'AI et quelles sont les dernières réglementations?

Le sentinel décompose les demandes combinées:

{
  "is_composite": true,
  "subqueries": [
    "What's new in AI safety?",
    "What are the latest AI regulations?"
  ]
}

L’option intéressante est ce qui se passe ensuite. Chaque sous-question reçoit son propre emplacement ONNX (voir ONNX: Modèles ML exploités localement). Lorsque j’obtient des points pour les articles la similitude maximale des cosine sur toutes les embeddings de sous-question, non la moyenneM SK1

Pourquoi le maximum? Un article qui répond parfaitement M SK1 Sécurité de l’AI " ne devrait pas être pénalisé' pour n’avoir rien dit au sujet des règlementsMST4 MST5 L’évaluation l’enfouierait sous un match partiel moyenMSS6 La similitude maximale signifieMSSS7 si un article souffre Toute part of your question, it rises. The alternativeM SK2 averagingMSC3 rewards bland articles that vaguely touch everything .

Écoulement de signaux hétérogènes

J’ai six signaux de classement. Ils ont des échelles complètement différentesM SK1

flowchart LR
    subgraph Signals
        BM25[BM25 - Keyword Match]
        Fresh[Freshness - 48h Half-Life]
        Auth[Authority - HN/Reddit Score]
        QSim[Query Similarity - Cosine]
        Vibe[Vibe Alignment - Cosine]
        Qual[Quality - Clickbait Detector]
    end

    subgraph RRF[RRF Fusion]
        direction TB
        R[Rank Each Signal - Independently]
        F["score = Σ weight × 1/(60 + rank)"]
    end

    BM25 & Fresh & Auth & QSim & Vibe & Qual --> R --> F

    style RRF fill:#1e3a5f,color:#e0e0e0

HN points vont jusqu'à des milliers. La similitude cosine est M SK1 à 1. La fraîcheur décline exponentiellement. Vous pouvezMSC4 ne pas les ajouter de façon sécuritaireMska5 Les échelles sont incompatiblesM Ska6

Le signal clé ici est BM25 à travers plusieurs champs (BMM SK2F). Si vous voulez l'arrière-plan sur BMCSK4 voir DocSummarizer Part 3.

Fusion de rang réciproque (Cormack et coll. Établissement d'un programme de réseau communautaire: score = Σ weight × 1/(k + rank) (avec k=60).

Si vous voulez l'arrière-plan complet sur RRF, Partie 3 le couvre. C'est là que le tournement est Les poids s'adaptent au type de demande. Le sentinel détecte l’intention , et le scoreur se transforme en lui-même

  • Enquêtes en ligne de temps ("Qu'est-ce qui s'est passé aujourd'hui?
  • Questions des explicateurs ("Comment fonctionne l'informatique quantique?
  • Roundups et comparaisons ont leurs propres profils réglés.

Vibes en tant que dimension de récupération

Ce qui a commencé comme une joke. Maintenant, c’est la fonction préférée de ' .

A "vibeM SK1 n’est pas't mot de recommandation prompte . Il signal de classement premier- embedded into the retrieval pipeline:

flowchart LR
    V["--vibe doom"] --> Expand["Query Expansion - 'concerning risks issues in...'"]
    V --> Embed["Vibe Embedding - 'vulnerability breach layoffs - recession crisis warning...'"]
    Embed --> Score["Cosine Similarity - per article"]
    Score --> RRF["RRF Signal - weight: 0.4"]

    style V fill:#8b0000,color:#e0e0e0

Trois things happen when you set a vibe:

  1. Expansion de la demande - la recherche est précédée d'un moodM SK1qualifications appropriées
  2. Emplacement de la vibration Le texte représentatif - est incorporé comme cible 384-dim
  3. Signale de classement - articles codés par la similitude des cosines avec l'incorporation de la vibe

Les vibes personnalisées fonctionnent identiquement. --vibe "contemplative philosophical"- Votre texte devient à la fois le préfixe de la demande et l’objectif de classement . Le système n’obtient pas de distinction entre les données prédéfinies et les données personnalisées . Il intègre tout ce que vous lui donnez.

Profils d’entités, Nombre des entités

Voici une erreur que j’ai faite d’abord.

Deux articles mentionnent à la fois "CalifornieM SK1

  1. Le bureau de la Californie annonce l’équipe de sécurité
  2. "Les agriculteurs de noix de Californie sont confrontés à la sécheresse "

Cote des entités partagées: M SK1 Par conséquent liées! Obviellement erronée .

La solution consistait à considérer les entités comme des vecteurs, et non comme des chaînes.

Il s’agit de Le modèle de fuzziness restreintLe modèle NER propose des entités, mais la pondération déterministe décide de ce qui importe.

Chaque document reçoit un Profil de l'entité pondérée Encodage du vecteur (a 384-dim qui les entités apparaissent et leur caractère distinctif):

weight = TF × IDF × confidence × type_weight
profile = L2_normalize(Σ entity_embedding × weight)
flowchart TD
    subgraph Doc1["Article: OpenAI Safety Team"]
        E1["OpenAI (ORG) - IDF: high - weight: 2.1"]
        E2["California (LOC) - IDF: low - weight: 0.3"]
        E3["Safety Team (MISC) - IDF: high - weight: 1.8"]
    end

    subgraph Doc2["Article: Almond Farming"]
        E4["California (LOC) - IDF: low - weight: 0.3"]
        E5["Almond Farmers (MISC) - IDF: high - weight: 1.9"]
        E6["Drought (MISC) - IDF: medium - weight: 1.2"]
    end

    Doc1 --> P1["Profile Vector - Dominated by OpenAI + Safety"]
    Doc2 --> P2["Profile Vector - Dominated by Farming + Drought"]
    P1 -. "low similarity" .- P2

    style Doc1 fill:#1a1a2e,color:#e0e0e0
    style Doc2 fill:#2d1a2e,color:#e0e0e0

IDF est la clé. M SK1Californie" apparaît en tonnes d’articles - faible IDFMST4 signal faibleMSSK5 ♫"OpenAIMSC7 est distinctifMSL8 haute IDF~, domine le profilMSR10 Maintenant les recherches de similitude fonctionnentMSR11 OpenAI regroupe des articles ensembleM SR12 Les articles agricoles regroupent séparémentMSL13 Le partage MSR14ClifornieM SR15 devient bruitM RS16

La partie intelligente: TF saturant. Au lieu de compter le nombre de mentions brutes 1 + log(mentions). Une entité mentionnée 50 fois dans un long article ne reçoit pas

La découverte de graphiques sémantiques

Les profils d’entités ne servent pas uniquement à comprendre les documents. dimension de récupération. Chaque documen 🥱tM SK2 son profil d'entité est indexé dans un graphe de l'HNSW.

Si vous voulez plus de détails sur HNSW et DuckDB VSS, voir GraphRAG Partie 2: Minimum viable.

flowchart TD
    subgraph Retrieval["Three-Layer Retrieval (UNION)"]
        L1["Lucene FTS - keyword matches"]
        L2["Embedding HNSW - semantic similarity"]
        L3["Entity Profile HNSW - entity fingerprint match"]
        L1 & L2 & L3 --> Union["Union of all candidates"]
    end

    subgraph Enrich["Post-RRF Enrichment"]
        Top["Top 5 Ranked Items"] --> Agg["Aggregate Profile - mean of entity profiles"]
        Agg --> Graph["HNSW Search - min similarity: 0.30"]
        Graph --> Related["+3 Related Articles - scored below existing items"]
    end

    Union --> RRF["RRF Fusion"] --> Enrich

    style Retrieval fill:#1a1a2e,color:#e0e0e0
    style Enrich fill:#0d3b2e,color:#e0e0e0

Cela fonctionne en deux étapes:

Au cours de la recherche: lorsque le sentinel extrait des entités de la demande 2+, un profil d'entité de demande est calculé à l'aide de la même formule TFM SK3IDF. Ce dernier recherche dans l'indice HNSW les articles comportant des empreintes digitales similaires de l'entityMSC5 avec une similitude minimale de \0.25. Un article sur les préoccupations liées à la sécurité de |"OpenAI " surfaces même s'il n'y a jamais mention des termes exacts de la questionMSSK9 parce que son profil d’entités ( dominée par un niveau élevé

Après le classement: les articles classés au premier rang 5 ont leurs profils d'entité en moyenne dans un vecteur agrégéM SK2 Ce vecteur àgrégé recherche des articles connexes que le mot clé et les couches d'implantation ont complètement manquées. Les articles trouvés reçoivent une note juste inférieure à l'article classé le moins bas (×0.9) et sont marqués comme découverts "par l’entremise d’entitésM SK1. Cela attire les sources primaires auxquelles les articles de presse font référence, mais ne citent pas verbatimment

Trois couches de récupération se fusionnent par l'entremise d'une union: Les mots clés Lucene correspondent ∪ L'intégration correspond à l'HNSW ∪ Le profil de l'entité correspond à HNSWM SK3 La union est délibérément plus large que l'intersectionMSC4 Elle saisit les éléments sur lesquels apparaîtrait un signal unique quelconque.

Le chemin de chute (pour corpora sans profils d'entités encore ) utilise l'entité SQL coM SK2contrôle des occurrencesHAVING shared_count >= 2). Il fonctionneM SK1 mais il 's O(NMSC4 au lieu d’OMska5log NM Ska6 Le --backfill-entity-profiles commande migre les corpora existants vers le chemin HNSW.

Synthèse standard: Un appel LLM

C'est le chemin normal. scroll "AI safety and regulation" affiche ce message. Après la phase de réduction distille vos sources en segments classésM SK1 en doubles , entités- segments profiléesMSC4 la synthèse est un appel uniqueMNK5

flowchart TD
    subgraph REDUCE["Reduce Phase (ALL DETERMINISTIC)"]
        Items[Fetched Items] --> Embed[ONNX Embed All Items]
        Embed --> RRF[6-Signal RRF Fusion]
        RRF --> TR[TextRank Compression]
        TR --> Seg[Segment Extraction + Salience Scoring]
        Seg --> Dedup[Deduplication + Relevance Floor]
    end

    subgraph SYNTH["Synthesis (1 LLM CALL)"]
        Dedup --> Rerank["Semantic Re-Rank - by query similarity"]
        Rerank --> Budget["Smart Evidence Budgeting - redistribute unused chars"]
        Budget --> Gen["Single LLM Call - with curated evidence"]
        Gen --> Output[Final Summary]
    end

    style REDUCE fill:#0d3b2e,color:#e0e0e0
    style SYNTH fill:#1e3a5f,color:#e0e0e0

La phase de réduction fait le travail ardu. Au moment où le LLM voit quelque choseM SK1 il reçoit:

  • Seulement les articles de haut niveau: rang de pertinence à 30% du meilleur article's cote
  • Diversité des sources: est limité à 3 des articles par domaine pour les demandes de redressement
  • Semantic re-ranking: items re-ordered by cosine similarity to the query embedding
  • Budgetage des preuves intelligentes: les articles courts donnent un budget de caractère inutilisé aux articles longs , ainsi que l’espace de preuve n’est pas gaspillé
  • Blocs de preuve structurés: [E1] Title | topic | relevance avec le contenu réduit au budget

Une LLM appelle ., ce qui correspond à la rémunération de Réduction du RAG: sélection , classement, dédoublementM SK3 et budgétisation tout se produit avant que le LLM ne constate quelque chose

Production parallèle restreinte de longs pipelines

Long-form M SK1--template blog-article) est une bête différente . Vous'génerez un document de sections multiplesM SK3 à partir de douzaines de sourcesMSC4 et vous avez besoin d’une cohérence entre les sections sans appels coûteux de compression LLM

La réponse est la suivante : dragge de contexte fuzzy restreint. Il s'agit de mécanismes déterministes qui conservent la cohérence des sections croisées - tout en permettant une génération parallèle

flowchart TD
    subgraph Phase1["Phase 1: Evidence Preparation (DETERMINISTIC)"]
        Articles[Top 20 Articles] --> Segments[Chunk into Segments]
        Segments --> Salience[Score Salience per Segment]
        Salience --> EmbedSeg[Embed Each Segment]
    end

    subgraph Phase2["Phase 2: Document Planning (1 SENTINEL CALL)"]
        EmbedSeg --> Summary[Build Evidence Summary]
        Summary --> Sentinel["Sentinel: Generate Outline - with theme keywords per section"]
        Sentinel --> EmbedThemes[Embed Section Themes]
    end

    subgraph Phase3["Phase 3: Evidence Assignment (DETERMINISTIC)"]
        EmbedThemes --> Assign["Score: 60% theme similarity - + 25% salience + 15% relevance"]
        Assign --> Dedup[Cross-Section Deduplication]
        Dedup --> Gate["Quality Gates - • Min salience 0.35 - • Min theme sim 0.45 - • Max 2 per source per section"]
    end

    subgraph Phase4["Phase 4: Section Generation (N+2 LLM CALLS)"]
        Gate --> Intro["Intro (sequential)"]
        Intro --> Body["N Body Sections (parallel) - max 3 concurrent"]
        Body --> Conclusion["Conclusion (sequential)"]
    end

    subgraph Phase5["Phase 5: Validation (DETERMINISTIC)"]
        Conclusion --> Validate[Citation Validation - URL + Entity Grounding]
    end

    subgraph Phase6["Phase 6: Assembly (DETERMINISTIC)"]
        Validate --> Assemble[Final Document Assembly]
    end

    style Phase1 fill:#0d3b2e,color:#e0e0e0
    style Phase2 fill:#1e3a5f,color:#e0e0e0
    style Phase3 fill:#0d3b2e,color:#e0e0e0
    style Phase4 fill:#1e3a5f,color:#e0e0e0
    style Phase5 fill:#0d3b2e,color:#e0e0e0
    style Phase6 fill:#0d3b2e,color:#e0e0e0

Comptez les appels LLM: 1 (plan d’ensemble sentinelM SK1 + 1 (introduction N (sections du corpsM SK1 + 1 (conclusionM SK1 = N+3. Quatre des six phases sont déterministes.

Traçage de contexte fuzzy restreint

Le problème avec la génération de sections parallèles est la cohérence. Si les sections ne savent pas ce que d’autres sections ont ditM SK2 vous obtiendrez une répétition et un débordement . La solution habituelle consiste à produire une génération séquentielle avec le contexte complet. Celle-ci

En revanche, chaque section Contexte restreint qu’elle a été construite de façon déterministe

flowchart LR
    subgraph Context["Per-Section Context (ALL DETERMINISTIC)"]
        RS["Running Summary - 1400 char budget - recent 2 sections: full - older: heading only"]
        NP["Negative Prompts - 'Do NOT discuss: X, Y, Z' - from covered concepts"]
        EC["Entity Continuity - re-introduce entities - last seen 2+ sections ago"]
        Props["Propositions - ~15 atomic facts - per section"]
        Evidence["Curated Evidence - max 12 segments - quality-gated"]
    end

    Context --> LLM["LLM generates - with full awareness - of document state"]

    style Context fill:#1a1a2e,color:#e0e0e0
  • Résumé en cours: après chaque section , la partie supérieure M SK2 le segment des preuves de culpabilité (200 les chars MSC4 est enregistrée МSK5 Les sections récentes MST6 sont pleinement digestées M ST7 les sections plus anciennes sont placées sous la rubrique
  • Invitations négatives: les concepts couverts sont extraits ( les noms de famille appropriés M SK2 les termes techniques , les mots clés de la positionnement "Ne discutez pas de ces sujets (a déjà été examiné): XM SK3 YMST4 ZMst5
  • La continuité de l'entitéLes entités qui ne sont pas mentionnées dans les sections 2+ reçoivent une balise pour la réintroduction - introduction "ReM SK1introduire, s’il y a lieu:EntitéMNK3 (la dernière mentionnéeMRK5section SNK6
  • Détection de la dérive: après que chaque section a été généréeM SK1 ses premiers caractères 1000 sont incorporés et comparés par rapport au plan' l'incorporation du thème de la section

Dans le mode parallèle, l'intro génère la première M SK1setting the baseline), les sections du corps se déroulent simultanément (up to 3 via SemaphoreSlim pour capter la cohérence, chacun excluant les sujets d’intro, mais non l’un de l’autreM SK1 et la conclusion se termine (excluant tout ).

Le mode séquentiel donne une cohérence plus étroite (chacune des sections exclut tous les concepts antérieurs cumulativement ), mais la parallèle est MSC2x plus rapide pour les grands documents MSC3

Assignation de la preuve: Le coeur du RAG réduit

Chaque section a besoin de preuves, mais pas Toute preuves. Chaque segment obtient une note compositeM SK1 60% similitude thématique (distance de cosine à la section'incorporation du thème de ), 25% salience (de quelle façon le segment est-il informatif? 15% pertinence de l'article (à quel point l’article de source est pertinent dans son ensemble ). Cette notation est entièrement déterministe M SK2 Aucune LLM ne décide ce qui est pertinent '

Puis les portes:

  • Sous-sol de Salience Les segments de qualité (0.35): faiblesM SK1 ne parviennent jamais à la LLM
  • Soutien à la similitude des thèmes (0.45): hors
  • Déduction de section croisée- (0.80 cosine ): le même fait n’apparaît pas deux fois
  • Per-cap de source (2 segments par article par section
  • Connaissance du rôle de la Section: les sections d’intro imposent des pénalités au détail technique (-0.3); les dernières sections le récompensent
  • Porte de cohésion de la demande (0.30): les éléments de preuve doivent être liés à la demande initiale , et non seulement au thème de la section

Le nombre de mots visés par le LLM est ajusté en fonction de la qualité des données probantes. Données solides ( Satisfaction ≥ | | 3 | 4 | Sources | , | 5 | 6 | Segments |) | 8 | Nombre total de mots | SMC9 | Données faibles ◦ ( | Satisfiance | 11 | 12 | Épaisse | 13 | 14 | 15 | de l'objectif | 16 | Cela évite les hallucinations lorsque les données sont minces | 17

Extraction de la proposition: DenseM SK1X dans la pratique

Avant que les éléments de preuve ne parviennent au LLM,, il ' est atomisé en propositions ( inspirées par le Papier de recherche dense-X). Chaque segment est divisé en six types de faits atomiques Les demandes d'indemnisation doivent être présentées dans les délais prescrits. (affirmations générales fondées sur des faits Les quotes-parts (direct de la source), Statistiques (nombre et métriques ), définitions ("X est YM SK1 Processus (stageM SK1par -step), et les faits de l'entité désignée (concentré sur une entité particulièreM SK1

Chaque section reçoit des propositions ~15 de , reproduites à travers les sections au moyen d'une similitude sémantique.

Au moment où le LLM écrit une section,, la phase de réduction l’a donnée:

  • Un titre et un thème clairs
  • Segments de preuve curatés (qualité-gatedM SK2deduplicated )
  • ~15 propositions atomiques
  • Sommaire des sections précédentes déjà couvertes
  • Les incitatifs négatifs pour ce qui non pas à répéter
  • Orientation de la continuité des entités

Un petit modèle peut faire un excellent travail avec ce type de préprocessage.

TextRank: Sommaire déterministe

Lorsque les articles sont trop longs pour le pipeline de la preuve, il faut les comprimer. Mais je ne veux pas consacrer un appel LLM à une résumation.

TextRank (Mihalcea & TarauM SK2 2004) le fait de façon déterministe:

flowchart LR
    Text[Article Text] --> Split[Split into Sentences]
    Split --> EmbedS[Embed Each Sentence]
    EmbedS --> Graph["Build Similarity Graph - (cosine > 0.15 = edge)"]
    Graph --> PR["PageRank - (20 iterations, d=0.85)"]
    PR --> Select["Select Top-K - in Original Order"]

    style Graph fill:#1e3a5f,color:#e0e0e0

Chaque phrase obtient une embedding. Les similitudes par pairs au-dessus de M SK1 deviennent des bordures de graphe . PageRank trouve le plus Centre sentences, celles qui sont les plus reliées à tout le reste de la documentation. Celles-ci représentent le document le mieux

Le détail clé: les phrases sélectionnées sont retournées dans l'ordre du document original. Cela préserve le flux narratif. Vous obtiendrez un résumé cohérent , pas une paire aléatoire de phrases importantesM SK3

Aucun appel LLM. Exécute en millisecondesM SK1 La similitude des cosine est SIMD-accélérée par TensorPrimitives (System.Numerics.Tensors) (AVX2, AVX≥-512, ou ARM NEONM SK4 choisi au moment du démarrage

Un-Hop Lien suivant

Les articles renvoient à d’autres articles. Ces références contiennent souvent les meilleurs éléments de preuve - la source principale que récapitule un article de presse .

DoomSummarizer suit les liens, mais sélectivementM SK1 Chaque lien candidat reçoit une note:

link_score = 0.7 × query_relevance(anchor_context) + 0.3 × segment_salience

Lorsque la salience des segments est combinée

  • Position (60%) - pyramide inverséeM SK2 les paragraphes précédents sont plus importants
  • Substances Longueur du paragraphe et densité de l'information

Liens en bas d’un plancher de pertinence (0.15) sont passés à l’écart. Le système suit la pyramide héuristice journalistique inversée : les liens importants ont tendance à apparaître tôt dans le bon tempsMSC3 les articles écritsM SK4

Les résultats sont cachés avec les haches de contenu et ETags. Les secondes exécutions sont rapides . Voir Cache des réponses, ETags , et Demandes conditionnelles.

Mode Crawl: Établir une base de connaissances locale

Tout ce qui a été décrit jusqu'à présent suppose le téléchargement du Web. Mais vous pouvez faire passer complètement le web.

crawl intégre un site Web dans une base de connaissances locale. Il fait une largeur-premier crawl MSC2BFSM SK3 à partir d’une URL de semencesMska4 en ce qui concerne la profondeur et les limites des pagesM Ska5 avec une limite de vitesse adaptative qui mesure le retard fondé sur les temps de réponse du serveurMka6

doomsummarizer crawl https://docs.example.com --name example-docs --depth 3 --max-pages 200

Everything gets persisted: full content, ONNX embeddingsMSC2 entity profiles , SQLite FTSM SK4 keyword indexes Mska5fullMSKA6text searchMske7 sentiment and topic scores (computed via embeding anchorsSMA9 no LLMSMAP10 Incremental reMSA11crawls send If-None-Match / If-Modified-Since headers. pages non modifiées retournent HTTP 304 et skip reprocessing. Pour les serveurs sans support ETagM SK3 SHAMNK4 content hashes catch duplicatesMSC5

Une fois crawlé, la demande est entièrement hors ligne:

doomsummarizer scroll "how does authentication work?" --name example-docs

L'article 5 de la Loi sur l'immigration et le statut des réfugiés --name routes d'affichage vers le KB local au lieu de sources Web. Les mêmes trois échantillonsM SK1 feux de récupération des stratà ̈res : FTS5 complets M SK4 prétexte préliminaire M Sk5 filtre M sk6 intéglementation de la recherche HNSW , profil de l'entité Recherche HNSD Mtk8 Il s'agit d'une unionM Sk9 fondée et rangéeM sk10 Réduction du pipeline identique M sc11 synthèse identique~ M sc12 Aucun réseau n'est exigéM sc13

L'entreposage est léger: SQLite pour les métadonnées et FTS5 indices , DuckDB avec l'extension VSS pour les index vecteurs HNSWM SK3 Aucun service externeMSC4 aucun DockerMST5 aucune clé APIMSP6 Une base de connaissances crawlée de centaines de pages se trouve dans quelques mégabytes et des demandes en millisecondesMSV7

Mettre les choses ensemble

doomsummarizer scroll "AI safety and regulation" --vibe doom --debug

Composite query detected: 2 subqueries
  • What's new in AI safety?
  • What are the latest AI regulations?

Searching...
├─ Lucene: 18 keyword matches (regulation^3, safety^2)
├─ Embedding: 12 semantic matches (max-sim across 2 subqueries)
├─ RRF fusion: 22 candidates, 6 signals
├─ Entity HNSW: +3 related via entity profiles
├─ TextRank: compressed 4 long articles
└─ Final: 12 items

Long-form: Phase 1 - 187 segments from 12 articles
Long-form: Phase 2 - "AI Safety Landscape" - 5 sections
Long-form: Phase 3 - Evidence assigned (cross-section dedup: 8 removed)
Long-form: Phase 4 - Generating sections...

Les idées qui l'ont fait fonctionner

Il s’agit des points de vue suivants :

  1. Réduire avant de produire: le chemin standard n’a besoin que d’un appel LLM 1 parce que la conduite fait tous les travaux de levage lourd de façon déterministe RAG réduit est le modèle, les embeddings, la PageRank, l’héuristique et les portes de qualité produisent des intrants aussi propres que les petits modèles peuvent les synthétiser.
  2. Sentinel-route de source dirigée: un petit modèle interprète les demandes dans l’intention structurée , puis YAMLM SK2 le routage dirigé sélectionne et vibe la route- qualifie les sourcesMSC4 The sentinel is cheap enough to call on every query
  3. Maximum de similitude pour les demandes combinées: donM SK1t scores moyens de la sous-question, prendre le meilleur match . Un article portant sur une partie de votre question est mieux qu'une moitiéMSC4matcher toutMST5
  4. Combinez les rangs, sans cotes: Le RRF vous permet de fusionner des signaux avec des échelles incompatibles . Autorité, fraîcheurM SK3 similitude d'incorporationMNK4 alinéa vibeMMK5 simple rang et fusionnageMRK6
  5. Vibes comme embeddings: tout texte peut être une dimension de récupération . l’incorporer , la coter contre elle M SK3 le pondérer dans la RRF
  6. Profils d'entités en tant que vecteurs: IDF - Emplacements d'entités pondéréesM SK2 non comptage des chaînes d'entité. Les entités rares dominent le profilMSC4 les entités communes deviennent bruiteusesMNK5 et la recherche HNSW détecte des articles connexes dans O
  7. Traçage de contexte fuzzy restreint: Gestion du contexte déterministe permet la production de sections parallèles. Sommaires en coursM SK1 prompts négatifs, continuité d'entités , et détection de dérive maintenir la cohérence sans appels de compression LLMMSC4
  8. Déterministe lorsque possible: des six phases de forme longues -, quatre sont déterministesM SK3 Le tableau TextRank remplace la sommation du LLMMSC4 L'attribution des preuves remplace le choix du LLSMSL5

Ressources

Articles connexes

En outre

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.