# StyloBot-utsläppsserien: Att bli snabbare

*Uppåt- -den här är för nördarna.- -.. Det är en djup vetenskaplig dykning in i StyloBots adaptiv-lärningssystem. (. EWMA-uppdateringar. `Mostlylucid.BotDetection` och ledtrådar till den likvärdiga maskinen.-.Lernering konstruerar så att ML-reader har en ingångspunkt... Om du vill ha hissen på hissen,,. läsa de tidigare utsläppsposterna.M SK3. Om ni vill veta hur fyras minne, -, omvandlar upprepade trafiker till subprocesser och under tiden återhämtar sig från felaktiga positiva signaler.*

> ## DRAFT
> 
> Detta är ett arbetsprojekt i StyloBot-utsläppsserien.

> **StyloBot-utsläppsserien**
> 
> 1. [**Behavior, Inte Identitet**](/blog/stylobot-fingerprint) - varför StyloBot modellerar klienter beteendemässigt
> 2. [**Behavior-Är medveten ASP.NET UI**](/blog/behaviour-aware-ux) - servern - skickade ut ytan över det upptäcktsresultatet
> 3. [**Att hitta och lösa gränslös tillväxt i långtids-, -- och / eller körande- -.-nätverk**](/blog/stylobot-release-reliability) - den tillförlitlighetsdisciplin som gör motorn tråkig i produktionen
> 4. [**Behavior-Akvis typscript-UI**](/blog/typescript-sdk) - Express , Fastify, och webbladerkomponenter
> 5. [**Sidecar-arkitekturen**](/blog/sidecar-architecture) - hur detektoren kopplas till icke--.NET-skivor
> 6. **Att lära sig bli snabbare** - adaptiv inlärningssystem, ,, fyra, M SK2, övningsminnet, ,, och bedömningsキャッシュen
> 7. [**Att testa det som inte stannar kvar**](/blog/stylobot-release-nondeterministic-testing) - kontrolldisciplinen : en BDF-fielddriver regression M SK2 belastning , och kalibrering
> 8. [**StyloExtract - en lokal lärande HTML omvandlare till Markdown**](/blog/stylobot-release-styloextract) - HTML, →, Markdown-lagret som paras med detektorn, ,, walkersbug lucidVIEW som fångade, M SK3, och den hundföda-loopan som gjorde det ärligt

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

Behavioralmodellen finns i [Behavior, Inte Identitet](/blog/stylobot-fingerprint); tillförlitlighetsdisciplinen i [Att hitta och fixa gränslös tillväxt](/blog/stylobot-release-reliability); källa på [github.com/scottgalM SK2stylobot](https://github.com/scottgal/stylobot).

[TOC]

---


## Varför stör StyloBot med det här

StyloBots hela jobb är att berätta för människor från robotar, ,, och det sättet den gör det på den mest grundläggande nivån är genom att bygga en bild av hur en genomsnittlig bot ser ut och hur en medelmänsklig människa ser ut.., inga fixera regler.,, ingen regex över användaren.M SK4, agentsträngar. **Accuracy förbättras först; latens förbättras som ett resultat** (Klasteringsidan av detta är täckt av [Behavior, Inte Identitet](/blog/stylobot-fingerprint); det här laget handlar om vad som händer med centrärerna när man har dem

Den mekanismen är också vad som gör StyloBot till att användas på dumt olika ställen.:, en personlig blogg på 50, begäran, /, minuten, ,, en marknadsföringssida som exploderar när produkten lanseras.,, ett SPA där större delen av trafiken är API-sändningar.

En upptäckare som kör hela pipelinen på varje utmaning är noggrann men oekonomisk. En upptäcker som blindt kastar ut bedömningar är snabb men brittisk . StyloBot sätter sig mellan de två M SK2 kaschen är det vanligaste fallet

För kontext mot de mer bekanta namnen i detta utrymme:

| | Platsering | | | Typiskt per - | anställningskostnader | | | Vad du får tillbaka ||
|---|---|---|---|
| Cloudflare Bot Management | | | Rand |( | Deras CDN | ) | МSK4 | Sub | - | Millisekund vid kanten | | | Block |/ | Utmaningen | Sk8 | tillåt innan din ursprung ser det |
| CHEQ ♫ ♫ / ♫ DataDome ♫ {\displaystyle ♫{| ♫ Server ♫} - ♫ Side API callout ♫
| StyloBot | Iprocessen eller lokala gRPC-bilar **~10-50 μs** uppvärmda via Skip, **400-900 μs** för en fullfast -path pipeline run`BotProbability`, `Confidence`, `RiskBand`, `ThreatScore`) direkt i din handledare |

Kanterprodukter är jättebra på "block före ursprunget "; vad de inte kan göra är att ge din applikation en procent per request, och låta din kassasida bestämma vad man ska göra med den M SK3 API-produkter gör det , men du betalar ett nätverkshop per request.

Nyckeln som gör datan säker är **policy -per-yta**. Berättelseskivan styrs av en `SignatureCacheOptions` lägg märke till att ' är set per policy, så att en administratörs utgångspunkt kan kräva förtroende och ett freshness-fenster i sekunden medan en innehållspfad accepterar förtroende över en timme. [ASP.NET mellanverk](/blog/behaviour-aware-ux), som en [gRPC bibil](/blog/sidecar-architecture), eller i-process bakom en Caddy-plugin

Resten av den här bilden är maskinen som gör datan säker: EWMA-updater , hysteresiska tröskeln, , bedömande datakasering, , uppdaterade prover, M SK4 och variansvakter, MST5 huvudnummern är latens, Mst6 Det verkliga designproblemet är att lära sig utan att göra gamla misstag permanenta, M st7

## Det metastablera fingeravtrycket

Allting under ancorar sig till " fingeravtrycket ", så det är värt att vara precis om vad det betyder här.. I StyloBot är en fingeravbild inte ett enda fält, . Det är en position i den dimensionala beteendevektoriska rymden från [Behavior, Inte Identitet](/blog/stylobot-fingerprint), ritning på TLS , naglarnas ordning, tidning, , bana sekvensen,, JS-beteendet, M SK5 och signalerna som kommer ut ur alla, 50 detektörer, . En roterad IP flyttar den knappt, *beteendemässigt* förändring: en annan bana sekvens , en annorlunda kadens , ett nytt sätt att misslyckas med kontroller

Det gör fingeravtrycket **Metastabla**: tillräckligt stabil för att en skådespelare ska kunna kännas igen över korta perioder - tidiga identitetsvrängningar, , utvecklande tillräckligt för att genuina beteendeförändringar visar sig som rörelser av punkten . Inte en fixerad identitet, M SK4, inte slumpmässigt högljudd,

Detta är egenskaperna som hela lärandesystemet ligger på.. Om fingeravtryck var högljudda, ♫ ( ♫ varenda begäran landade någonstans slumpmässigt ♫) ♫ EWMAs medelvärde skulle inte skära på något och kaset skulle alltid vara fel ♫ *och* drift kan upptäckas eftersom den verkliga förändringen visar sig som rörelse mot en annan stabil bakgrund.

Det strukturella argumentet för varför denna egenskap har (människor som är oljudliga men konsekventa i strukturen , robotar som är konsekventa men felaktiga i structuren M SK2 är kravet [**Behavior, Inte Identitet**](/blog/stylobot-fingerprint), och om någon av geometrin här är oklar att ' är artikeln som ska läsas först *en gång* påståendet är i hand.

## Forskningen ":" -detektorn borde bli bättre och billigare ju mer man ser

Varje observation gör två saker: :, den täcker centreiden, den här fingeravtrycket tillhör (, precision, ), och den ökar systemets självförtroende om att den här avtrycken beter sig som den där centreiden. (, platsing ,, vilket möjliggör hastighet ). Den hårda delen av en adaptiv detektor gör både utan att låta gamla misstag bli permanenta

En robotdetektor ställer samma dyra fråga miljoner gånger om dagen *är den här skådespelaren fortfarande på samma sätt som vi redan lärde oss att det var* För den stora majoriteten av dessa begäran„ , ”, så har systemet redan en åsikt“ . ”. Den såg samma TLS-fingerprint “ , ”, samma skriftsedel ” , ”, densamma användaren “ - ”, agentens rotationsmönster “, ”, det samma IP-kvarteret för tio minuter sedan “ M SK6 ” och tog slutsatsen `bot, 0.93`. Det finns inga poäng med att köra fulla detektorstrålning på samma skådespelare igen, om inget av den skådespelaren har synligt ändrats

StyloBots lärandesystem är byggt runt den idén. *bygger och raffinerar centroiderna* i första verket. När pipelinen inte sätter igång' inte drivs , så återanvändas den tidigare platsningen under kontrollerade omständigheterM SK3 tillfrågan levereras i mikrosekunderMSC4 och när den levereras matas den fortfarande med den långa maskinens dataprocesser, så att centroiderna stannar kvar

> **ML bortsett.** Det här är **anpassningsmässig beräkning** i nervnätverk (e.gM SK2 [tidigt-utbrott av nätverk](https://arxiv.org/abs/1709.01686),, blandning, -, av -, experter kollar, ):, billig klassifier först, M SK4, dyr klassifier bara när den billiga är billig, ', och självförtroendet är lågt. ., detektorleitungen är den dyra inferensväggen.

## Fyra nivåer av minne

Att lära sig i StyloBot är upplagd så att varje nivå motsvarar en annan livstid:

1. **Fast-path reputation (instantM SK2** En kort lista av mönster klassificerade som `ConfirmedBad` i `PatternReputation` speichera. En begäran som matchar en av dessa avbryter pipelinen på prioritering | 3 | innan någon annan detektor kör |. | Inskrywing kräver poäng | | 3 | 4 | och stöd | 5 | 6 | 7 | mer om siffrorna under |
2. **Intra- --" request blackboard (" per "-" request** Detektorer skriver signaler till ett gemensamt `BlackboardState.Signals` dyka upp under utmaningen; senare läser detektörerna de signalerna . Det här är inte' inte långt - tidiga minnen M SK4 det är ' hur det är så att de ♫ 49 ♫ detektärerna koordinerar inom en utmaning utan att var och en måste återkomputera egenskaperna som de andra redan har extraherat
3. **Inter-skräv reputation M SK1minuter till dagar ).** Pattern-nivåns minne: `InMemoryPatternReputationCache` spår per-pattern-botscore med online EWMA-updater och tidnedgång. Varje mönster bär på `ReputationState` (`Neutral` → `Suspect` → `ConfirmedBad`, plus `ConfirmedGood`, `ManuallyBlocked`, `ManuallyAllowed`) med asymetriska förhöjningar och försämringsgränser
4. **Per-fingerprint verdict cache (minuterM SK2** Per-aktorins minne: ruttrande fönstret i `SignatureCoordinator` bär varje observationerad fingeravtryck `SignatureVerdictGate.DecideAsync` läser detta på varje fråga.

Tier 1 kort - omsluter verket i verket, . TIer ♫ 2 ♫ koordinerar inuti verket. . ♫ Tier "3" är den långa minnen som överlever under dagar. . ♫ TIer . 4 is the short memory that lets repeat traffic skip the pipeline entirely.

```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: hur systemet glömmer

Varje numerisk minne i systemet använder samma uppdaterande regel, i `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;
}
```

Det är hela grejen. `alpha` är vikten på den nya observationen `1 - alpha` är tröghet från det förflutna.

Patterns rykte använder den direkt. Från `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` stängs till 0.1, så att en enda observation flyttar poängen med 10% av luckan till observationen.

> **ML bortsett.** EWMA = det klassiska [exponentiell rörande medel](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) som dyker upp [Adam](https://arxiv.org/abs/1412.6980) (the `β₁`, `β₂` momentum och variansaccumulatorer), i [Polyak i genomsnitt](https://en.wikipedia.org/wiki/Stochastic_approximation), i BatchNorm Running medel [TD(0)-värdeuppdateringar](https://en.wikipedia.org/wiki/Temporal_difference_learning) (`V ← V + α(r + γV' - V)`). `α = 0.1` här är i samma intervall som du ser för hastighetsbuffer, :, tillräckligt långsamt för att en dålig observation kan röra igång värdet.

Vi valde detta uppdaterade över det uppenbara, men det felaktiga alternativet att lagra den maximala sannolikheten som någonsin observerats, ., ett max- -av historiens lager skulle låta en enda - -spikepin få ett mönster på - -0.95 för alltid. ,, oavsett hur den beter sig efteråt.

Förruttningen sträcker sig ut till mönsterna själva `ReputationOptions` (defaults från koden

```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;
```

Ett mönster som inte har setts på en dag har tappat större delen av sin stöd, ett som inte setts i 90 dagar och är tillbaka i `Neutral` är skräp `ConfirmedBad` mönster får en längre tau. De har förtjänat sin status genom starka bevis och borde inte förlora den på en enda tyst stund. minne som inte bryter sig, minne som går bort från verkligheten

> **ML bortsett.** Svaret-dekation-tillM SK2ste steget är det första -ordet medel -omvandling MSC5den [Ornstein–Uhlenbeck](https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process) form ): utan nya bevis, poängen drar tillbaka mot den tidigare hastigheten `1/τ`.

Hysteresi är inbyggd i statmaskinen. Den faktiska tröskeln från `ReputationOptions`:

| Omvandling | Punktes tröskel | | | stöd trössel ||
|---|---|---|
| `Neutral → Suspect` | ≥ 0.6 | ≥ 10 |
| `Suspect → ConfirmedBad` | ≥ 0.9 | ≥ 50 |
| `Suspect → Neutral` | ≤ ♫ ♫ 0.4 ♫
| `ConfirmedBad → Suspect` | ≤ ♫ ♫ 0.5 ♫
| `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
```

Skillnaden mellan 0.4--poängsnivån mellan förstärkningsgränsen (0.9) och demotegränsen `ConfirmedBad` är avsiktligt. `Suspect`; bara kvarlevda bevis i en riktning korsar gränsen

> **ML bortsett.** Det här är en [Schmitt-Trigger](https://en.wikipedia.org/wiki/Schmitt_trigger):, bredare, -, snarare än -, symmetriska trösklar för statövergångar, M SK3, ML-analogn är den diskreta, -, beslutsvalven kring vilken ändalklassifier som helst där du inte vill att etiketter svänger i varje lager.

## Den bedömande kassen: hastigheten du måste tjäna

Per” - ”fingerprint-sliding-fenstern är den lager som hotpath direkt konsulterar i efterfrågan. `SignatureVerdictGate.DecideAsync` är hela beslutet och det

```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);
}
```

Politiska tröskeln per - från `SignatureCacheOptions` (defaults visar

```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 %
```

Tro på sig själv `SignatureCoordinator.TryGetVerdictAsync` från provstorleken , med full tro på observationerna i 10 och en linjär ramp under МSK2

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

Så `SkipMinConfidence = 0.85` betyder att en fingeravtryckt behöver ~9 observationer i det nuvarande vensteret innan den kan vara överspringad - anpassningsbar M SK2 Längst därifrån , föredrar dörrarna fördomar

De fyra åtgärderna:

- **Miss.** Inget användbart rekord för den här fingeravtrycket, eller ett äldre än `BiasMaxAgeSeconds`. Detektorleitungen går igång fullkomligt . Resultatet får in strömmen till skiftfenan nästa gång
- **Fördomar.** Ett rekord existerar med medelvärdigt självförtroende , eller det' är lite föråldrande M SK2 Pipelinen går igång , men den inlagda bedömelsen injiceras som en våg Mska4 tidigare bidrag M Ska5 Det posteriora drars mot det tidigare i proportion till det tidigare självför troendet och ett linjärt åldrande
- **Skip.** Rekorden är ny, och är tillräckligt säker på att pipeline bidraget skulle vara marginalt.
- **Vakthund-tripM SK1** Springa- eligible cache hit , men skillnadvakten upptäckte något atypiskt. Cachekommenterade slutsatserna är olagda för den här begäranM SK3 pipelinen körs nyss

```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
```

Mittvaran släpper ut `X-StyloBot-VerdictSource` (`cache` eller `pipeline`) och `X-StyloBot-WatchdogTrip` ( resonemangsträng när den är användbar ) på svaret så att operatörerna kan se live vilken väg varje utmaning tog

Att hoppa är vad som händer när det inte finns något nytt att lära sig. När ett fingeravtryck har setts med tillräckligt mycket självförtroende i vart eller annat riktning | ( | dörren är riktningsrik |- | agnostisk | МSK3 | så säker | - | mänsklig och säker ♫ - | robotar är lika anpassningsriktade ♪ ), | varje efterföljande begäran kostar endast att kolla på dörrarna |, | en observationsbok |M, | och beslutstaganden |МSK9 | På gränssnittet |

## Berättelsens kass som en insats , inte ett beslut

Innan man går in i återhämtningsmekanik, framställningen som gör dem konsekventa, kopierad bedömelse är inte ett sparat svar och systemet återanvänder den blindt. *bidrag*, mätt utifrån självförtroende och ålder `FingerprintPriorContributor.ContributeAsync` är hela maskinen:

```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)"
};
```

Ett 30-sekunda-äldligt svar med självförtroendet 0.9 ancorar posterioren starkt | | 3 | effektiva vikter | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | en | 12 | timme | 13 | gammalt svar med selbstförtroandet | 14 | knappt rör det | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ett | 23 | 24 | långt svar utan effektiv vikt | 25

> **ML bortsett.** Det här är verkligen **Bayesianer**: tidigare ( kopierad dömelse M SK2 × sannolikhet ( denna begäran ' beviset `decay = 1 - age/horizon` termin spelar samma roll som en försvinningfaktor i [rekursiv Bayesisk uppskattning](https://en.wikipedia.org/wiki/Recursive_Bayesian_estimation); gamla förfäder förlorar styrka så sannolikheten dominerar som de förflutna åldern. `RequestContributionDelta` (den förändring den här begäran gjorde till den körande posterioren ) snarare än den råa per- begärans sannolikhet M SK3 på kasserade slutsatser , är per MSC5 begäran sannolikheten mestadels det föregående talade `delta` är den del som i själva verket har nya informationer

## Hur falska positiva inte kombineras med '

Fram till den här punkten låter systemet farligt Cache . "-", Heavy , , , så den här sektionen är den viktigaste. ":", hur designen antar att cached verdicts slutligen är felaktiga, , , och hur billigt det märker och återhämtar dem när de är fel?

```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
```

**riktning-agnostisk självförtroende** `SkipMinConfidence` är kontrollerad mot `verdict.Confidence`, inte emot `verdict.BotProbability`. Ett säkert -botstillstånd och ett visst -mänskligtstillstånd är lika antagliga att hoppa över *självsäkra* bedömningar " ( ett system som är motsägelsefullt mot vilket sätt beviset pekade på

**EWMA, inte MAX.** En enda hög ” - ” sannolikhetsobservation flyttar den körda poängen `α = 0.1` av luckan till observationen.. En riktig attacker samlar fast bevis eftersom *varenda dag* observation is hostil. En legitimt besökare som råkade se ut som en scraper för en fråga bryter sig tillbaka mot godartade vid följande observationer.

**Sammling-storleksmängd.** `confidence = min(1, request_count / 10)`. Nedre ~9 observationer, till och med en stark posterior hålls fast vid fördomar snarare än att hoppa

> **ML bortsett.** Det här är en **förminskning**: tills tillräckligt med bevis har samlats , posterioren inte får att agera med självförtroendet [UCB-bandit](https://en.wikipedia.org/wiki/Multi-armed_bandit#Upper_Confidence_Bound) including a sample -count term: small `n`, bredt tillförtroende intervall , inte använd ' inte ännu utnyttjad

**Variansvakthund.** Även med ett självsäkrat verdict `VarianceWatchdog.Check` gör tre oberoende tester mot `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
```

Rödseln-avståndskontrollen behöver minst 3 separerade vägfamiljer på plats innan den kan aktiveras

```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}");
}
```

Varenda en resa och pipelinen körs färskt ; så bär försvaret `X-StyloBot-WatchdogTrip: ip-rotation:1.2.3.0->5.6.7.0` "(", eller vad som helst som sköts, ")", så att operatörerna ser orsaken

> **ML bortsett.** Vakthunden är **koncept-driftdetektor** för ett fingeravtryck. De klassiska analogerna är [ADWIN](https://www.cs.upc.edu/~gavalda/papers/adwin06.pdf), [Page–Hinkley](https://en.wikipedia.org/wiki/CUSUM), och [DDM](https://link.springer.com/chapter/10.1007/978-3-540-28645-5_29); alla dessa upptäcker att en onlineström 's distribution har förändrats tillräckligt mycket för att den existerande modellen inte längre är tillförlitlig . De tre kontrollerna här är domain, -, specifika driftsignaler, M SK4, drift av nätverkets identitet, (, IP, Mska6, volymdrift, Mske7, tempon, M Ska8, beteendemässig drift, MSC9, bana, centroid, Msek10

**Springa** Även när dörrarna hoppar över pipelinen

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

Faktumet att detektorn övergick skapar inte ett hål i per- -fingerprinthistorien.

**Refresh sampling.** `ShouldRefresh` bedömande nedgraderar en konfigurerad bråkdel av Skip , "-", och Bias , så att pipelinen kör och uppdaterar live-rekordet.`DeterministicBucket.ShouldFire`), så att återförflyttningar från samma klient landar identiskt ; över tid får varje fingeravtryck en periodisk full återföring

> **ML bortsett.** Det här är en deterministisk version **ε-hungrig utforskning** från förstärkningslärning: mestadels utnyttjar man den nuvarande policyn (Skip ), vissa gånger betalar kostnaden för att utforska ♫ ( Bias ♫) ♫ så modellen är kalibrerad ♫

**Beståndsdel -familjsfall.** När ett fingeravtryck roterar och den nya identiteten inte har någon kopierad bedömelse av sin egen ",", faller dörrarna genom till familjen "'", den kanoniska undertecknen . [Leidens klusteranker](/blog/stylobot-fingerprint) från beteendemodellen). Från `TryGetVerdictAsync`:

csharp
if (!_signatureCac
