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
Cooking with DiSE (Part 4): Building Systems That LearnM SK2 Adaptation, and Evolve
Monday, 08 December 2025
La plupart des architectures logicielles présupposent que le système est statique. DiSE présuppose qu’il est vivant
Note: Il s’agit de la partie 4 de la série "Cooking with DiSEM SK2 Partie 1, Partie 2: Apprentis diplômés, et Partie 3: Gods intrustworthy pour l’arrière-plan. Cet article est un aperçu architectural - et maintenant nous avons une mise en œuvre de travail CM SK2 mostlylucid.botdetection.
Concept clé: Routage comportemental. Cette architecture permet une nouvelle catégorie - où les détecteurs et les systèmes d’apprentissage transparents , réglables Portail YARP, Les bots ne parviennent jamais à votre backend. Ou utiliser le middleware pour construire des rouages comportementaux directement dans votre couche d'applicationM SK2
Le problème: Systèmes statiques dans un monde dynamique
Depuis des années, nous avons construit des logiciels comme le clockwork, les entrées et les sorties, les règles, les conduites, les essais et les déploiements.
Mais les systèmes modernes -, en particulier AI-augmentés - ne se comportent plus comme des horlogesM SK3 Ils se comporteront comme des écosystèmes
- Les agresseurs développent leurs techniques
- Les utilisateurs changent leur comportement
- Les exigences évoluent avec le temps
- L'environnement évolue constamment
Les architectures statiques ne peuvent't conserver le rythme. Vous remédiez à un trou , trois autres apparaissentM SK3 Vous réglagez un seuil , quelque chose se débrouilleMSC5 VousMNK6 vous réagissons toujoursMMK7 vous ne vous adaptez jamaisMRK8
Architecture DiSE (Evolution synthétique dirigée ) traite les logiciels comme les biologistes traitent les organismes: comme quelque chose qui doit s’adapterMSC3 soi-mêmeM SK4 corrigerMNK5 et se perfectionner sous pressionMRK6
L’idée fondamentale: Les systèmes comme organismes en évolution
Architecture traditionnelle:
flowchart LR
B[Build] --> S[Ship] --> P[Patch] --> B
style B stroke:#6366f1,stroke-width:2px
style P stroke:#ef4444,stroke-width:2px
Architecture DiSE:
flowchart LR
P[Perceive] --> E[Evaluate] --> M[Mutate] --> S[Select] --> P
style P stroke:#10b981,stroke-width:2px
style M stroke:#f59e0b,stroke-width:2px
style S stroke:#6366f1,stroke-width:2px
Un système DiSE comporte quatre comportements essentiels:
| Comportement | Ce qu'il fait | Équivalence biologique |
|---|---|---|
| Percevoir | Recueillir les signaux de l'environnement | Organes sensoriels |
| Évaluer | Signales de score contre les buts | Système nerveux |
| Mutate | Générer des variantes de stratégies | Mutation génétique |
| Sélectionner | Gardez ce qui fonctionneM SK1 jetez de côté ce qui ne fonctionne pas |
C’est literally la façon dont votre système évolue avec le temps pour adopter des comportements plus intelligents.
Exemple de béton: Détection du boit
mostlylucid.botdetection est la première mise en œuvre C# des principes de DiSE . Let's tracer l’architectureM SK3
Perception: L’architecture des tableaux noirs
Le système utilise un orchestrateur blackboard - les détecteurs contribuent à la formation d’un état partagé, déclenchent d’autres détectors au fur et à mesure que les signaux s’accumulentM SK2
// Detectors emit contributions (evidence), not verdicts
public sealed record DetectionContribution
{
public required string DetectorName { get; init; }
public required string Category { get; init; }
// Positive = bot signal, Negative = human signal
public required double ConfidenceDelta { get; init; }
public double Weight { get; init; } = 1.0;
public required string Reason { get; init; }
public BotType? BotType { get; init; }
// Signals for triggering other detectors
public ImmutableDictionary<string, object> Signals { get; init; }
}
Plusieurs détecteurs fonctionnent dans les ondes parallèles. Chacune d’entre elles fournit une pièce de preuve . Le système perçoit l’environnement à travers de nombreuses lentilles.
// Wave 0: All detectors with no trigger conditions run in parallel
// Wave N: Detectors whose triggers are now satisfied run in parallel
while (waveNumber < MaxWaves && !cancellationToken.IsCancellationRequested)
{
var readyDetectors = availableDetectors
.Where(d => !ranDetectors.Contains(d.Name))
.Where(d => CanRun(d, state.Signals))
.ToList();
await ExecuteWaveAsync(readyDetectors, state, aggregator, ...);
// Check for early exit on high confidence
if (aggregator.ShouldEarlyExit)
break;
}
Évaluation: Consensus pondéré avec Sigmoid
Les preuves sont agrégées dans une décision en utilisant la transformation sigmoïde - ce qui permet de lever correctement les signaux forts provenant des détecteurs de poids élevés -
private (double botProbability, double confidence) CalculateWeightedScore()
{
var weighted = _contributions
.Where(c => c.Weight > 0)
.Select(c => (delta: c.ConfidenceDelta, weight: c.Weight))
.ToList();
var weightedSum = weighted.Sum(w => w.delta * w.weight);
// Sigmoid maps any real number to (0, 1)
// Strong human signal (-3) → ~5% bot probability
// Neutral (0) → 50% bot probability
// Strong bot signal (+3) → ~95% bot probability
var botProbability = 1.0 / (1.0 + Math.Exp(-weightedSum));
return (botProbability, confidence);
}
L’évaluation n’est pas un modèle unique qui prend une décision. consensus pondéré sur plusieurs détecteurs spécialisés - et de façon cruciale , lorsque l’AI n’a pas effectué d’essai de clamped pour éviter la surconfidence:
// CRITICAL: Clamp probability when AI hasn't run
var botProbability = aiRan
? rawBotProbability
: Math.Clamp(rawBotProbability, 0.20, 0.80);
Exit précoce: Optimisation du chemin rapide
Le système ne fonctionne pas tous les détecteurs.
// Early exit on verified bots (good or bad)
public static DetectionContribution VerifiedGoodBot(
string detector, string botName, string reason) => new()
{
DetectorName = detector,
Category = "Verification",
ConfidenceDelta = 0,
TriggerEarlyExit = true,
EarlyExitVerdict = EarlyExitVerdict.VerifiedGoodBot
};
En production, hautes -requêtes de confiance qui sortent sous 10ms après que les détecteurs 2-3 soient convenusM SK1 Le pipeline complet ne fonctionne qu’en cas incertains.
Réparateurs de circuits: SelfM SK1Healing
Les détecteurs peuvent échouer. Le système se protège lui-même:
// Circuit breaker per detector
private void RecordFailure(string detectorName)
{
var state = _circuitStates.GetOrAdd(detectorName, _ => new CircuitState());
state.FailureCount++;
state.LastFailure = DateTimeOffset.UtcNow;
if (state.FailureCount >= CircuitBreakerThreshold)
{
state.State = CircuitBreakerState.Open;
// Detector disabled until reset time passes
}
}
Les détecteurs qui ont échoué sont temporairement désactivés. Après un refroidissementM SK1 ils 'ont essayé de nouveau (deuxième partieMST4état ouvertMSC5 C'est pression de sélection au niveau des infrastructures.
Mutation: Le système d'apprentissage
Lorsque le système détecte avec grande confiance, il apprentissage par publication au bus de l’événement d’apprentissage:
private void PublishLearningEvent(AggregatedEvidence result, ...)
{
var eventType = result.BotProbability >= 0.8
? LearningEventType.HighConfidenceDetection
: LearningEventType.FullDetection;
_learningBus.TryPublish(new LearningEvent
{
Type = eventType,
Confidence = result.Confidence,
Label = result.BotProbability >= 0.5,
Metadata = new Dictionary<string, object>
{
["botProbability"] = result.BotProbability,
["categoryBreakdown"] = result.CategoryBreakdown,
["contributingDetectors"] = result.ContributingDetectors
}
});
}
Cette information est transmise à l’entrepôt de pesage, afin d’actualiser le détecteur héuristique' les poids appris au fil du tempsM SK2
Le panier cognitif
Au lieu d’un seul cerveau "AIM SK1 DiSE utilise la cognition en couche
flowchart TB
subgraph Fast["Fast Path (< 100ms)"]
H[Static Heuristics]
D[Detectors]
ML[Learned Heuristic Model]
end
subgraph Slow["Slow Path (Async)"]
LLM[Ollama LLM]
end
subgraph Learn["Learning Layer"]
W[Weight Store]
Rep[Reputation]
end
Fast --> |escalate uncertain| Slow
Slow --> |label| Learn
Learn --> |update weights| Fast
style Fast stroke:#10b981,stroke-width:2px
style Slow stroke:#6366f1,stroke-width:2px
style Learn stroke:#f59e0b,stroke-width:2px
| couche | vitesse MSC2 but MSC3 exemple de détection du boit SMC4 | |
|---|---|---|
| Héuristique statique Réponses instinctives | Patterns de l'UA connus du robot | |
| Détecteurs | <10ms | Observation du traité SMK3 Analyse de l'en-tête MMK4 Contrôles IP RMK5 |
| Étudié en héuristique Classification dynamique | Régression logistique avec les poids appriss | |
| LLM | 50-500ms | Rationalisation approfondie MSC3 Analyse de nouveaux patrons SMC4 |
| Apprentissage | Contexte MSC1 Formation de la mémoire MSC2 Mise à jour du poids MSc3 changements de réputation SMC4 |
L’influence clé: le système apprend ses propres poids en temps réel -timeM SK2 Aucun modèle ML externe n’est requis. Le détecteur héuriste commence par des défauts sensibles et évolue sur la base du rétroaction de détectionMSC4
Avenir: Les modèles ONNX avec RAG et embedding sont prévus pour v2. Le modèle héuriste actuel' sa sortie sert de données d’entraînement marquées pour la formation future du modèleM SK2 L’architecture dispose déjà des MSC3 artefacts génétiques " ( contributionsMNK6 pondérations MNK7 signauxMMK8 qui rendent l’ajout d’une évolution synthétique dirigée plus simple
Cela reflète la cognition biologique:
- Système immunitaire inhérent → Héuristique statique
- Système immunitaire adaptatif → Étudié le modèle héuristique
- Cellules de mémoire → magasin de poids + réputation
Le détecteur héuristique: Apprentissage sans modèles externes
C’est là' le bit intelligent. Au lieu d’expédier un modèle ML externe ,, le système apprend son propre classeur en utilisant une simple régression logistique avec extraction dynamique des caractéristiques.
public class HeuristicDetector : IDetector
{
// Default weights - sensible starting points
private static readonly Dictionary<string, float> DefaultWeights = new()
{
// Human-like patterns (negative = more likely human)
["hdr:accept-language"] = -0.6f,
["hdr:referer"] = -0.4f,
["fp:received"] = -0.7f, // Fingerprint = strong human signal
["fp:legitimate"] = -0.8f,
// Bot indicators (positive = more likely bot)
["ua:contains_bot"] = 0.9f,
["ua:headless"] = 0.8f,
["ua:selenium"] = 0.7f,
["ua:curl"] = 0.6f,
["accept:wildcard"] = 0.4f,
};
private (bool IsBot, double Probability) RunInference(Dictionary<string, float> features)
{
// Simple linear model: score = bias + Σ(feature * weight)
float score = _bias;
foreach (var (featureName, featureValue) in features)
{
var weight = _weights.TryGetValue(featureName, out var w)
? w
: DefaultNewFeatureWeight;
score += featureValue * weight;
}
// Sigmoid gives us probability
var probability = 1.0 / (1.0 + Math.Exp(-score));
return (probability > 0.5, probability);
}
}
Les caractéristiques sont extraites dynamiquement de la demande et des preuves agrégées:
public static class HeuristicFeatureExtractor
{
public static Dictionary<string, float> ExtractFeatures(
HttpContext context,
AggregatedEvidence evidence)
{
var features = new Dictionary<string, float>();
// Request metadata
features["req:header_count"] = Math.Min(headers.Count / 20f, 1f);
features["req:cookie_count"] = Math.Min(cookies.Count / 10f, 1f);
// Header presence
features["hdr:accept-language"] = headers.ContainsKey("Accept-Language") ? 1f : 0f;
// UA patterns (dynamic - only present if detected)
if (ua.Contains("bot")) features["ua:contains_bot"] = 1f;
if (ua.Contains("selenium")) features["ua:selenium"] = 1f;
// Detector results (named by actual detector)
foreach (var contrib in evidence.Contributions)
features[$"det:{contrib.DetectorName}"] = contrib.ConfidenceDelta;
// Client-side fingerprint - STRONG human signal
if (hasFingerprint)
{
features["fp:received"] = 1f;
features["fp:legitimate"] = 1f;
}
return features;
}
}
Les nouvelles fonctionnalités reçoivent automatiquement des poids par défaut et apprennent avec le temps. Le système découvre ce qui importeM SK1
Le magasin de poids: Apprentissage continu
Les poids persistent dans SQLite et sont mis à jour par moyen mobile exponentiel:
public class SqliteWeightStore : IWeightStore
{
public async Task RecordObservationAsync(
string signatureType,
string signature,
bool wasBot,
double detectionConfidence,
CancellationToken ct = default)
{
// EMA update: weight = weight * (1 - α) + new_value * α
var alpha = 0.1; // Learning rate
var weightDelta = wasBot ? detectionConfidence : -detectionConfidence;
var sql = @"
INSERT INTO learned_weights (signature_type, signature, weight, ...)
VALUES (@type, @sig, @delta, ...)
ON CONFLICT(signature_type, signature) DO UPDATE SET
weight = weight * (1 - @alpha) + @delta * @alpha,
confidence = MIN(1.0, confidence + @conf * 0.01),
observation_count = observation_count + 1,
last_seen = @now
";
await ExecuteAsync(sql, ...);
}
}
Il s'agit de mutation par l'observation. Chaque détection instructe le système à faire quelque chose . Au fil du tempsM SK2 les poids convergent vers des valeurs optimales pour vos modèles de trafic particuliers.
Hallucinations en tant que mutation
Dans DiSE, la hallucination LLM n’est pas un bug; elle est le substrat générateur de l’évolution.
Un LLM à température élevée, qui propose dix variantes d’une règle de détection, n’est pas : mutation du génome du système:
public async Task<List<DetectionRule>> GenerateMutationsAsync(DetectionContext context)
{
var prompt = $"""
Given this traffic pattern:
{JsonSerializer.Serialize(context)}
Generate 5 variant detection rules that might catch similar patterns.
Return JSON array of rules with: pattern, weight, confidence.
Be creative. Some variants should be strict, some lenient.
""";
var response = await _ollama.GenerateAsync(new GenerateRequest
{
Model = "gemma3:1b",
Prompt = prompt,
Options = new RequestOptions { Temperature = 0.9 } // High creativity
});
return ParseRules(response.Response);
}
Les mutations sont ensuite évaluées en fonction des données historiques:
public async Task<DetectionRule?> SelectFittestAsync(
List<DetectionRule> mutations,
List<LabeledRequest> testData)
{
var results = new List<(DetectionRule Rule, double Fitness)>();
foreach (var rule in mutations)
{
var tp = testData.Count(r => rule.Matches(r) && r.IsBot);
var fp = testData.Count(r => rule.Matches(r) && !r.IsBot);
var fn = testData.Count(r => !rule.Matches(r) && r.IsBot);
// F1 score as fitness
var precision = tp / (double)(tp + fp);
var recall = tp / (double)(tp + fn);
var f1 = 2 * (precision * recall) / (precision + recall);
results.Add((rule, f1));
}
return results.OrderByDescending(r => r.Fitness).First().Rule;
}
Seuls les plus aptes survivent à la production. Cela transforme les LLM de chatbots fragiles en opérateurs évolutifs.
Configuration basée sur le génome
Au centre de DiSE se trouve le système de politique - configurations désignées qui définissent le comportement de la détection
{
"Policies": {
"fastpath": {
"Description": "Fast path + Heuristic for sync decisions",
"FastPath": ["UserAgent", "Header", "Ip", "Behavioral", "ClientSide", "Inconsistency", "VersionAge"],
"AiPath": ["Heuristic"],
"EscalateToAi": true,
"EarlyExitThreshold": 0.15,
"ImmediateBlockThreshold": 0.90,
"Weights": {
"ClientSide": 0.2,
"Heuristic": 1.5
},
"Transitions": [
{ "WhenRiskExceeds": 0.5, "WhenRiskBelow": 0.85, "GoTo": "demo" }
]
},
"demo": {
"Description": "Full pipeline sync for demonstration",
"FastPath": [],
"AiPath": [],
"BypassTriggerConditions": true,
"ForceSlowPath": true
}
}
}
Politiques définies:
- Détecteurs FastPath - courir parallèlement, sousM SK2ms
- Voie de l'AI - Héuristique (1-5ms) etM SK3ou LLM (500ms+)
- Seuils - quand se retirer tôt, quand bloquer
- Transitions - escalation automatique vers d’autres politiques lorsqu’elles sont incertaines
- Pour -poids de politique - Importance du détecteur de son par cas d'utilisation
Le système peut transition entre les politiques à la mi-- demande. Les résultats incertains des pistes rapides s’élargent jusqu’à l’ensemble du pipeline de démonstration. routage adaptatif - le génome répond aux preuves en temps réel
Vous n't expédiez les configurations statiques. vous expédier espèces comportementales qui se prêtent au trafic.
Fonctions de la condition physique: Ce qui survive
Tous les systèmes DiSE optimisent contre un paysage de fitness:
public class FitnessEvaluator
{
public double Evaluate(GenomeConfig genome, EvaluationData data)
{
var fpRate = data.FalsePositives / (double)data.TotalHumans;
var fnRate = data.FalseNegatives / (double)data.TotalBots;
var latency = data.P99LatencyMs;
var cost = data.AiCallsPerRequest * _config.CostPerAiCall;
// Multi-objective fitness
return 1.0
- (fpRate * _config.FalsePositivePenalty) // Don't block humans
- (fnRate * _config.FalseNegativePenalty) // Don't miss bots
- (latency / _config.MaxLatencyMs) // Stay fast
- (cost / _config.MaxCostPerRequest); // Stay cheap
}
}
Nous n’optimisons pas uniquement l’exactitude de la méthode .; nous optimisons également survie dans un environnement dynamique.
trop d’AI → coût élevé, latence médiocre . Trop peu d’AI → faible détection des nouveaux attaquesM SK1 Trop agressif → faux positifsM SK1 utilisateurs angry. trop souple → inondations de robots.
Le système doit trouver un équilibre stable.
AI comme enseignant, Non travailleur
Un système DiSE mature déplace l’AI du chemin chaud:
flowchart TB
subgraph Early["Early Stage"]
AI1[AI handles most cases]
end
subgraph Middle["Middle Stage"]
AI2[AI handles edge cases]
H1[Heuristics handle common cases]
end
subgraph Mature["Mature Stage"]
AI3[AI teaches and mutates]
H2[Heuristics handle almost everything]
M[Memory provides context]
end
Early --> Middle --> Mature
style Early stroke:#ef4444,stroke-width:2px
style Middle stroke:#f59e0b,stroke-width:2px
style Mature stroke:#10b981,stroke-width:2px
Au fil du temps:
- Les détecteurs statiques améliorent (trainés par des étiquettes d'AIM SK1
- Les héuristiques sont plus exactes (sélectionnée par la condition physiqueM SK1
- L'AI ne traite que de la nouveauté et des mutations.
AI devient:
- L'article 5 de la Loi sur l'immigration et le statut des réfugiés oracle pour les comportements nouveaux
- L'article 5 de la Loi sur l'immigration et le statut des réfugiés génératrice de mutations
- L'article 5 de la Loi sur l'immigration et le statut des réfugiés détecteur de dérivation
- L'article 5 de la Loi sur l'immigration et le statut des réfugiés enseignant qui étiquette les cas frontaliers
Aucune dépendance de temps d'exécution. Établissement adaptatif.
Routage comportemental: Une nouvelle catégorie
En ce qui concerne les Portail YARP, cette architecture permet de créer quelque chose de nouveau : routage comportemental.
Le routage traditionnel est statique: chemin M SK1 backend. le routage comportemental est réflexif : caractéristiques de trafic
flowchart LR
subgraph Gateway["YARP Gateway"]
D[Detector Team]
P[Policy Engine]
R[Router]
end
Traffic[Traffic] --> D
D --> P
P --> R
R -->|Human| App[Your App]
R -->|Bot| Block[403]
R -->|Uncertain| Challenge[Challenge]
R -->|Learning| Queue[Async Analysis]
style Gateway stroke:#10b981,stroke-width:2px
Les concepts clés:
- Équipes de détection - groupes configurables de détecteurs qui travaillent ensemble, réglables par politique
- Décisions transparentes - chaque décision de routage est explicable voir la ventilation des contributions
- Ajustement réflexif - le système apprend de ses décisions et ajuste les poids au fil du temps
- Protection de niveau Edge- - les bots ne parviennent jamais à votre backend; bloqué au router
Il s’agit d’un nouveau modèle de routage primitive où les flux de trafic sont formés par des modèles de comportements appriss.
Pourquoi cela importe?
La plupart des cultures d’ingénierie craignent
- Nondeterminisme
- Déplacement
- La mutation
- La hallucination
- Comportement d'urgence
DiSE les utilise comme suit : matériaux de construction.
Systèmes statiques décèdent. Les systèmes évolutifs surviventM SK1
Toutes les industries qui font face à des adversaires, soit ,, drift, , ou pression d’échelle, auront besoin de telles architectures.
- Détection des bottes
- Mécanismes de fraude
- Firewalls adaptés
- Écosystèmes LLM
- Self-optimisation des microservices
- Systèmes de débugging autonomes
- Routage comportemental - Formation du trafic fondée sur les modèles appriss
Qu'est-ce que DiSE?
Permettez-moi de préciser ce qui est dit :
- Pas "les grands LLM partout" - Les LLM sont coûteux. Utilisez-les de façon stratégique
- Non "remplacer la logique d'affaires par AI" - Les héuristiques sont plus rapides et plus prévisibles
- Ce n'est pas "le système doit fonctionner de façon sauvage" - L'évolution est dirigée , délimitée M SK2 gouvernée .
- Non "AutoML sur les stéroïdes" - Il s’agit d’un comportement , pas seulement de la modélisation des modèles M SK2
DiSE est contrôlé, évolution explicableM SK1
- Limitée par des contraintes
- géré par des fonctions explicites d'aptitude
- Memory-aware
- Versions
- Sécurité au déploiement
Il s’agit d’un système de gestion des ressources humaines qui a été mis en place dans le cadre duquel les ministères et organismes fédéraux, provinciaux et territoriaux participent à l’élaboration des politiques. Directeur général de l’Agence evolution - guidé, non aléatoireM SK2
Essayez-le
mostlylucid.botdetection applique ces principes:
dotnet add package Mostlylucid.BotDetection
builder.Services.AddBotDetection();
app.UseBotDetection();
Configurer pour la production avec l'apprentissage activé:
{
"BotDetection": {
"BotThreshold": 0.7,
"Policies": {
"default": {
"FastPath": ["UserAgent", "Header", "Ip", "Behavioral", "ClientSide", "Inconsistency", "VersionAge"],
"AiPath": ["Heuristic", "Llm"],
"EscalateToAi": true,
"EarlyExitThreshold": 0.85
}
},
"AiDetection": {
"Provider": "Heuristic",
"Heuristic": {
"Enabled": true,
"LoadLearnedWeights": true,
"EnableWeightLearning": true,
"LearningRate": 0.01
}
}
}
}
Surveillez son évolution. Le détecteur héuriste apprend à partir de chaque demande, mettant à jour ses poids pour correspondre aux patrons de votre traficM SK2
Conclusion
DiSE Architecture est le passage du logiciel comme machine au logiciel comme organisme.
Il s’agit de l’architecture de
- Adaptabilité
- Résilience
- Évolution contrôlée
- Cognition stratifiée
- Mémoire-apprentissage dirigé
- Modification de la sélection +
- Comportement stratégique
Les architectures statiques ne peuvent pas tenir compte des environnements dynamiques. Les agresseurs évoluent. Les utilisateurs évoluent≥. Les exigences évoluent~.
Les systèmes doivent évoluer too.
Si vous voulez des systèmes qui fonctionnent simplement, les bâtir de la vieille façon. Si vous voulez des systèmes qui survivre - les bâtir avec DiSE.