# Établissement d’un "Lawyer GPT" pour votre blog - Partie SSK3 Local LLM Integration

<!--category-- AI, LLM, LLamaSharp, GGUF, C#, AI-Article, mostlylucid.blogllm -->
<datetime class="hidden">2025-11-12T22:45</datetime>

## Introduction

Bienvenue à la partie 6! Nous ' avons construit l’infrastructure complète[Partie 4](/blog/building-a-lawyer-gpt-for-your-blog-part4)), Client Windows ([Partie 5](/blog/building-a-lawyer-gpt-for-your-blog-part5)), embeddings et recherche par vecteur ([Partie 3](/blog/building-a-lawyer-gpt-for-your-blog-part3)), et mise en place de GPU ([Partie 2](/blog/building-a-lawyer-gpt-for-your-blog-part2)). Maintenant vient la partie excitante : l’intégration d’un LLM local pour produire des suggestions de rédaction

> NOTE: C'est une partie des expériences que j'ai réalisées avec l'A.I. M SK1 rédaction assistée) + ma propre éditionMST4 La même voixM ST5 le même pragmatismeM st6 quelques doigts plus rapidesMst7

C'est là où nous faisons enfin la "AI" partie de "AI assistant à l'écritureMSC3 travailM SK4 NousMST5 ferons fonctionner les grands modèles linguistiques localement sur votre AMSV6 GPUMSP7 générant le contexteMSS8 conscience des suggestions fondées sur vos articles de blog antérieursMSR9

[TOC]

## Pourquoi Local LLM?

Avant de plonger dans l’interface, laissez-leur comprendre pourquoi nous exploitons les modèles localement au lieu d’utiliser OpenAI.

### Comparaison locale vs API

| Aspect | Local LLM MSC2 API MSC3OpenAIMSc4 etc.
|--------|-----------|-------------------|
| **Protection des renseignements personnels** | ✅ Compte tenu de l’information fournie par le fournisseur, les données sont transmises à un tiers.
| **Coût** |
| **Délai** | ✅ ≥<1 seconde | ≤⚠️ Réseau dépendant |
| **Customisation** | ✅ Contrôle complet MSC2 | | 3 | Limitée | | |
| **Choix du modèle** |
| **Offline** | ✅ Travaille en mode offline MSC2 | | 3 | Besoins d'Internet MSC4 |
| **Mise en place** | ❌ Complexe | ≥✅ Simple M|

Pour un assistant à la rédaction, question de confidentialité et de coûts. Nous ne voulons pas que les projets de blog soient envoyés aux API externes , et par–- le prix du token s’additionne rapidement pour un outil de rédaction quotidienM SK5

## Options d'intégration LLM pour C#

Il existe plusieurs façons de faire fonctionner les LLM dans C#:

```mermaid
graph TB
    A[C# Application] --> B{Integration Method}

    B --> C[LLamaSharp]
    B --> D[ONNX Runtime]
    B --> E[TorchSharp]
    B --> F[HTTP API]

    C --> G[llama.cpp bindings]
    G --> H[GGUF Models]

    D --> I[ONNX Models]
    I --> J[Limited Model Support]

    E --> K[PyTorch Models]
    K --> L[Complex Setup]

    F --> M[External Process]
    M --> N[Ollama, LM Studio]

    class C recommended
    class G,H llamaSharp

    classDef recommended stroke:#333,stroke-width:4px
    classDef llamaSharp stroke:#333,stroke-width:2px
```

**Mon choix: LLamaSharp**

Pourquoi?

- Liens natifs C# pour llamaM SK1cpp (bibliothèque d'inférence la plus rapide )
- Appuie le format GGUF (moderneM SK1 modèles quantifiés)
- Accélération CUDA construite-in
- Développement actif et grande communauté
- Travaille avec Llama, Mistral , PhiM SK2 Gemma, et plus

## Comprendre les formats de modèle & Quantisation

### Format GGUF

[GGUF](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md) (GPTM SK1Format unifié généré) est la norme pour le fonctionnement efficace des LLMs .

```mermaid
graph LR
    A[Original Model<br/>Llama 2 7B<br/>~28GB float32] --> B[Quantization]

    B --> C[Q4_K_M<br/>~4.1GB<br/>4-bit]
    B --> D[Q5_K_M<br/>~4.8GB<br/>5-bit]
    B --> E[Q6_K<br/>~5.5GB<br/>6-bit]
    B --> F[Q8_0<br/>~7.2GB<br/>8-bit]

    C --> G[Fast, Lower Quality]
    D --> H[Balanced]
    E --> I[Higher Quality]
    F --> J[Near Original]

    class A original
    class C,D quantized
    class H recommended

    classDef original stroke:#333,stroke-width:2px
    classDef quantized stroke:#333,stroke-width:2px
    classDef recommended stroke:#333,stroke-width:2px
```

**Quantisation expliquée**:

- Modèle original: M SK1 flottants à bits ( très gros, très précisMSC4
- Q4: M SK1 integers bits (75% plus petits, perte minimale de qualitéMSC4
- Q5/QM SK1 Point succulent pour la plupart des cas d'utilisation
- Q8: Près de M SK1Qualité originale, encore 4x plus petit

### Choix du modèle par matériel

| Modèle MSC1 Taille MSC2QMSC3KMSC4MSC5MSC6MSC7MSC Usage du VRAM SMC7MSc Fits ESC8GBMSC9MSC10MSc fits \ESC11GBMSc12MSc13MSc14MSc15MSc16MScQualité \SMC17MSc
|-------|---------------|------------|-----------|------------|------------|---------|
| **Phi-3 Mini (3.8BM SK2** | MSC1GB MSC2 \MSC3GB
| **Llama 2  7B** | 4.1GB | ≥~6GB
| **Mistral 7B** | MSC1GB MSC2 \MSC3GB
| **Gemma 7B** | MSC1GB MSC2 \MSC3GB
| **Llama 3  8B** |  4.7GB
| **Llama 2  13B** |  7.4GB

**Recommandations de GPU:**

- **8GB VRAM**: Commencez par **Mistral 7B** ou **Phi-3 Mini** (safestM SK1
- **12GB VRAM**: **Llama 3  8B** (la meilleure qualitéM SK1 ou **Mistral 7B** (fasterM SK1
- **16GB VRAM (my setup)**: **Llama 3  8B** ou essayer **Modèles 13B**
- **CPU-seulement**: Tous les modèles fonctionnentM SK1 beaucoup plus lentement (démarrer avec PhiMSC3 Mini pour la vitesse)

**Ma recommandation**: **[Mistral 7B](https://mistral.ai/)** (version la plus récente) ou **[Llama 3](https://ai.meta.com/llama/)** 8B

- Excellente qualité pour la rédaction technique
- Travaille sur toutes les tailles de GPU
- assez rapide pour un usage interactif
- Bonne à suivre les instructions

## Téléchargement des modèles

Les modèles sont distribués sur Hugging Face.

### Trouver des modèles GGUF

1. Envoyer à [Le visage de l'écrasement](https://huggingface.co/models)
2. Recherche: `"mistral 7b gguf"`
3. Cherchez TheBloke's quantisations (le plus populaireM SK2

**Liens directs** (TheBlokeM SK1s quantisations):

- [Mistral-7B -Instruct-vM SK3GGUF](https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF)
- [Llama-2-7BM SK1Chat-GGUF](https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF)
- [Llama-3-8BM SK1Instruct-GGUF](https://huggingface.co/QuantFactory/Meta-Llama-3-8B-Instruct-GGUF)

### Télécharger la quantisation spécifique

```bash
# Install huggingface-cli
pip install huggingface-hub

# Download Mistral 7B Q5_K_M (recommended)
huggingface-cli download TheBloke/Mistral-7B-Instruct-v0.2-GGUF \
    mistral-7b-instruct-v0.2.Q5_K_M.gguf \
    --local-dir C:\models\mistral-7b \
    --local-dir-use-symlinks False
```

Ou télécharger manuellement:

1. Cliquez sur l'onglet "Files and versions"
2. Trouver `mistral-7b-instruct-v0.2.Q5_K_M.gguf` (~4.8GBM SK1
3. Cliquer pour télécharger
4. Réservez à `C:\models\mistral-7b\`

## Établissement de LLamaSharp

### Installer NuGet Package

```bash
cd Mostlylucid.BlogLLM.Core
dotnet add package LLamaSharp  # Latest version
dotnet add package LLamaSharp.Backend.Cuda12  # Latest, matching CUDA version
```

**Pourquoi deux paquets?**

- `[LLamaSharp](https://github.com/SciSharp/LLamaSharp)` - Bibliothèque de base
- `LLamaSharp.Backend.Cuda12` - [CUDA](https://developer.nvidia.com/cuda-toolkit) 12 binaires pour l'accélération GPU

### Vérifier la base de données CUDA

LLamaSharp détectera automatiquement la CUDA si elle est correctement installée.

```csharp
using LLama;
using LLama.Common;

// Check if CUDA is available
bool cudaAvailable = NativeLibraryConfig.Instance.CudaEnabled;
Console.WriteLine($"CUDA Available: {cudaAvailable}");
```

Si `false`, vérificationM SK1

1. CUDA 12.x installée (Part 2)
2. `LLamaSharp.Backend.Cuda12` Installation du paquet
3. PATH inclut le répertoire de fichiers CUDA

## Établissement du service LLM

### Paramètres du modèle

```csharp
using LLama;
using LLama.Common;

namespace Mostlylucid.BlogLLM.Core.Services
{
    public class ModelParameters
    {
        public string ModelPath { get; set; } = string.Empty;
        public int ContextSize { get; set; } = 4096;  // Context window
        public int GpuLayerCount { get; set; } = 35;  // Layers on GPU (35 = all for 7B)
        public int Seed { get; set; } = 1337;  // For reproducibility
        public float Temperature { get; set; } = 0.7f;  // Creativity (0.0 = deterministic, 1.0 = creative)
        public float TopP { get; set; } = 0.9f;  // Nucleus sampling
        public int MaxTokens { get; set; } = 500;  // Max generation length
    }
}
```

**Explications des paramètres**:

- **Contexte**: Combien de texte peut le modèle "voirM SK2 à la fois
  
  - 4096 tokens ≈ 3000 mots
  - Plus grand = plus de contexte mais plus lente et plus VRAM

- **Nombre de layers Gpu**: Combien de couches de transformateurs fonctionnent sur GPU
  
  - Les modèles 7B ont des couches ~32
  - 35 = mettre tout sur GPU ( le plus rapide)
  - Les valeurs inférieures = utilisent moins de RAM mais plus lentement

- **Température**: Contrôle de la randomité
  
  - 0.0 = choisissez toujours le symbole qui est le plus probable.
  - 0.7 = bon solde ( notre défautM SK3
  - 1.0+ = très créatif ( peut être sans sens

- **Haut de la page**: Échantillonnage du noyau
  
  - 0.9 = considérer les tokens qui composent 90% de masse de probabilité
  - Prévient l'échantillonnage de tokens très peu probables

### Mise en œuvre du service LLM

```csharp
using LLama;
using LLama.Common;
using Microsoft.Extensions.Logging;

namespace Mostlylucid.BlogLLM.Core.Services
{
    public interface ILlmService
    {
        Task<string> GenerateAsync(string prompt, CancellationToken cancellationToken = default);
        Task<string> GenerateWithContextAsync(string prompt, List<string> contextChunks, CancellationToken cancellationToken = default);
    }

    public class LlmService : ILlmService, IDisposable
    {
        private readonly LLamaWeights _model;
        private readonly LLamaContext _context;
        private readonly ILogger<LlmService> _logger;
        private readonly ModelParameters _parameters;

        public LlmService(ModelParameters parameters, ILogger<LlmService> logger)
        {
            _parameters = parameters;
            _logger = logger;

            _logger.LogInformation("Loading model from {ModelPath}", parameters.ModelPath);

            // Configure model parameters
            var modelParams = new ModelParams(parameters.ModelPath)
            {
                ContextSize = (uint)parameters.ContextSize,
                GpuLayerCount = parameters.GpuLayerCount,
                Seed = (uint)parameters.Seed,
                UseMemoryLock = true,  // Keep model in RAM
                UseMemorymap = true    // Memory-map the model file
            };

            // Load model
            _model = LLamaWeights.LoadFromFile(modelParams);
            _context = _model.CreateContext(modelParams);

            _logger.LogInformation("Model loaded successfully. VRAM used: ~{VRAM}GB",
                EstimateVRAMUsage(parameters.GpuLayerCount));
        }

        public async Task<string> GenerateAsync(string prompt, CancellationToken cancellationToken = default)
        {
            var executor = new InteractiveExecutor(_context);

            var inferenceParams = new InferenceParams
            {
                Temperature = _parameters.Temperature,
                TopP = _parameters.TopP,
                MaxTokens = _parameters.MaxTokens,
                AntiPrompts = new[] { "\n\nUser:", "###" }  // Stop generation at these
            };

            var result = new StringBuilder();

            _logger.LogInformation("Generating response for prompt: {Prompt}", TruncateForLog(prompt));

            await foreach (var token in executor.InferAsync(prompt, inferenceParams, cancellationToken))
            {
                result.Append(token);
            }

            var response = result.ToString().Trim();
            _logger.LogInformation("Generated {Tokens} tokens", CountTokens(response));

            return response;
        }

        public async Task<string> GenerateWithContextAsync(
            string prompt,
            List<string> contextChunks,
            CancellationToken cancellationToken = default)
        {
            // Build prompt with retrieved context
            var fullPrompt = BuildContextualPrompt(prompt, contextChunks);

            _logger.LogInformation("Context chunks: {Count}, Total prompt tokens: ~{Tokens}",
                contextChunks.Count, CountTokens(fullPrompt));

            return await GenerateAsync(fullPrompt, cancellationToken);
        }

        private string BuildContextualPrompt(string userPrompt, List<string> contextChunks)
        {
            var sb = new StringBuilder();

            sb.AppendLine("You are a helpful writing assistant for a technical blog.");
            sb.AppendLine("Use the following excerpts from past blog posts as context:");
            sb.AppendLine();

            for (int i = 0; i < contextChunks.Count; i++)
            {
                sb.AppendLine($"--- Context {i + 1} ---");
                sb.AppendLine(contextChunks[i]);
                sb.AppendLine();
            }

            sb.AppendLine("---");
            sb.AppendLine();
            sb.AppendLine("Based on the context above, help with the following:");
            sb.AppendLine(userPrompt);
            sb.AppendLine();
            sb.AppendLine("Response:");

            return sb.ToString();
        }

        private int CountTokens(string text)
        {
            // Rough estimate: 1 token ≈ 4 characters
            return text.Length / 4;
        }

        private string TruncateForLog(string text, int maxLength = 100)
        {
            if (text.Length <= maxLength) return text;
            return text.Substring(0, maxLength) + "...";
        }

        private double EstimateVRAMUsage(int gpuLayers)
        {
            // Rough estimate for 7B model
            return (gpuLayers / 35.0) * 6.0;  // ~6GB for full 7B model
        }

        public void Dispose()
        {
            _context?.Dispose();
            _model?.Dispose();
        }
    }
}
```

**Comment cela fonctionne**:

1. **Établissement du modèle**: Charge le modèle GGUF dans VRAM à l'aide de paramètres spécifiés
2. **Exécuteur interactif**: LLamaSharp's mode d'exécution pour les interactions similaires à celles du chat
3. **InferAsync**: Écoule les tokens à mesure qu’ils sont générés
4. **Structure du contexte**: Combine la prompte de l'utilisateur avec les chunks du blog récupérés
5. **Prompts anti-**: Interrupt la génération à certaines chaînes.

### Évaluation du service

```csharp
using Microsoft.Extensions.Logging;

class Program
{
    static async Task Main(string[] args)
    {
        // Setup logging
        var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
        var logger = loggerFactory.CreateLogger<LlmService>();

        // Configure model
        var parameters = new ModelParameters
        {
            ModelPath = @"C:\models\mistral-7b\mistral-7b-instruct-v0.2.Q5_K_M.gguf",
            ContextSize = 4096,
            GpuLayerCount = 35,
            Temperature = 0.7f,
            MaxTokens = 200
        };

        // Create service
        using var llmService = new LlmService(parameters, logger);

        // Test simple generation
        Console.WriteLine("=== Test 1: Simple Generation ===\n");
        var response1 = await llmService.GenerateAsync(
            "Explain what Docker Compose is in 2-3 sentences."
        );
        Console.WriteLine(response1);
        Console.WriteLine("\n");

        // Test with context
        Console.WriteLine("=== Test 2: Generation with Context ===\n");
        var context = new List<string>
        {
            "Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services.",
            "In development, Docker Compose makes it easy to spin up all dependencies (databases, caches, etc.) with one command: docker-compose up."
        };

        var response2 = await llmService.GenerateWithContextAsync(
            "Write an introduction paragraph for a blog post about using Docker Compose for development dependencies.",
            context
        );
        Console.WriteLine(response2);
    }
}
```

**Résultats attendus**:

```
=== Test 1: Simple Generation ===

Docker Compose is a tool that allows you to define and run multi-container Docker applications using a simple YAML configuration file. It simplifies the process of managing multiple containers, networking, and volumes, making it ideal for development environments.

=== Test 2: Generation with Context ===

If you've ever found yourself juggling multiple terminal windows to start databases, caches, and other services for local development, Docker Compose is about to become your new best friend. This powerful tool lets you define your entire development environment in a single YAML file and spin everything up with one command. In this post, we'll explore how to leverage Docker Compose to manage all your development dependencies, making your local setup reproducible, shareable, and incredibly easy to manage.
```

Remarquable! Le modèle fonctionne et génère un contexte cohérent

## Intégration avec le panel de suggestions

Maintenant, let's intégrer la génération LLM dans notre client Windows à partir de Partie 5.

### Service de mise à jour des suggestions

```csharp
namespace Mostlylucid.BlogLLM.Client.Services
{
    public class SuggestionService : ISuggestionService
    {
        private readonly BatchEmbeddingService _embeddingService;
        private readonly QdrantVectorStore _vectorStore;
        private readonly ILlmService _llmService;  // NEW

        public SuggestionService(
            BatchEmbeddingService embeddingService,
            QdrantVectorStore vectorStore,
            ILlmService llmService)  // NEW
        {
            _embeddingService = embeddingService;
            _vectorStore = vectorStore;
            _llmService = llmService;
        }

        public async Task<string> GenerateAiSuggestionAsync(
            string currentText,
            List<SimilarPost> context)
        {
            // Extract text from similar posts
            var contextChunks = context
                .Take(3)  // Top 3 most similar
                .Select(p => p.FullText)
                .ToList();

            // Determine what type of suggestion to generate
            var prompt = DeterminePromptType(currentText);

            // Generate suggestion
            var suggestion = await _llmService.GenerateWithContextAsync(
                prompt,
                contextChunks
            );

            return suggestion;
        }

        private string DeterminePromptType(string currentText)
        {
            // Analyze what user is writing
            var lines = currentText.Split('\n');
            var lastLine = lines.LastOrDefault(l => !string.IsNullOrWhiteSpace(l)) ?? "";

            // Is user starting a new section?
            if (lastLine.StartsWith("## "))
            {
                return "Suggest 3-5 bullet points for what this section could cover.";
            }

            // Is user writing code?
            if (lastLine.Contains("```"))
            {
                return "Suggest relevant code examples that might be useful here.";
            }

            // Is user writing an introduction?
            if (currentText.Length < 500 && currentText.Contains("## Introduction"))
            {
                return "Suggest 2-3 sentences to continue this introduction based on similar posts.";
            }

            // Default: continue current thought
            return "Suggest 1-2 sentences to continue the current paragraph in a natural way.";
        }
    }
}
```

### Mise à jour du modèle de visualisation des suggestions

```csharp
public partial class SuggestionsViewModel : ViewModelBase
{
    [RelayCommand]
    private async Task RegenerateSuggestion()
    {
        IsGenerating = true;
        AiSuggestion = "Generating...";

        try
        {
            var currentText = GetCurrentEditorText();  // From messaging
            var suggestion = await _suggestionService.GenerateAiSuggestionAsync(
                currentText,
                SimilarPosts.ToList()
            );

            AiSuggestion = suggestion;
        }
        catch (Exception ex)
        {
            AiSuggestion = $"Error: {ex.Message}";
        }
        finally
        {
            IsGenerating = false;
        }
    }
}
```

## Optimisation du rendement

### Cache de modèles

Garder le modèle chargé entre les demandes:

```csharp
public class LlmServiceFactory
{
    private static LlmService? _instance;
    private static readonly object _lock = new();

    public static LlmService GetInstance(ModelParameters parameters, ILogger<LlmService> logger)
    {
        if (_instance == null)
        {
            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = new LlmService(parameters, logger);
                }
            }
        }

        return _instance;
    }
}
```

### Renouvellement de la Cache KV

LLamaSharp appuie la réutilisation du cache KV pour des générations subséquentes plus rapides:

```csharp
public class StatefulLlmService
{
    private readonly InferenceParams _defaultParams;
    private string _cachedPromptPrefix = string.Empty;

    public async Task<string> GenerateWithPrefixAsync(string prefix, string newPrompt)
    {
        // If prefix matches cached, reuse KV cache
        if (prefix == _cachedPromptPrefix)
        {
            // Only process new tokens
            return await GenerateAsync(newPrompt);
        }

        // Process entire prompt and cache
        _cachedPromptPrefix = prefix;
        return await GenerateAsync(prefix + newPrompt);
    }
}
```

Cela est particulièrement utile pour notre cas d'utilisation.

### Battage

Pour plusieurs suggestions, les emballer en lotsM SK1

```csharp
public async Task<List<string>> GenerateBatchAsync(List<string> prompts)
{
    var results = new List<string>();

    foreach (var prompt in prompts)
    {
        // With KV cache reuse, subsequent prompts are faster
        results.Add(await GenerateAsync(prompt));
    }

    return results;
}
```

## Ingénierie rapide pour l'aide à la rédaction

Bonnes indications = bonne productionM SK1 Voici des modèles pour différents scénarios:

### Continuer à écrire

```csharp
private string PromptContinueWriting(string currentText, List<string> context)
{
    return $@"You are a technical blog writing assistant.

Here are excerpts from similar blog posts:
{string.Join("\n\n", context.Select((c, i) => $"--- Post {i + 1} ---\n{c}"))}

Current draft:
{currentText}

Task: Suggest 2-3 sentences to naturally continue the current paragraph.
Keep the same technical depth and casual, pragmatic tone.

Suggestion:";
}
```

### Suggérer la structure de la section

```csharp
private string PromptSectionStructure(string sectionTitle, List<string> context)
{
    return $@"You are a technical blog writing assistant.

Similar sections from past posts:
{string.Join("\n\n", context)}

New section: {sectionTitle}

Task: Suggest 4-6 bullet points for what this section should cover.
Format as a markdown list.

Bullets:";
}
```

### Exemple de code

```csharp
private string PromptCodeExample(string description, List<string> context)
{
    return $@"You are a C# coding assistant.

Relevant code from past posts:
{string.Join("\n\n", context)}

Task: {description}

Provide a clean, well-commented C# code example.

Code:";
}
```

## Gestion de la mémoire

Avec les grands modèles, la gestion de la mémoire est cruciale,

### Surveillance de l'utilisation du RAM

```csharp
public class VramMonitor
{
    [DllImport("nvml.dll")]
    private static extern int nvmlDeviceGetMemoryInfo(IntPtr device, ref NvmlMemory memory);

    [StructLayout(LayoutKind.Sequential)]
    public struct NvmlMemory
    {
        public ulong Total;
        public ulong Free;
        public ulong Used;
    }

    public static (ulong used, ulong total) GetVramUsage()
    {
        // Simplified - actual implementation needs proper NVML initialization
        var memory = new NvmlMemory();
        // nvmlDeviceGetMemoryInfo(device, ref memory);

        return (memory.Used / 1024 / 1024, memory.Total / 1024 / 1024);  // Convert to MB
    }
}
```

### Décharger le modèle lorsqu'il est inactif

```csharp
public class LlmServiceWithUnload : IDisposable
{
    private LlmService? _service;
    private readonly Timer _unloadTimer;
    private DateTime _lastUsed;

    public LlmServiceWithUnload()
    {
        _unloadTimer = new Timer(CheckForUnload, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
    }

    private void CheckForUnload(object? state)
    {
        if (_service != null && (DateTime.Now - _lastUsed) > TimeSpan.FromMinutes(10))
        {
            _service.Dispose();
            _service = null;
            GC.Collect();
            Console.WriteLine("Model unloaded due to inactivity");
        }
    }

    public async Task<string> GenerateAsync(string prompt)
    {
        _lastUsed = DateTime.Now;

        if (_service == null)
        {
            // Reload model
            _service = CreateService();
        }

        return await _service.GenerateAsync(prompt);
    }
}
```

## Erreur de manutention

Les LLM peuvent échouer de façon inattendue. manipulez avec soin:

```csharp
public async Task<string> GenerateWithRetryAsync(string prompt, int maxRetries = 3)
{
    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            return await GenerateAsync(prompt);
        }
        catch (OutOfMemoryException)
        {
            _logger.LogWarning("OOM error, reducing max tokens");
            _parameters.MaxTokens = Math.Max(100, _parameters.MaxTokens / 2);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Generation failed, attempt {Attempt}/{Max}", i + 1, maxRetries);

            if (i == maxRetries - 1) throw;

            await Task.Delay(1000 * (i + 1));  // Exponential backoff
        }
    }

    throw new Exception("Generation failed after retries");
}
```

## Résumé

Nous' avons réussi à intégrer l’inférence locale LLM:

1. ✅ Choix [LLamaSharp](https://github.com/SciSharp/LLamaSharp) pour l'intégration de C#
2. ✅ Perçu [Format GGUF](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md) et quantisation
3. ✅ Modèle approprié choisi ([Mistral 7B](https://mistral.ai/) / [Llama 3](https://ai.meta.com/llama/) 8BM SK1
4. ✅ LlmService mis en œuvre avec accélération CUDA
5. ✅ intégré avec le client Windows pour des suggestions
6. ✅ Ingénierie rapide pour les tâches de rédaction
7. ✅ Optimisations de performance ajoutées (caching
8. ✅ Gestion et erreurs de mémoire manipulées

## Qu’est-ce que's Suivant?

À l'intérieur **[Partie 7: Production de contenu & Génie rapide](/blog/building-a-lawyer-gpt-for-your-blog-part7)**Nous mettrons l’accent sur le pipeline complet de production de contenu.

- Techniques avancées d'ingénierie rapide
- Multi-conversation de retour pour refinement itératif
- Stratégies de gestion des fenêtres contextuelles
- Évaluation et filtrage de la qualité
- Application de la cohérence du style
- Génie de blocs de code à traiter
- Méthodes d'utilisation du monde réel

Nous ' ferons en sorte que le système soit réellement utile pour la rédaction quotidienne de blogues.

## Navigation des séries

- [Partie 1: Introduction & Architecture](/blog/building-a-lawyer-gpt-for-your-blog-part1)
- [Partie 2: Établissement d'un GPU & CUDA en C#](/blog/building-a-lawyer-gpt-for-your-blog-part2)
- [Partie 3: Comprendre les emplacements & Bases de données vectorielles](/blog/building-a-lawyer-gpt-for-your-blog-part3)
- [Partie 4: Établissement du pipeline d’ingestion](/blog/building-a-lawyer-gpt-for-your-blog-part4)
- [Partie 5: Le client Windows](/blog/building-a-lawyer-gpt-for-your-blog-part5)
- **Partie 6: Intégration locale de LLM** (le présent articleM SK1
- [Partie 7: Production de contenu & Génie rapide](/blog/building-a-lawyer-gpt-for-your-blog-part7)
- [Partie 8: Faits avancés & Déploiement de la production](/blog/building-a-lawyer-gpt-for-your-blog-part8)

## Ressources

- [Documentation LLamaSharp](https://scisharp.github.io/LLamaSharp/)
- [Spécification du format GGUF](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md)
- [Collection de modèles TheBloke'](https://huggingface.co/TheBloke)
- [llama.cpp GitHub](https://github.com/ggerganov/llama.cpp)

Nous vous ferons plaisir. [Partie 7](/blog/building-a-lawyer-gpt-for-your-blog-part7)!