Back to "LLMApi: Maintenir sa vitalité et son existence, Gérer et cacher"

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 AI-Article API ASP.NET Core LLM LLMApi mockllmapi Nuget SignalR

LLMApi: Maintenir sa vitalité et son existence, Gérer et cacher

Thursday, 06 November 2025

Introduction

Dans mon projet LLMApi, j’ai voulu être en mesure d’appuyer la demande de LOTS de données; mais les LLM ont une quantité très limitée de données qu’ils peuvent produire à un moment donné; et ne sont pas particulièrement rapides dans ce domaine '. J’avais donc besoin d’ajouter une façon intelligente de prégénérer ces données et de les livrer en MSC5chunksM SK6 afin que vous puissiez obtenir rapidement des données chunkybackMNK7

Parallèlement, il y a eu le problème des contextes, une grande fonctionnalité mais jusqu'à présent un contexte a duré aussi longtemps que l'application, ce qui ajoute tout le soutien pour un cache glissant afin d'éliminer cette source potentielle de fuites de mémoire si vous laissez le simulateur en marche.

Systèmes de cache &

Communiquer 1.8.0 - Performance avancée & Gestion des ressources

Le présent document décrit deux systèmes puissants qui mostlylucid.mockllmapi intelligents, efficaces , et productionM SK2 prêtes: Établissement d'un appareil automatisé et Cache des réponses.

Lancement rapide: Voir .http pour ready-to-run des exemples HTTP démontrant toutes les fonctionnalités .


Table des matières


Établissement d'un appareil automatisé

Qu'est-ce que l'auto-Chunking?

Auto-chunking est un système intelligent qui transforme automatiquement les grandes demandes en chunks optimaux lorsqu’elles dépassent vos limites de token LLM' It's activé par défaut et fonctionne de façon transparente— vous n’avez pas besoin de changer vos appels API '

Le problème est résolu

Demander 100 des éléments ayant une forme complexe pourrait produire une réponse qui dépasse votre limite de tokens de sortie LLM'.

Solution

Le système:

  1. Estimations Utilisation d'un symbole fondé sur la complexité de forme
  2. Calculs des tailles optimales qui correspondent aux limites
  3. Exécute multiples demandes de LLM automatiquement
  4. Maintenir cohérence entre les chunks en utilisant le contexte
  5. Les combinaisons Résultats d'une seule réponse sans fil

Configuration de l'enregistrement

Ajouter à appsettings.json:

{
  "MockLlmApi": {
    "BaseUrl": "http://localhost:11434/v1/",
    "ModelName": "llama3",

    // Auto-Chunking Settings
    "MaxOutputTokens": 2048,           // LLM output limit (default: 2048)
    "EnableAutoChunking": true,         // Enable automatic chunking (default: true)
    "MaxItems": 1000,                   // Maximum items per response (default: 1000)

    // Input Token Settings
    "MaxInputTokens": 2048              // LLM input limit (default: 2048)
  }
}

Options de configuration expliquées

Établissement Défault MSC2 Description MSC3
MaxOutputTokens 2048
EnableAutoChunking vrai activer globalement/ désactiver le blocage automatique
MaxItems 1000 ≥ Limite stricte pour les articles par réponseM SK3 Les demandes qui dépassent cette limite sont assujetties à un avertissement
MaxInputTokens 2048 ≥ Taille maximale de la saisie de l'interrogatoire. Utilisée pour trunquer l'historique du contexte si nécessaire.

Comment fonctionne le chantage

Vue d'ensemble Flux

flowchart TD
    A[API Request: ?count=100] --> B{Extract Count}
    B --> C{Check MaxItems}
    C -->|Exceeds| D[Cap at MaxItems]
    C -->|Within| E{Check autoChunk param}
    D --> E
    E -->|false| F[Execute Single Request]
    E -->|true/default| G{Estimate Tokens}
    G --> H{Will Exceed<br/>MaxOutputTokens?}
    H -->|No| F
    H -->|Yes| I[Calculate Chunk Strategy]
    I --> J[Execute Chunk 1]
    J --> K[Build Context for Chunk 2]
    K --> L[Execute Chunk 2]
    L --> M{More Chunks?}
    M -->|Yes| N[Build Context for Next]
    M -->|No| O[Combine All Results]
    N --> L
    O --> P[Return Unified Response]
    F --> P

    style I fill:#e1f5ff
    style O fill:#d4edda
    style P fill:#d4edda

1. Estimation du symbole

Le système analyse votre forme JSON pour estimer les tokens par article:

// Simple shape → ~50 tokens/item
{"id": 1, "name": ""}

// Complex nested shape → ~200 tokens/item
{
  "user": {
    "id": 1,
    "profile": {
      "name": "",
      "address": {"street": "", "city": ""},
      "contacts": [{"type": "", "value": ""}]
    }
  }
}

Facteurs d’estimation:

  • La profondeur de nidification (+0.5x par niveau au-delà de 2)
  • Compte de l'arrée (+0.3x par tableau
  • Compte des biens (+0.05x par propriété au-delà de 5)
flowchart LR
    A[Shape JSON] --> B[Parse Structure]
    B --> C[Count Properties]
    B --> D[Measure Nesting Depth]
    B --> E[Count Arrays]
    C --> F[Base Token Count:<br/>Length / 4]
    D --> G[Complexity Multiplier]
    E --> G
    C --> G
    G --> H[Estimated Tokens/Item:<br/>Base × Multiplier]

2. Calcul de la taille du tronçon

Available Output Tokens = MaxOutputTokens × 75%  (25% reserved for prompt overhead)
Items Per Chunk = Available Output Tokens / Estimated Tokens Per Item
Total Chunks = Ceiling(Requested Items / Items Per Chunk)

Exemple:

  • Demande: M SK1 articles
  • Complexité de forme: M SK1 tokens/item
  • MaxOutputTokens: 2048
  • Disponibles: M SK1 tokens (2048 | | 3 | 4 |
  • Articles par tronçon: M SK1 | | (1536 |
  • Résultat: M SK1 fragments de 10 d'articles chacun

3. Exécution par tranche

Chaque chunk:

  1. Reçoit une forme modifiée avec le nombre actualisé
  2. Obtient le contexte des chunks précédents pour la cohérence
  3. Exécute une demande LLM indépendante
  4. Retourne JSON que's a parlé et accumulé

4. Préservation du contexte

Les chunks subséquents reçoivent un contexte comme:

IMPORTANT CONTEXT - Multi-part Response (Part 2/10):
This is a continuation of a larger request. Previous parts have generated:
  Part 1: 10 items (first: id=1, name="Alice", last: id=10, name="Jane")

Ensure consistency with the above data (IDs, names, relationships, style).
Continue numbering, IDs, and patterns logically from where the previous part left off.

Cela garantit que les identifiants ne se démarquent pas de nouveau, que les noms demeurent cohérents et que les données se sentent cohérentes.

Exemples d'utilisation du chantage

Exemple 1: Basic Auto-Chunking

# Request 100 users
GET /api/mock/users?count=100
Content-Type: application/json

{
  "shape": {
    "id": 1,
    "name": "string",
    "email": "[email protected]"
  }
}

Ce qui se passe:

  • Estimations du système ~100 tokensM SK1item
  • Calcule les 4 chunks de 25 articles chacun
  • Exécute automatiquement les demandes de 4 LLM
  • Retourne le tableau combiné des utilisateurs 100

Logs:

[INFO] Request needs chunking: 100 items × 100 tokens/item = 10000 tokens > 1536 available
[INFO] AUTO-CHUNKING ENABLED: Breaking request into 4 chunks (25 items/chunk)
[INFO] AUTO-CHUNKING: Executing chunk 1/4 (items 1-25 of 100)
[INFO] AUTO-CHUNKING: Executing chunk 2/4 (items 26-50 of 100)
[INFO] AUTO-CHUNKING: Executing chunk 3/4 (items 51-75 of 100)
[INFO] AUTO-CHUNKING: Executing chunk 4/4 (items 76-100 of 100)
[INFO] AUTO-CHUNKING COMPLETE: Combined 4 chunks into 100 items

Exemple 2: Opt-Out par demande

# Disable chunking for this specific request
GET /api/mock/users?count=100&autoChunk=false

Utiliser quand:

  • Évaluation des limites de LLM
  • Vous voulez voir le comportement de la truncation
  • Ingénierie de débugging

Exemple 3: MaxItems Limit

# Request 2000 items (exceeds MaxItems=1000)
GET /api/mock/products?count=2000

Résultat:

[WARN] AUTO-LIMIT: Request for 2000 items exceeds MaxItems limit (1000). Capping to 1000 items

Retourne 1000 les articles découpés automatiquement

Exemple 4: Formes ensemencées complexes

POST /api/mock/orders?count=50
Content-Type: application/json

{
  "shape": {
    "orderId": 1,
    "customer": {
      "id": 1,
      "name": "string",
      "address": {
        "street": "string",
        "city": "string",
        "country": "string"
      }
    },
    "items": [
      {"productId": 1, "name": "string", "quantity": 1, "price": 9.99}
    ],
    "shipping": {"method": "string", "trackingNumber": "string"},
    "payment": {"method": "string", "status": "string"}
  }
}

Ce qui se passe:

  • Système de détection d'une complexité élevée ( nidification profondeM SK1 tableaux
  • Estimations ~300 tokensM SK1item
  • Calcule les 10 chunks de 5 articles chacun
  • Maintenir la continuité de l'ID d'ordonnance et les relations avec les clients au sein des groupes

Enregistrement

Toutes les opérations de regroupement sont enregistrées pour être observables:

Logs de débugging:

  • Calcul de l’extraction: Found explicit count in query parameter 'count': 100
  • Aucun regroupement n’est nécessaire: No chunking needed for this request

Logs d'information:

  • Décision de conciliation: Request needs chunking: 100 items × 150 tokens = 15000 tokens > 1536 available
  • Stratégie: Chunking strategy: 100 items → 4 chunks × 25 items/chunk
  • Exécution: AUTO-CHUNKING: Executing chunk 2/4 (items 26-50 of 100)
  • Complétion: AUTO-CHUNKING COMPLETE: Combined 4 chunks into 100 items

Logs d'avertissement:

  • Limite dépassée: AUTO-LIMIT: Request for 2000 items exceeds MaxItems (1000). Capping to 1000

Cache des réponses

Qu'est-ce que le cache de réponse?

Cache des réponses pré-génére plusieurs réponses LLM pour la même demande,les stocker en mémoire et les servir une seule foisM SK2par -une pour fournir une variété sans appels répétés de LLMMSC4

Comment le MSK est-il différent

Contrairement à la cache traditionnelle, (la même réponse chaque fois

  • Résultats obtenus Variations N par demande
  • Serve chaque variante une fois (sliding windowM SK1
  • Remplir dans le fond lorsqu'il est épuisé
  • Provisions diversité tout en maintenant le rendement

Configuration du cache

{
  "MockLlmApi": {
    // Cache Settings
    "MaxCachePerKey": 5,                     // Variants per unique request (default: 5)
    "CacheSlidingExpirationMinutes": 15,     // Idle time before expiration (default: 15)
    "CacheAbsoluteExpirationMinutes": 60,    // Max lifetime (default: 60, null = none)
    "CacheRefreshThresholdPercent": 50,      // Trigger refill at % empty (default: 50)
    "MaxItems": 1000,                        // Max total cached items (default: 1000)
    "CachePriority": 1,                      // Memory priority: 0=Low, 1=Normal, 2=High, 3=Never (default: 1)

    // Advanced Cache Options
    "EnableCacheStatistics": false,          // Track cache hits/misses (default: false)
    "EnableCacheCompression": false          // Compress cached responses (default: false)
  }
}

Le comportement de la Cache

stateDiagram-v2
    [*] --> ColdCache: First Request
    ColdCache --> Generating: Generate N variants
    Generating --> WarmCache: Store variants
    WarmCache --> ServingFromCache: Subsequent requests
    ServingFromCache --> WarmCache: Variants remaining
    ServingFromCache --> RefillTriggered: Last variant served
    RefillTriggered --> BackgroundRefill: Async refill
    BackgroundRefill --> WarmCache: Refill complete
    ServingFromCache --> Expired: 15min idle
    Expired --> [*]

    note right of ColdCache
        Cache miss
        5x LLM calls
        Slow first response
    end note

    note right of ServingFromCache
        Cache hit
        Instant response
        No LLM call
    end note

    note right of BackgroundRefill
        Transparent refill
        User does not wait
        Fresh variants ready
    end note

Demande initiale (Cache froide)

GET /api/mock/users?shape={"id":1,"name":""}
X-Cache-Count: 5

Ce qui se passe:

  1. Le système génère immédiatement des réponses variantes 5
  2. Serve la première variante
  3. Entrepôts restants 4 dans le cache
  4. Temps de réponse: 5× normal (génére toutes les variantesM SK2

Demandes subséquentes (Cache chaude)

# Request 2
GET /api/mock/users?shape={"id":1,"name":""}
X-Cache-Count: 5

Ce qui se passe:

  1. Serve la deuxième variante du cache
  2. Le cache a maintenant des variantes 3.
  3. Temps de réponse: Accès immédiat (pas d'appel LLM)
# Request 5 (last variant)
GET /api/mock/users?shape={"id":1,"name":""}
X-Cache-Count: 5

Ce qui se passe:

  1. Serve la cinquième variante du cache
  2. La cache est maintenant vide
  3. Trigger le renouvellement de l'arrière-plan de 5 nouvelles variantes
  4. Temps de réponse: Immédiat
# Request 6 (refill in progress)
GET /api/mock/users?shape={"id":1,"name":""}
X-Cache-Count: 5

Ce qui se passe:

  1. Refill completed, sert à partir d'un cache renouvelé
  2. Temps de réponse: Immédiat

Uniqueté de la clé du cache

Les clés de cache sont basées sur:

  • Méthode HTTP (GET
  • Voie complète avec chaîne de demande
  • Forme JSON

Différentes demandes gèrent des caches distincts:

GET /api/mock/users?count=10        # Cache Key A
GET /api/mock/users?count=20        # Cache Key B (different count)
GET /api/mock/products?count=10     # Cache Key C (different endpoint)

Exemples d'utilisation du cache

Exemple 1: Enable Caching with Query Parameter

GET /api/mock/users?count=10
X-Cache-Count: 3

Génie 3 variantsM SK1 les sert séquentiellement.

Exemple 2: Enable Caching with Shape Property

POST /api/mock/users
Content-Type: application/json

{
  "shape": {
    "$cache": 5,
    "id": 1,
    "name": "string"
  }
}

Génie 5 variantes.

Exemple 3: Disable Caching

# Don't cache this request
GET /api/mock/random-data?count=10

Non X-Cache-Count ou $cache signifie qu’il n’y a pas de caching—réponse LLM fraîche chaque fois.

Exemple 4: Cache avec activités de recherche

GET /api/mock/users?count=100
X-Cache-Count: 3

Comportement:

  • C'est désactivé lors de l'utilisation du cache (pour éviter la pollution du cache)
  • Si la demande a besoin de chunking,, le caching est parpassé
  • Pratiques exemplaires: Utiliser le cache pour les petits-réponses moyennesM SK2 bouclage pour les grands

Entreposage du contexte

Expiration du contexte

Contextes de l'API (historique des conversations pour maintenir la cohérence entre les demandes) sont stockés avec 15-Exigence d'échéance de sliding en minute.

Comment cela fonctionne

gantt
    title Context Sliding Window Expiration (15 minutes)
    dateFormat mm:ss
    axisFormat %M:%S

    section Context Lifecycle
    Request 1 creates context        :milestone, m1, 00:00, 0m
    Active (15min window)             :active, 00:00, 10m
    Request 2 extends window          :milestone, m2, 10:00, 0m
    Active (window reset)             :active2, 10:00, 15m
    Request 3 after 20min idle        :milestone, m3, 30:00, 0m
    Expired - starts fresh            :crit, 25:00, 5m
# Request 1
GET /api/mock/users/123?context=user-session-1

# Creates context "user-session-1" with 15-minute expiration
# Request 2 (10 minutes later)
GET /api/mock/orders?context=user-session-1

# Context still exists, expiration resets to 15 minutes
# Request 3 (20 minutes after Request 2, no activity for 20 minutes)
GET /api/mock/profile?context=user-session-1

# Context expired, starts fresh

Configuration du contexte

Contextes utilisent les mêmes paramètres d'expiration:

{
  "MockLlmApi": {
    "MaxInputTokens": 2048    // Contexts are truncated to fit within this limit
  }
}

L'entreposage de contexte est mis en œuvre en utilisant IMemoryCache avec:

  • Date d'expiration des Sliding: 15 minutes (hardcodedM SK2
  • Case-noms insensibles: "UserM SK1Session" =
  • Nettoyage automatique: Les contextes expirés sont supprimés automatiquement
  • Aucune fuite de mémoire: Les appels d'évacuation nettoient les dictionaries de suivi

Pratiques exemplaires

Quand utiliser le chantage

Utiliser le regroupement lorsque:

  • Demande de > 20 articles ayant des formes complexes
  • Travailler avec les données hiérarchiques nested/
  • Demander des centaines d'articles

Ne disablez pas les chunkings à moins de :

  • Évaluation des limites du token LLM
  • Ingénierie de débugging
  • Vous voulez voir le comportement de la truncation

Quand utiliser le cache

Utiliser le cache lorsque:

  • Le modèle de demande est répétitif (e .gM SK2 données descendantes, listes de référenceMSC4
  • Variété souhaitée (utilisateurs de modèle différents chaque foisM SK1
  • Questions liées au rendement (réponses immédiatesM SK1

Donn't cache lorsque:

  • Chaque réponse doit être unique (eM SK1g.,génération de données d'essai aléatoires )
  • Les données doivent être spécifiques à la session
  • Le volume de demande est faible (cache surcoût ne vaut pas la peineM SK1

Configuration optimale

Petits LLM (e.gM SK2 tinyllamaMSC3

{
  "MaxOutputTokens": 512,
  "MaxInputTokens": 1024,
  "MaxCachePerKey": 3,
  "EnableAutoChunking": true
}

LLM moyennes (eM SK1g., Llama 3):

{
  "MaxOutputTokens": 2048,
  "MaxInputTokens": 2048,
  "MaxCachePerKey": 5,
  "EnableAutoChunking": true
}

Larges LLM (eM SK1g., Llama 3 70BMSC5

{
  "MaxOutputTokens": 4096,
  "MaxInputTokens": 4096,
  "MaxCachePerKey": 5,
  "EnableAutoChunking": true
}

Troubleshooting

Questions liées à la recherche

Problème: "Requête pour des articles 100 ne retourne que SSK2

Solution: Vérifier les logs de l’exécution du chunking. Si le chunking n’est pas effectué, augmenter MaxOutputTokens:

{
  "MaxOutputTokens": 4096    // Increase limit
}

Problème: "Les chunks ont des IDs incohérents (Les IDs restartent à 1 pour chaque chunk

Solution: Il s’agit d’un problème rare de comportement LLM. Try:

  1. Utiliser un modèle différent
  2. Accroître Temperature pour une plus grande créativité
  3. Ajouter des plages d'identification explicites en forme: {"id": "start at 1 and increment"}

Problème: "Too many chunks generated (performance impactM SK2

Solution:

  1. Simplifier votre forme (d'éliminer les nidifications inutiles)
  2. Accroître MaxOutputTokens
  3. Réduire le nombre demandé
  4. Utilisation ?autoChunk=false si vous n’avez pas besoin d’un ensemble de données complet

Questions de cache

Problème: "La même réponse à chaque fois malgré le cache"

Solution: La cache est vide, le renouvellement de fond peut être lent . Vérifier:

  1. Le service LLM est réceptif
  2. Accroître MaxCachePerKey pour plus de variantes
  3. Vérifier les registres pour "Fausse recharge de fond

Problème: "Le cache n'est pas utiliséM SK1

Solution: Assurez-vous que vous spécifiez le cache avec either:

  • Paramètre de la demande: ?cache=5
  • Intitulé: X-Cache-Count: 5
  • Propriété de forme: "$cache": 5

Problème: "Utilisation croissante des mémoiresM SK1

Solution:

  1. Réduire MaxCachePerKey (moins variantesM SK1
  2. Réduire CacheSlidingExpirationMinutes (expire plus rapidementM SK1
  3. Activer EnableCacheCompression: true (trade CPU pour mémoire)
  4. Réduire MaxItems (cap dur sur la taille du cache)

Questions de contexte

Problème: "Contexte perdu entre demandes"

Solution: Contexte expiré (15 minutes d’inactivitéM SK1 Si vous avez besoin de plus de temps:

  • Faire des demandes plus fréquemment pour garder le contexte vivant
  • Considérer l’utilisation d’un stockage contextuel persistant (requête de fonctionnalité pour la prochaine mise à jour)

Problème: "Contexte de plus en plus grand

Solution: Les contextes sont résumés automatiquement lorsqu'ils dépassent MaxInputTokens. Vérifier

  1. Les logs montrent les messages "Contexte résumé"
  2. Accroître MaxInputTokens le cas échéant
  3. Utiliser des noms de contexte plus courts pour améliorer l'efficacité

Mesures de rendement

Présentation de la musique chinoise

Scénario Sans augmentation de la fréquence de l’échantillonnage
100 articles simples MSC2 tronqués MSC3 complets ≥MSC4 tronçons ≤MSC5 ≥ MSC6 Travaux vs. Défaut
50 articles complexes tronqués complets \10 tronçons Travaux vs. Défaut
10 articles 3 4 5 Pas de frais généraux

Rendement en cache

Scénario Sans cache Avec cache ♫ (Claire ♫ ) Amélioration ♫
Requête simple 2.1s M ≥0.002s 1000× plus rapide
Demande complexe 1800× plus rapide
Première requête 2 3 4 5 variantes 5× plus lente (primanteM SK2

Utilisation de la mémoire

Configuration
Sans cache MSC2 Ligne de base MB MSC3
CacheM SK1 5 variantes × \100 clés
CacheM SK1 5 variantes × \1000 clés
Entreposage du contexte (100 actif) ≥+10 MB

Historique de la version

  • v1.8.0 - Mise à jour initiale de l’auto-chunking et du caching amélioré
  • v1.7.0 - Système de cache de base
  • v1.6.0 - Entreposage du contexte introduit

Pour plus de détails, voir RELEASE_NOTES.md.

logo

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