# Bâtir un "avocat GPT" pour votre blog - Partie 6: Intégration locale LLM

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

AVERTISSEMENT: CES PROJETS DE POSTES QUI 'ESCAPÉ'.

Il est probable qu'une grande partie de ce qui est ci-dessous ne fonctionnera pas; je les génère comme comment faire pour MOI, puis faire toutes les étapes et obtenir le travail de l'application d'échantillon ... Vous avez été sournois et les a vus! ils seront probablement prêts à la mi-décembre.

<img src="https://media1.tenor.com/m/_rQc7PIEqwQAAAAd/cat-hello-cat-peek.gif" height="300px" />
## Présentation

Bienvenue dans la 6ème partie![Nous avons construit l'infrastructure complète - pipeline d'ingestion (](/blog/building-a-lawyer-gpt-for-your-blog-part4)Quatrième partie[), client Windows (](/blog/building-a-lawyer-gpt-for-your-blog-part5)Cinquième partie[) , l'intégration et la recherche vectorielle (](/blog/building-a-lawyer-gpt-for-your-blog-part3)Troisième partie[) et configuration du GPU (](/blog/building-a-lawyer-gpt-for-your-blog-part2)Deuxième partie



Maintenant vient la partie passionnante: l'intégration d'un LLM local pour générer des suggestions d'écriture.

[TOC]

## REMARQUE: Ceci fait partie de mes expériences avec l'IA (couture assistée) + mon propre montage.

Même voix, même pragmatisme, juste des doigts plus rapides.

### C'est là que nous faisons enfin travailler la partie "AI" de "AI assistant d'écriture".

Nous allons exécuter de grands modèles de langue localement sur votre A4000 GPU, générant des suggestions contextuelles basées sur vos messages de blog passés.
|--------|-----------|-------------------|
| **Pourquoi le LLM local ?** | ✅ Complete | ❌ Data sent to third party |
| **Avant de plonger, comprenons pourquoi nous utilisons des modèles localement au lieu d'utiliser l'API d'OpenAI.** | ✅ Free after setup | ❌ Per-token pricing |
| **Comparaison locale par rapport à l'API** | ✅ <1 second | ⚠️ Network dependent |
| **L'API locale LLM (OpenAI, etc.)** | ✅ Full control | ❌ Limited |
| **Vie privée** | ✅ Any GGUF model | ❌ Provider's models only |
| **Coût** | ✅ Works offline | ❌ Requires internet |
| **Latence** | ❌ Complex | ✅ Simple |

Personnalisation

## Choix du modèle

Hors ligne

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

**Configuration**

Pour un assistant à l'écriture, la vie privée et les coûts sont importants.

- Nous ne voulons pas d'ébauches de blog envoyées aux API externes, et le prix par jeton s'additionne rapidement pour un outil d'écriture quotidien.
- Options d'intégration LLM pour C#
- Il y a plusieurs façons d'exécuter les LLM en C#:
- Mon choix: LLamaSharp
- Pourquoi ?

## Reliures Native C# pour lama.cpp (bibliothèque d'inférence la plus rapide)

### Prend en charge le format GGUF (modèles modernes et quantifiés)

[Accélération CUDA intégrée](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md)Développement actif et grande communauté

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

**Travaille avec Llama, Mistral, Phi, Gemma, et plus encore**:

- Comprendre les formats des modèles et la quantisation
- Format GGUF
- GGUF
- (GPT-Generated Unified Format) est la norme pour l'exécution efficace des LLM.

### Quantification expliquée

Modèle original : flotteurs 32 bits (très gros, très précis)
|-------|---------------|------------|-----------|------------|------------|---------|
| **Q4 : 4 bits entiers (75% de plus petite taille, perte de qualité minimale)** | 2.3GB | ~4GB | ✅ Easy | ✅ Easy | ✅ Easy | ⭐⭐⭐ Good |
| **Q5/Q6: Spot doux pour la plupart des cas d'utilisation** | 4.1GB | ~6GB | ✅ Tight | ✅ Good | ✅ Easy | ⭐⭐⭐ Good |
| **Q8: Qualité presque originale, encore 4x plus petite** | 4.1GB | ~6GB | ✅ Tight | ✅ Good | ✅ Easy | ⭐⭐⭐⭐ Better |
| **Sélection du modèle par matériel** | 4.1GB | ~6GB | ✅ Tight | ✅ Good | ✅ Easy | ⭐⭐⭐⭐ Better |
| **Modèle Taille (Q4_K_M) Utilisation de VRAM Adapté à 8 Go? Adapté à 12 Go? Adapté à 16 Go? Adapté à la qualité** | 4.7GB | ~7GB | ⚠️ Very Tight | ✅ Good | ✅ Easy | ⭐⭐⭐⭐⭐ Best |
| **Mini Phi-3 (3.8B)** | 7.4GB | ~10GB | ❌ No | ⚠️ Tight | ✅ Good | ⭐⭐⭐⭐ Better |

**Lama 2 7B**

- **Mistral 7B**Gemma 7B**Lama 3 8B**Lama 2 13B**Recommandations du GPU :**8 Go VRAM
- **: Commencez par**: **Mistral 7B**ou**Phi-3 Mini**(plus sûr)
- **12 Go VRAM**: **Lama 3 8B**(meilleure qualité) ou**Mistral 7B**
- **(rapide)**16 Go VRAM (ma configuration)

**Lama 3 8B**: **[ou essayer](https://mistral.ai/)**Modèles 13B**[CPU seulement](https://ai.meta.com/llama/)**: N'importe quel modèle fonctionne, juste beaucoup plus lentement (démarrer avec Phi-3 Mini pour la vitesse)

- Ma recommandation
- Mistral 7B
- (dernière version) ou
- Lama 3

## 8B

Excellente qualité pour l'écriture technique

### Fonctionne sur toutes les tailles de GPU

1. Assez rapide pour une utilisation interactive[Bon à suivre les instructions](https://huggingface.co/models)
2. Téléchargement des modèles`"mistral 7b gguf"`
3. Les modèles sont distribués sur Hugging Face.

**Nous utiliserons des versions GGUF quantifiées.**Trouver des modèles GGUF

- [Allez-y.](https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF)
- [Visage bouillant](https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF)
- [Rechercher :](https://huggingface.co/QuantFactory/Meta-Llama-3-8B-Instruct-GGUF)

### Recherchez les quantifications de TheBloke (le plus populaire)

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

Liens directs

1. (quantisations de TheBloke):
2. Mistral-7B-Instruct-v0.2-GGUF`mistral-7b-instruct-v0.2.Q5_K_M.gguf`Lama-2-7B-Chat-GGUF
3. Lama-3-8B-Instruction-GGUF
4. Télécharger Quantification spécifique`C:\models\mistral-7b\`

## Ou télécharger manuellement :

### Cliquez sur l'onglet "Files et versions"

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

**Rechercher**

- `[LLamaSharp](https://github.com/SciSharp/LLamaSharp)`(~4.8 Go)
- `LLamaSharp.Backend.Cuda12` - [Cliquez sur télécharger](https://developer.nvidia.com/cuda-toolkit)Enregistrer dans

### Configuration LLamaSharp

Installer le paquet NuGet

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

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

Pourquoi deux paquets ?`false`- Bibliothèque de base

1. CUDA
2. `LLamaSharp.Backend.Cuda12`12 binaires pour accélération GPU
3. Vérifier le moteur CUDA

## LLamaSharp détectera automatiquement CUDA s'il est installé correctement.

### Si

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

**, vérifier:**:

- **CUDA 12.x installé (partie 2)**paquet installé
  
  - PATH inclut le répertoire CUDA bin
  - Construction du service LLM

- **Paramètres du modèle**Explications des paramètres
  
  - ContexteTaille
  - : Combien de texte le modèle peut "voir" à la fois
  - 4096 jetons 3 000 mots

- **Plus grand = plus de contexte mais plus lent et plus VRAM**GpuLayerCount
  
  - : Combien de couches de transformateur fonctionnent sur GPU
  - Les modèles 7B ont ~32 couches
  - 35 = mettre tout sur GPU (le plus rapide)

- **Valeurs inférieures = utiliser moins de VRAM mais plus lentement**Température
  
  - : Contrôle du hasard
  - 0,0 = toujours choisir le jeton le plus probable (brouillage, répétitif)

### 0,7 = bon équilibre (notre défaut)

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

**1.0+ = très créatif (peut être non sensoriel)**:

1. **Haut de la page**: Échantillonnage de noyaux
2. **0,9 = considérer des jetons qui constituent 90 % de la masse de probabilité**Empêche l'échantillonnage à partir de jetons très improbables
3. **Mise en œuvre du service LLM**Comment ça marche
4. **Chargement du modèle**: Charge le modèle GGUF dans VRAM en utilisant des paramètres spécifiés
5. **Exécuteur interactif**: Mode d'exécution de LLamaSharp pour les interactions de type chat

### InferAsync

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

**: Jetons de flux tels qu'ils sont générés (sortie en temps réel)**:

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

Mise en place du contexte

## : Combine l'invite utilisateur avec des morceaux de blog récupérés

Anti-promptes

### : Stoppe la génération à certaines cordes (prévente le dérapage)

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

### Tester le service

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

## Produit escompté

### Incroyable !

Le modèle fonctionne et génère un texte cohérent, conscient du contexte.

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

### Intégration avec le Groupe des suggestions

Maintenant, intégrons la génération LLM dans notre client Windows à partir de la partie 5.

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

Mettre à jour le service Suggestions

### Mettre à jour SuggestionsVoirModèle

Optimisation des performances

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

## Modèle de cache

Maintenez le modèle chargé entre les demandes :

### Réutilisation de KV Cache

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

### LLamaSharp prend en charge la réutilisation du cache KV pour les générations suivantes plus rapides:

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

### Ceci est particulièrement utile pour notre cas d'utilisation - les morceaux de contexte restent les mêmes, seule la question de l'utilisateur change.

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

## Abattement

Pour de multiples suggestions, faites-les par lots :

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

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

### Bonnes invites = bonne sortie.

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

## Voici des modèles pour différents scénarios:

Continuer d'écrire

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

## Proposer une structure de section

Exemple de code

1. ✅ Chose [Gestion de la mémoire](https://github.com/SciSharp/LLamaSharp)Avec de grands modèles, la gestion de la mémoire est cruciale.
2. ✅ Understood [Surveiller l'utilisation de VRAM](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md)Décharger le modèle en cas d'inactivité
3. ✅ Selected appropriate model ([Gestion des erreurs](https://mistral.ai/) / [Les LLM peuvent échouer de manière inattendue.](https://ai.meta.com/llama/)Gérez gracieusement :
4. ✅ Implemented LlmService with CUDA acceleration
5. ✅ Integrated with Windows client for suggestions
6. ✅ Implemented prompt engineering for writing tasks
7. ✅ Added performance optimizations (caching, batching)
8. ✅ Handled memory management and errors

## Résumé

Nous avons intégré avec succès l'inférence locale LLM :**[LLamaSharp](/blog/building-a-lawyer-gpt-for-your-blog-part7)**pour l'intégration C#

- Format GGUF
- et quantification
- Mistral 7B
- Lama 3
- 8B)
- Qu'est-ce qu'il y a ?
- Dans

Partie 7: Génération de contenu et génie rapide

## , nous allons nous concentrer sur le pipeline de génération de contenu complet:

- [Techniques avancées d'ingénierie rapide](/blog/building-a-lawyer-gpt-for-your-blog-part1)
- [Conversation multi-tours pour le raffinement itératif](/blog/building-a-lawyer-gpt-for-your-blog-part2)
- [Stratégies de gestion des fenêtres contextuelles](/blog/building-a-lawyer-gpt-for-your-blog-part3)
- [Évaluation et filtrage de la qualité](/blog/building-a-lawyer-gpt-for-your-blog-part4)
- [Application de la cohérence du style](/blog/building-a-lawyer-gpt-for-your-blog-part5)
- **Génération de blocs de code de manipulation**Modèles d'utilisation du monde réel
- [Nous allons rendre le système vraiment utile pour l'écriture quotidienne de blog!](/blog/building-a-lawyer-gpt-for-your-blog-part7)
- [Navigation des séries](/blog/building-a-lawyer-gpt-for-your-blog-part8)

## Première partie: Introduction et architecture

- [Partie 2: Configuration GPU & CUDA en C#](https://scisharp.github.io/LLamaSharp/)
- [Partie 3: Compréhension des intégrations et des bases de données vectorielles](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md)
- [Partie 4: Construction du pipeline d'ingestion](https://huggingface.co/TheBloke)
- [Partie 5: Le client Windows](https://github.com/ggerganov/llama.cpp)

Partie 6: Intégration locale des LLM[(ce poste)](/blog/building-a-lawyer-gpt-for-your-blog-part7)!