# StyloBot Release Series: Apprentissage pour accroître la vitesse

*Haut de la page: c'est pour les nerds . Il' est une plongée technique profonde dans le StyloBotM SK3 son système d'apprentissage adaptatif MSC4 mises à jour de l'EWMAMNK5 seuils d'hysterèseMRK6 cache du verdictMMK7 chiens de surveillance des variationsMEK8 avec code réel de `Mostlylucid.BotDetection` et des pointeurs vers la machine équivalente-construit l’apprentissage de façon à ce que les lecteurs ML disposent d’un point d’entrée . Si vous voulez la placement de l’élévateur, lisez les articles précédents de diffusionM SK3 si vous voulez savoir comment la mémoire des quatre niveauxMSC4 transforme le trafic répétitif en sous-référenceMST5millisecondes décisions tout en se récupérant de faux positifsM ST6 lire surM st7*

> ## DÉCLARATION
> 
> Il s’agit d’un projet de travail dans la série de mise à jour StyloBot.

> **StyloBot Release Series**
> 
> 1. [**Comportement, Non identité**](/blog/stylobot-fingerprint) - pourquoi StyloBot modele les clients de façon comportementale
> 2. [**Behaviour-Aware ASP.NET UI**](/blog/behaviour-aware-ux) - le serveur - remet la surface sur ce résultat de détection
> 3. [**Trouver et rétablir une croissance sans limites dans les services longs-Running .NET**](/blog/stylobot-release-reliability) - la discipline de fiabilité qui maintient le moteur borne dans la production
> 4. [**Behaviour-Aware TypeScript UI**](/blog/typescript-sdk) - ExpressM SK1 Fastify, et composants de navigateur
> 5. [**L'architecture de la Sidecar**](/blog/sidecar-architecture) - comment le moteur de détection se connecte aux piles NET non -.
> 6. **Apprentissage pour devenir plus rapide** - le système d'apprentissage adaptatif , quatre- mémoire de niveauM SK3 et cache des verdicts
> 7. [**Étudier ce qui ne va pas se tenir**](/blog/stylobot-release-nondeterministic-testing) - la discipline de vérification : un fichier BDF conduit à la régressionM SK2 charge, et à l'étalonnage
> 8. [**StyloExtract - un convertisseur HTML d'apprentissage local à Markdown**](/blog/stylobot-release-styloextract) - la couche de marquage HTML→ qui se joigne au détecteur , le bug lucidVIEW du fauteuil roulant qui a capté l’image

<!--category-- ASP.NET, StyloBot, Bot Detection, Performance, Machine Learning -->
<datetime class="hidden">2026-05-13T11:00</datetime>

Le modèle comportemental se trouve dans [Comportement, Non identité](/blog/stylobot-fingerprint); la discipline de fiabilité dans [Trouver et régler une croissance sans limites](/blog/stylobot-release-reliability); source à [github.comM SK1scottgal/stylobot](https://github.com/scottgal/stylobot).

[TOC]

---


## Pourquoi StyloBot s'occupe de cela?

StyloBot'tout son travail consiste à dire aux humains des robots, et la façon dont il le fait au niveau le plus élémentaire est d’établir une image de ce qu’un bot moyen ressemble et de ce que l’humain moyen ressemble . Aucune règle fixeMSC3 aucun regex sur l’utilisateurM SK4 chaînes d’agents: centroïdes comportementales dans un espace vectoriel dimensionnel MST6 MST7 un par groupe de clients qui se déplacent de la même manièreM ST8 Chaque observation confirme soit un centroïde existant, soit son emplacement. **Accuracy improves first; latence improves as a consequenceM SK1** (Le côté de regroupement est couvert par [Comportement, Non identité](/blog/stylobot-fingerprint); ce post est sur ce qui se passe avec les centroïdes une fois qu’ils ont été obtenus .)

Ce mécanisme est également ce qui rend le StyloBot déployable dans des endroits stupidement différents: un blog personnel à 50 demandesM SK2minute , un site de marketing qui explose au cours du lancement d’un produitMSC4 un SPA où la plupart du trafic sont les appels APIMST5 un checkout électronique de commerce où un faux positif sur un client payant est une perte réelle d’argentMSP7 un portail de contenu où SSK8 du trafic est automatisé mais que 30% des humains ont toujours besoin d’une voie propre par l’entremise de S. Le même moteur finit par avoir différents centroids sur différentes sites parce qu’il voit un trafic différentMSV11 la façon dont il les construit est la même partoutMSS12

Un détecteur qui exploite le pipeline complet sur chaque demande est rigoureux mais non économique. Un déTECteur qui cache blindement les verdicts est rapide mais fragile . Le StyloBot se situe entre ces deux appareils: le cache est le cas courantM SK3 le pipelines complet est la voie de récupérationMSC4

Pour le contexte contre les noms plus familiers dans ce espace:

| | Placement | Typique par SSK3coût de demande S| Ce que vous recevez en retour |
|---|---|---|---|
| Cloudflare Bot Management | Edge (their CDN) MSC4 SubM SK5milliseconde à l'extrémité de la bordure ♫| Block ♫
| CHEQ / DataDome | Server-side API callout Support de l'API sur le serveur MSC4 M~50-150 ms Snetwork roundMSC7tripM SK8 \| JSON verdict from their service
| StyloBot | Dans le processus ou dans l'automobile de sidecar gRPC locale | **~10-50 μs** chauffée par Skip, **400-900 μs** pour une conduite de pipeline pleinement rapide-path M SK1 Verdict type (`BotProbability`, `Confidence`, `RiskBand`, `ThreatScore`) directement dans votre gestionnaire |

Les produits de bord sont excellents à "bloc avant l'origine"; ce qu'ils ne peuvent pas faire est remettre votre application une probabilité par -requête et laisser votre page d'achat décider ce que faire avec elleM SK3 Les produits API font celaMSC4 mais vous payez un coupe-neige réseau par requêteMska5 StyloBot est le cas où le verdict est dansMske6procédureMka7 le coupe‐neige network n'existe Mska8t existantsM Ska9 et la voie chaude est plus rapide que soit par ordre de grandeurMSKA10

L'élévateur qui rend le cache sûr est **Politique-perM SK1surface**. Le cache du verdict est régi par un `SignatureCacheOptions` ' s’établissait en fonction de la politique d’administration, et ce pour qu’un point final administratif puisse exiger une confiance dans 0.95 et une fenêtre de fraîcheur seconde alors que le chemin du contenu accepte une confiance de 0.7 pendant une heure. [ASP.NET middleware](/blog/behaviour-aware-ux), en tant que [Véhicule de bord gRPC](/blog/sidecar-architecture), ou dansM SK1process behind a Caddy plugin.

Le reste de ce post est la machinerie qui rend le cache sécuritaire: mises à jour de l’EWMAM SK1 seuils d’hysterèse , caching des verdicts, échantillonnage de renouvellementMSC4 et chiens de surveillance de la varianceMNK5 Le numéro d’en-tête est la latenceMRK6 Le problème réel du design consiste à apprendre sans faire des erreurs anciennes permanentes MNK7

## Les empreintes digitales métastables

Tout ce qui se trouve au-dessous de l'ancrage est "la empreinte digitale ", donc il vaut la peine d'être précis sur ce que cela signifie iciM SK3 Dans StyloBot, une empreinte nulle n'est pas un seul champ. [Comportement, Non identité](/blog/stylobot-fingerprint), dessin sur TLS , ordre du titre de l'en-tête *d'ordre comportemental* Changer: une séquence de chemin différente , une cadence différente

C'est ce qui rend les empreintes digitales **Métastabilité**: suffisamment stable pour qu'un acteur demeure reconnaissable au cours d'une période de courte durée - agitation de l'identité à terme M SK2 suffisamment évoluant pour que le changement comportemental réel apparaisse comme un mouvement du point . Pas d'identité fixe MSC4 pas de bruit aléatoire MST5 Une signature lente M ST6 motrice avec structure M st7

C’est la propriété sur laquelle repose l’ensemble du système d’apprentissage. Si les empreintes digitales étaient bruyeuses (toute demande atterrissait quelque part au hasard ) L’estimation moyenne de l’EWMA n’affaiblitrait rien et le cache serait toujours erronéM SK3 Si elles étaient rigides MSC4la position ne se déplaçait jamaisMSC5 il n’y aurait pas de dérive à suivre et le chien-observateur n’aurait rien à surveiller pour ce qui est de la métastabilité, c’est précisément celle qui fait fonctionner les deux extrémitésMSM7 des observations soutenues peuvent raffiner un centroid parce que le signal sous-jacent est suffisamment stable pour affaiblirMMSC8 *et* On peut détecter la dérive parce que le changement réel apparaît comme un mouvement contre un arrière-plan autrement stable.

L’argument structural pour expliquer pourquoi cette propriété porte (humans sonores mais cohérents dans la structureM SK1 bots cohérentes mais malformées dans la construction ) est le chargement-qui porte la revendication de [**Comportement, Non identité**](/blog/stylobot-fingerprint), et si l'une des géométrie ici n'est pas claire que' est l'article à lire pour la première fois . Tout ce qui suit dans cet article est ce que vous pouvez faire *une fois* que la réclamation est en main.

## La thèse: la détection devrait être meilleure et moins coûteuse plus vous voyez

Chaque observation fait deux choses : : elle affine la centroïde; cette empreinte appartient à (, à l'exactitude de ), et augmente la confiance du système en ce que cet empreinte se comporte comme celle-ci. (, placement, ,, qui permet la vitesse, ).. La partie dure d'un détecteur adaptatif fait les deux sans laisser des erreurs anciennes devenir permanentes.

Un détecteur de robots se pose la même question coûteuse millions de fois par jour: *est-ce que cet acteur se comporte toujours comme ce que nous avons déjà appris qu’il était?* Pour la grande majorité de ces demandes, le système a déjà une opinion. Il a vu la même empreinte digitale TLS , la même commande d’en-têteM SK3 le même Utilisateur - Modèle de rotation des agents MSC5 le same quartier IP il y a dix minutes M SK6 et conclu `bot, 0.93`. Il n’y a pas de point d’effectuer une nouvelle fois la conduite complète du détecteur sur le même acteur, à moins que rien ne soit visiblement changé au sujet de cet acteur.

StyloBot, le système d’apprentissage de ' est construit autour de cette idée. *construit et raffine les centroïdes* en premier lieu. Lorsque le pipeline ne fonctionne pasM SK1t run, l’emplacement antérieur est utilisé à nouveau dans des conditions contrôlées , la demande est servie en microsecondesMSC4 et sa fourniture alimente encore la mémoire opérationnelle longueMNK5 de sorte que les centroïdes demeurent courants MNK6

> **ML à côté.** Il s'agit de **calculs adaptatifs** dans les réseaux neuronaux (eM SK1g. [early-exit networks](https://arxiv.org/abs/1709.01686), MixtureM SK1of-Experts s'entraînent ):classificateur d'un prix abordable en premier placeMSC4classifiant coûteux seulement lorsque la confiance de l'un de ces derniers est faibleMST6 Le pipeline du détecteur est le chemin d'inférence coûteux MST7 le cache par fingerprint8Cécheur des empreintes digitales est le bon SST9 avons-nous déjà appris ce chemin?

## Quatre niveaux de mémoire

L’apprentissage dans StyloBot est stratifié de sorte que chaque niveau correspond à une durée de vie différente:

1. **Rapide-reputation de la voie (instantM SK2** Une courte liste de modèles classés comme `ConfirmedBad` dans le `PatternReputation` store. Une requête correspondant à l’une de ces deux demandes interrompt le pipeline en priorité 3 avant que tout autre détecteur ne fonctionne . L’entrée requiert une note ≥≥ 0.9 et un soutien
2. **Tableau d'affichage de demandes (per-requestM SK3 millisecondes ).** Les détecteurs écrivent des signaux à un partage `BlackboardState.Signals` sink pendant la demande; les détecteurs ultérieurs lisent ces signaux. Il ne s’agit pas de M SK2t long -mémoire à termeMSC4 il s’agissait de la façon dont les 49détecteurs se coordonnent dans une demande sans que chacun ait à recomputer les caractéristiques des autres déjà extraites
3. **Inter-recherche de réputation (minutes à joursM SK2** Modèle-mémoire de niveau: `InMemoryPatternReputationCache` les pistes par -cotes de robot du modèle avec mise à jour en ligne de l’EWMA et défaillance temporelleM SK1 Chaque modèle comporte un `ReputationState` (`Neutral` → `Suspect` → `ConfirmedBad`, plus `ConfirmedGood`, `ManuallyBlocked`, `ManuallyAllowed`) avec seuils asymétriques de promotion et d’élimination
4. **Per-cache de verdict des empreintes digitales M SK1minutes).** Per-mémoire d'acteur: la fenêtre de glissage en direct `SignatureCoordinator` porte chacune des empreintes digitales observées' le dépistage postérieur de la , le nombre d’échantillonnagesM SK2 l’étape dernière - le moment où on a vu la MSC4 la plus récente bande de risque, et la plus dernière note de menaceMSL6 `SignatureVerdictGate.DecideAsync` lire ce message à chaque demande.

Niveaux 1 courtsM SK1circuit le pipeline . Niveaux (coordonnées) 2 à l’intérieur de celui-ci

```mermaid
flowchart LR
    classDef input fill:none,stroke:#3b82f6,stroke-width:2px
    classDef fast fill:none,stroke:#22c55e,stroke-width:2px
    classDef async fill:none,stroke:#a855f7,stroke-width:2px
    classDef store fill:none,stroke:#f59e0b,stroke-width:2px

    REQ["Incoming request<br\>(TLS fingerprint, headers, IP)"]:::input
    T1["Tier 1 · Fast-path reputation<br\>ConfirmedBad list<br\>priority 3, pre-pipeline"]:::fast
    T2["Tier 2 · Intra-request blackboard<br\>BlackboardState.Signals<br\>lifetime: one request"]:::async
    T3[("Tier 3 · PatternReputation<br\>EWMA + state machine<br\>lifetime: minutes to days")]:::store
    T4[("Tier 4 · SignatureCoordinator<br\>sliding window<br\>lifetime: minutes")]:::store
    PIPE["Detector pipeline<br\>(BlackboardOrchestrator)"]:::async
    OUT["Verdict"]:::fast

    REQ --> T1
    T1 -->|match| OUT
    T1 -->|no match| T4
    T4 -->|Skip| OUT
    T4 -->|Miss / Bias / Watchdog| PIPE
    PIPE <--> T2
    PIPE <--> T3
    PIPE --> T4
    PIPE --> OUT
```

## EWMA: comment le système oublié

Chaque mémoire numérique du système utilise la même règle de mise à jour, dans `Helpers/Ewma.cs`:

```csharp
public static class Ewma
{
    /// <summary>new = (1 - alpha) * previous + alpha * observation</summary>

    public static double Update(double previous, double observation, double alpha)
        => (1.0 - alpha) * previous + alpha * observation;
}
```

C'est tout ce qu'il y a à dire. `alpha` est le poids de la nouvelle observation; `1 - alpha` est l'inertie du passé. Réaction alpha plus élevée M SK1 réaction plus rapide à la dernière observation

La réputation du modèle l’utilise directement. De `PatternReputationUpdater.ApplyEvidence`:

```csharp
// EMA update: alpha clamped to [0,1] preserves EMA semantics (alpha > 1 inverts
// the old score contribution).
var alpha = Math.Min(_options.LearningRate * evidenceWeight, 1.0);
var newScore = Ewma.Update(decayed.BotScore, label, alpha);
```

`LearningRate` par défaut à 0.1, de sorte qu’une seule observation déplace la note par 10% de l’écart vers cette observationM SK2 L’autre 90% est quelque chose que ce modèle ait fait historiquement.

> **ML à côté.** EWMA = le classique [Moyenne mobile exponentielle](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) qui apparaît dans [Adam](https://arxiv.org/abs/1412.6980) (le `β₁`, `β₂` Accumulators de moment et de variance), en [Évaluation moyenne de Polyak](https://en.wikipedia.org/wiki/Stochastic_approximation), en BatchNorm running mean [Mise à jour de la valeur TD(0)](https://en.wikipedia.org/wiki/Temporal_difference_learning) (`V ← V + α(r + γV' - V)`). `α = 0.1` ici est dans le même intervalle que vous'd voyez pour les tampons de momentum : assez lente qu’une mauvaise observation ne puisseM SK2t déplacer la valeur en cours, suffisamment vite que la valeur courante trace un changement soutenuMSC4

Nous avons choisi cette mise à jour au-dessus de l’obvious - mais - la mauvaise alternative d’entreposer la probabilité maximale jamais observée. Un stock historique maximalM SK3 de - permettrait à un seul Pic5 d’établir pour toujours un modèle à P0.95 M, peu importe comment il se comportera ultérieurementMSC8 Le stock du EWMA possède la propriété opposanteMNK9 une MPSK10 tige suivie par des centaines d’observations bénéfiques s’effondre doucement en retour vers le bénéfiqueMRK11 Les positifs faux sont récupérablesMMK12

La dégradation s’étend aux mêmes modèles. `ReputationOptions` (définitions par défaut du code

```csharp
public double ScoreDecayTauHours { get; set; } = 3;             // generic
public double SupportDecayTauHours { get; set; } = 6;
public double ConfirmedBadScoreDecayTauHours { get; set; } = 12; // ConfirmedBad
public double ConfirmedBadSupportDecayTauHours { get; set; } = 24;
public int GcEligibleDays { get; set; } = 90;
```

Un modèle qui n’a pas été observé dans un jour a perdu la plus grande partie de son appui, soit ;, celui dont on ne l’a jamais vu en ', et qui est à nouveau présent. `Neutral` est de l’erreur-collectéM SK1 `ConfirmedBad` Les modèles ont un tau plus long (ils ont gagné leur statut grâce à des preuves solides et ne devraient-ils pas les perdre en une seule heure tranquille

> **ML à côté.** La note-décayM SK1à la direction -la première étape est la première-meilleure de l’ordreMSC4reversion MST5le [Ornstein–Uhlenbeck](https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process) forme): sans preuves nouvelles , la note se replie vers le taux antérieur `1/τ`.

L’hysterèse est intégrée à la machine d’État. Les seuils réels de `ReputationOptions`:

| Transition | seuil de points MSC2 seuils d'appui MSC3
|---|---|---|
| `Neutral → Suspect` | ≥ 0.6 | ≥ 10 |
| `Suspect → ConfirmedBad` | ≥ 0.9 | ≥ 50 |
| `Suspect → Neutral` | ≤ ≥0.4 ≤| (ou baisses d’appui) ±|
| `ConfirmedBad → Suspect` |  ≤
| `Neutral → ConfirmedGood` | ≤ 0.1 | ≥ 100 |

```mermaid
stateDiagram-v2
    direction LR
    [*] --> Neutral
    Neutral --> Suspect : score &ge; 0.6<br/>support &ge; 10
    Suspect --> ConfirmedBad : score &ge; 0.9<br/>support &ge; 50
    Suspect --> Neutral : score &le; 0.4
    ConfirmedBad --> Suspect : score &le; 0.5<br/>(support &ge; 100 OR<br/>support &lt; 50)
    Neutral --> ConfirmedGood : score &le; 0.1<br/>support &ge; 100
    ConfirmedBad --> [*] : 90 days unseen<br/>+ neutral + low support
    Neutral --> [*] : 90 days unseen<br/>+ low support

    note left of ConfirmedBad
        Fast-path eligible
        (Tier 1 short-circuit)
    end note
    note right of Neutral
        Promote at score 0.9 / sup 50
        Demote at score 0.5 / sup 100
        Wider gap = oscillation-resistant
    end note
```

L’écart 0.4- entre le seuil de promotion (0.9) et celui de démote `ConfirmedBad` est délibérée: il ' s'agit d'une oscillationM SK2 bande de surpression. Tout ce qui se tourne entre MST4 et SST5 demeure un `Suspect`; seules preuves confirmées dans une direction franchissent la frontière

> **ML à côté.** Il s’agit d’un [Trigger de Schmitt](https://en.wikipedia.org/wiki/Schmitt_trigger): plus étendueM SK1par rapport à - seuils symétriques pour les transitions d'État. L'analogue ML est l'enveloppe discrétionnaire de décision autour de tout classeur continu où vous ne voulez pas que les étiquettes détournent chaque lotMSC6 réfléchir à la façon dont les votes ensembles sont habituellement comparés à une exigence de marge , ou comment les systèmes d’alerte déclenchent ("seulement sur une page si la condition se maintient pendant N minutes+"). C'est aussi le motif pour lequel les points d’exploitation dans une précision*-la courbe de rappel sont réglées par ±-direction=.

## La vitesse du cache de verdict: que vous devez gagner

La fenêtre per-fingerprint sliding est la couche que le chemin chaud de demande consulte maintenant directement. `SignatureVerdictGate.DecideAsync` est l’ensemble de la décision et il's petiteM SK1

```csharp
public async Task<GateDecision> DecideAsync(
    string? signature, SignatureCacheOptions options, CancellationToken ct = default)
{
    if (!options.Enabled || string.IsNullOrEmpty(signature))
        return new GateDecision(GateAction.Miss, null);

    var verdict = await _coordinator.TryGetVerdictAsync(signature, ct);
    if (verdict is null)
        return new GateDecision(GateAction.Miss, null);

    if (verdict.Confidence < options.BiasMinConfidence)
        return new GateDecision(GateAction.Miss, verdict);          // too noisy

    var ageSeconds = (DateTime.UtcNow - verdict.LastSeenUtc).TotalSeconds;

    var skipEligible =
        verdict.Confidence >= options.SkipMinConfidence
        && ageSeconds <= options.SkipMaxAgeSeconds;

    if (skipEligible && !ShouldRefresh(signature, options.SkipSamplingRate))
        return new GateDecision(GateAction.Skip, verdict);          // cache hit

    var biasEligible = ageSeconds <= options.BiasMaxAgeSeconds;
    return new GateDecision(biasEligible ? GateAction.Bias : GateAction.Miss, verdict);
}
```

Les seuils de politique par - provenant des `SignatureCacheOptions` (les valeurs par défaut sont indiquées):

```csharp
public double SkipMinConfidence { get; init; } = 0.85;
public int    SkipMaxAgeSeconds { get; init; } = 300;        // 5 min
public double BiasMinConfidence { get; init; } = 0.30;
public int    BiasMaxAgeSeconds { get; init; } = 86_400;     // 24 h
public double SkipSamplingRate  { get; init; } = 0.05;       // 5 %
```

La confiance elle-même est dérivée de `SignatureCoordinator.TryGetVerdictAsync` à partir de la taille de l’échantillon, avec toute confiance aux observations M SK1 et une rampe linéaire inférieure:

```csharp
var confidence = Math.Min(1.0, behavior.RequestCount / 10.0);
```

Ainsi, `SkipMinConfidence = 0.85` signifie qu’une empreinte digitale a besoin de ~9 d’observations dans la fenêtre courante avant d’être admissible à l’examen.

Les quatre actions:

- **Miss.** Aucune inscription utilisable pour cette empreinte digitale, ou une plus ancienne que `BiasMaxAgeSeconds`. La conduite complète du détecteur est activée. Le résultat alimente la fenêtre de glissement pour la prochaine foisM SK2
- **Préjudice.** Un registre existe avec une confiance modérée, ou c’est-à-dire qu’il ' est légèrement désuetM SK2 Le pipeline se déroule, mais le verdict cache est injecté sous forme d’une vagueMSC4 contribution antérieureMNK5 L’arrière est tiré vers l’avant en proportion de la confiance antérieures et d’un déclin linéaire de l’âgeMRK6
- **Skip.** Le dossier est récent et suffisamment sûr que la contribution du pipeline serait marginale.
- **Vérificateur(s)** Passer-aperçu du cache admissible, mais l’agent de surveillance des variations a détecté quelque chose d’atypique . Le verdict caché est invalidé pour cette demande

```mermaid
flowchart TD
    classDef input fill:none,stroke:#3b82f6,stroke-width:2px
    classDef decision fill:none,stroke:#f59e0b,stroke-width:2px
    classDef fast fill:none,stroke:#22c55e,stroke-width:2px
    classDef slow fill:none,stroke:#a855f7,stroke-width:2px
    classDef trip fill:none,stroke:#ef4444,stroke-width:2px

    REQ["Request arrives"]:::input --> LOOKUP{"TryGetVerdictAsync<br\>(sliding window<br\>+ family fallback)"}:::decision
    LOOKUP -->|"null OR low-conf OR stale"| MISS["MISS<br\>full pipeline"]:::slow
    LOOKUP -->|"record found"| CONF{"conf ≥ 0.85<br\>+ age ≤ 300s?"}:::decision
    CONF -->|"no"| BIAS["BIAS<br\>pipeline + prior contribution"]:::slow
    CONF -->|"yes"| REFRESH{"In 5% refresh<br\>(hash bucket)?"}:::decision
    REFRESH -->|"yes"| BIAS
    REFRESH -->|"no"| WD{"VarianceWatchdog<br\>OK?"}:::decision
    WD -->|"tripped"| TRIP["WATCHDOG-TRIP<br\>X-StyloBot-VerdictSource = pipeline<br\>X-StyloBot-WatchdogTrip = reason"]:::trip
    WD -->|"ok"| SKIP["SKIP<br\>X-StyloBot-VerdictSource = cache<br\>orchestrator bypassed"]:::fast

    MISS --> UPDATE[("Update sliding window<br\>+ RecordObservation")]:::slow
    BIAS --> UPDATE
    TRIP --> UPDATE
    SKIP --> UPDATE
```

Le logiciel de médiation émet `X-StyloBot-VerdictSource` (`cache` ou `pipeline`) et `X-StyloBot-WatchdogTrip` (string de rÃ©ponse lorsquâ€TMil est applicable) sur la réponse afin que les opérateurs puissent voir en direct quel chemin chaque requête a suivi

Skip est ce qui se produit lorsqu’il n’y a rien de nouveau à apprendre. Une fois qu’une empreinte digitale a été vue avec suffisamment de confiance dans l’une ou l’autre direction (la passerelle est la direction -agnostiqueMSC3 si sûreM SK4humaine et sûre+-les robots sont également admissibles=), toutes les demandes subséquentes ne coûtent que le dépistage de la passerelleMST7 un registre d’observationM ST8 et l’application des politiquesM st9 Sur la case de référence MST10M SST11 MacBook AirSST12 SST13 GBS ST14 que M ST15s MSST16 μsSST17 comparativement MSST18μs pour une passerelle pleine rapide MS ST19 passage du pipeline de voilure+M ST20 Skip est approximativement un ordre de grandeur plus rapide que le passage complet bon marché et de nombreuses commandes plus rapides que tout autre élément impliquant un ralentissement réseau+MST21

## Le cache du verdict en tant que contribution, n'est pas une décision

Avant d’entrer dans la mécanique de récupération, le cadre qui les rend cohérents: le verdict caché n’est pas une réponse stockée que le système réutilise aveuglement . Sur le chemin du biais ilM SK3 est injecté comme une vagueMSC4 *Contributions*, pondéré en fonction de la confiance et de l’âge `FingerprintPriorContributor.ContributeAsync` est l’ensemble de la mécanique:

```csharp
var horizon = AgeDecayHorizon;                                 // default 86,400s
var decay = horizon > 0.0 ? Math.Max(0.0, 1.0 - age / horizon) : 1.0;
var effectiveWeight = conf * WeightMultiplier * decay;

if (effectiveWeight <= 0.0) return _emptyResult;

var delta = 2.0 * (prob - 0.5);   // map [0,1] probability to [-1,+1] confidence delta

var contribution = new DetectionContribution
{
    DetectorName = DetectorName,
    Category = DetectorName,
    ConfidenceDelta = delta,
    Weight = effectiveWeight,
    Reason = $"Cached fingerprint verdict (prob={prob:F2}, conf={conf:F2}, age={age:F0}s)"
};
```

Un verdict antérieur avec confiance 0.9 ancre fortement le postérieur ( poids effectif | | 4 | 5 | 6 | 7 | 8 | 9 | 10

> **ML à côté.** C'est vraiment **Bayesian**: précédemment (décision cachée) × probabilité MSC4la présente demandeMSC5éléments de preuveM SK6 \→ postérieureMST8 Le `decay = 1 - age/horizon` Le terme joue le même rôle qu'un facteur forgetting dans [Estimation Bayesienne récursive](https://en.wikipedia.org/wiki/Recursive_Bayesian_estimation); les anciens ancêtres perdent leur force, de sorte que la probabilité domine comme les âges antérieurs. `RequestContributionDelta` (le changement que cette demande faite à l'extrémité opérationnelle postérieure ) plutôt qu'à la probabilité de demande brute perM SK2: sur les verdicts cachés `delta` est la partie qui, selon ', constitue en fait de l’information nouvelle

## Comment les faux positifs ne se combinent-ils pas?

Jusqu’à ce point, le système semble dangereusement caché.

```mermaid
flowchart TD
    classDef store fill:none,stroke:#f59e0b,stroke-width:2px
    classDef defense fill:none,stroke:#22c55e,stroke-width:2px
    classDef recover fill:none,stroke:#a855f7,stroke-width:2px

    CACHE[("Cached verdict<br\>(EWMA posterior + sample count)")]:::store

    D1["Direction-agnostic confidence<br\>caches confident verdicts,<br\>not just bot verdicts"]:::defense
    D2["EWMA, not MAX<br\>one spike contributes 10%,<br\>not 100%"]:::defense
    D3["Sample-size gating<br\>full trust at 10 samples,<br\>Bias below that"]:::defense
    D4["Variance watchdog<br\>IP rotation, rate spike,<br\>path divergence"]:::defense
    D5["Skip-path observation<br\>cache hits still record,<br\>history stays whole"]:::recover
    D6["Refresh sampling<br\>5% of Skips downgraded<br\>to Bias by signature hash"]:::recover

    D1 --> CACHE
    D2 --> CACHE
    D3 --> CACHE
    D4 --> CACHE
    D5 --> CACHE
    D6 --> CACHE
```

**Orientation-confidence agonisteM SK1** `SkipMinConfidence` est contrôlée contre `verdict.Confidence`, non contre `verdict.BotProbability`. Un verdict certain de -un verdict robot et un verdict humain sont également admissibles à passer par le biais d’une procédure d’évitement. *Confiance* Le système est biaisé selon la façon dont les éléments de preuve ont été mis en évidence.

**EWMA, non MAX.** Une seule observation de probabilité élevée - déplace le résultat en cours par `α = 0.1` Un véritable attaquant accumule rapidement des éléments de preuve parce que *tous les* L’observation est hostile. Un visiteur légitime qui a l’air d’apparaître comme un scraper pour une demande décroît de façon bénéfique lors des observations subséquentes.

**Exemple-ajustement de tailleM SK1** `confidence = min(1, request_count / 10)`. Suivant ~9 observations, même un postérieur fort est retenu à l’intention de la partialité plutôt qu’à l’égard du renversementM SK3 La décision d’avoir pleinement confiance dans le cache est prise en fonction de la signification de l’EWMA

> **ML à côté.** Il s’agit d’un **Réduction préliminaire**: jusqu’à ce que des preuves suffisantes s’accumulent , la partie postérieure n’arrive pas à agir avec confiance [Bandits de l'UCB](https://en.wikipedia.org/wiki/Multi-armed_bandit#Upper_Confidence_Bound) inclure une échantillonnage `n`, large intervalle de confianceM SK1 ne pas utiliser

**Vérificateur de la variation.** Même avec un verdict confidentiel, nouveau cached, Skip peut être révoqué par demandeM SK2 `VarianceWatchdog.Check` effectue trois tests indépendants contre `VarianceWatchdogOptions` (defaults):

```csharp
public int    IpRotationWindowSeconds { get; init; } = 300;   // same fingerprint, new /24
public double RateSpikeMultiplier     { get; init; } = 10.0;  // last minute vs rolling 5
public bool   CheckPathCentroid       { get; init; } = true;  // never-seen path family
```

La vérification de la divergence requiert au moins 3 des familles distinctes de chemin sur le registre avant qu’elle ne puisse être déclenchée

```csharp
if (options.CheckPathCentroid && hist.PathFamilyCount >= PathFamilyBaseline)
{
    var family = PathFamily(ctx.Request.Path.Value);
    if (family is not null && !ContainsFamily(hist, family))
        return new WatchdogResult(true, $"path-divergence:{family}");
}
```

Tout voyage et le pipeline fonctionne fresh; la réponse transporte `X-StyloBot-WatchdogTrip: ip-rotation:1.2.3.0->5.6.7.0` (ou quoi que ce soit qui a été déclenché ) de sorte que les opérateurs sachent la raison

> **ML à côté.** Le chien de garde est **concept-détection de dérive** pour une empreinte digitale. Les analogues classiques sont [ADWIN](https://www.cs.upc.edu/~gavalda/papers/adwin06.pdf), [Page–Hinkley](https://en.wikipedia.org/wiki/CUSUM), et [DDM](https://link.springer.com/chapter/10.1007/978-3-540-28645-5_29); toutes ces variables détectent qu’un flux en ligne ' sa distribution a changé suffisamment pour que le modèle existant ne soit plus digne de confiance M SK2 Les trois vérifications ici sont les domaines - signaux de dérivation spécifiques

**Passer-observation du cheminM SK1** Même lorsque la passerelle passe le pipeline,, l’ordinateur intermédiaire enregistre toujours la demande:

```csharp
_watchdog.RecordObservation(precomputedSig, clientIp, pathStr);
_ = _signatureCoordinator.NotifyObservationAsync(
    precomputedSig, pathStr, v.BotProbability, context.RequestAborted);
```

Le fait que la détection ait été écartée ne crée pas de trou dans l’historique des empreintes digitales par -; clustering,Driving detection, et le tableau de bord'Les statistiques sur les empreintements digitales pour chaque demande indiquent si le pipeline est ou non exploité.

**Renouveler l’échantillonnage.** `ShouldRefresh` déterministement abaisse une fraction configurable des requêtes admissibles à Bias de Skip- afin que le pipeline fonctionne et rafraîchise l’enregistrement en direct. Le hash de signature décide quelles demandes sont réfrigérées.`DeterministicBucket.ShouldFire`), de sorte que les retraits du même client débarquent identiquement ; au fil du temps, chaque empreinte digitale reçoit une réévaluation complète périodique

> **ML à côté.** Il s'agit d'une version déterministe **ε-exploration abondante** de l’apprentissage du renforcement: la plupart du temps exploiter la politique actuelle (SkipM SK2 une partie du temps payer le coût d’exploration (BiasMSC4 pour que le modèle demeure calibréMST5 Le déterminisme par hash fait qu’il soit idempotentMSP6 ce qui est important quand le même client se retientMSS7

**Entité-recul familialM SK1** Lorsqu’une empreinte digitale tourne et que sa nouvelle identité n’a pas de verdict caché d’elle-même, la porte passe à la signature canonique de la famille [Ancre de l'unité de Leiden](/blog/stylobot-fingerprint) du modèle comportemental). De `TryGetVerdictAsync`:

```csharp
if (!_signatureCache.TryGet(signatureId, out var atom) || atom == null)
{
    if (!_signatureToFamily.TryGetValue(signatureId, out var familyId) ||
        !_families.TryGetValue(familyId, out var family) ||
        ...
        !_signatureCache.TryGet(family.CanonicalSignature, out atom) || atom == null)
    {
        return null;
    }
}
```

Un robot qui's a été fusionné dans une famille parce que son vecteur comportemental correspondait à un frère connu hérite du verdict du frère' plutôt qu’à partir de zéro, mais seulement si l’ancrage familial est lui-même encore dans la fenêtre sélévatrice.

## Comment se présente-t-il au moment du démarrage?

Les chiffres ci-dessous sont tirés de la mise en place d’un point de repère 5 MacBook Air (32 GBM SK2 . La distribution du pipeline en direct se situe dans un modèle comme le suivant :

| Voie / mode MSC2 Par SMC3coût de demande SMC4 Ce qui fonctionne MSC5
|---|---|---|
|VerdictM SK1cache hit (Skip **~10-50 μs** | Surveillance de la signature , puis passer par le biaisM SK2 aucun détecteur |
| Voie rapideM SK1 chaleureuse, client unique | **400-600 μs** | Tous 19 rapides- détecteurs de voies + tableau noir M+ SQLite écrire MSC5
| Calendrier rapideM SK1 froid (première coupe **~900 μs** | PremierM SK1allocations touchées + pipeline intégrale |
| Voie rapideM SK1 60 Contention VU | **50 ms pM SK1 / ≥134 msp99** | Détection inchangée; la latence est à l'échelon des demandes |
| Voie lente (ProjectHoneypot DNS lookup **~100 ms** | Une ronde DNSM SK1trip; uniquement sur déclencheur de signaux |
| escalation de la LLM (OllamaM SK2 locale) | **1-5 s** | Éteint par défaut; jamais sur le fil de demande |

L'ensemble du spectre en direct sur un client unique est de microsecondes pour Skip, sub-milliseconde pour une conduite pipeline pleinement rapide -path passM SK3 et MSC4 ms seulement lorsqu'un détecteur se rapproche explicitement d'une source de signaux éloignéesMNK5 Les numéros SSK6 ms / S134 ms ne sont pas des coûts de détectionMST9 ilsMSST10re ce qui apparaît à pSST11pMSST12 lorsque les utilisateurs virtuels se battent pour le même gestionnaireMSS14 et ils apparaissent identiques avec la désactivation de la détection\MSS15

Où va-t-il en fait pour le budget du cheminement rapide-?

| Niveau | Étendue MSC2 Exemples MSC3
|---|---|---|
| Trivial < 200 nsM SK3 \| | | 33-200\ \ | |\ comportement des témoins \ 33\ ns\ ,\ corrélation de l'en-tête \
| Cheap < 1 μsM SK3 | | | \ 200 ns-1μs || FastPathReputation |
| modérée (1-5 μs) | ≥1.3-4.3μs M| CacheComportement de l'entreposage MSC6 μ sMSC7 Haxxor SMC8 μSM SK9 Comportement du entreposage

C’est la raison pour laquelle Skip est si précieux.

Le tableau de bord CLI lit directement les en-têtes des réponses, cache vs pipeline vs watchdog-trip est visible par rangéeM SK2 La barre supérieure des empreintes digitales montre chaque empreinte digitale 's EWMAMSC4smoothed posterior Mska5the stable verdictM Ska6 non selon la façon dont la dernière demande a été boucléeMSKA7 PerMka8la note de requête est l’information sur la demandeMKA9 l’acteurMsaka10le pointage se déplace lentement à l’intention de l’acquéreurMlaska11

## Pourquoi ' a-t-il été construit de cette façon

L’ensemble du système est un mécanisme avec deux conséquences. *améliorer* Le second est qu’une fois une empreinte digitale confidentielle déposée, le pipeline n’a plus rien à faire pour lui.

Passer est ce qui se produit lorsque rien de nouveau n’est à apprendre. Le biais est ce qu’il arrive lorsque le pipeline doit fonctionner mais que l’information antérieure demeure pertinente . La faute est la froide

La mise à jour de l’EWMA pour chaque mémoire, l’hysterèse asymétrique dans la machine d’état, l'échantillonMSC2 le port de taille sur confianceM SK3 léchantillage déterministe de rafraîchissement , le cheminementMST5 la mémoire familialeMSP6 et la familleMSV7 les échecs canoniques existent tous pour la même raisonMSR8 Chacune est un endroit où le système peut se tromper au sujet d’une empreinte digitale et encore récupérerMSS9 par lui-mêmeMSSS10 sans qu’un opérateur ne pénètre dans le systèmeM SS11

Le numéro de latence est le titre facile.