# Att bygga en "Lawyer GPT" för din blogg | - | Del |6: | Lokal LLM integration

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

## Inleiding

Välkomna till del 6! Vi ♫ ' ♫ har byggt den kompletta infrastrukturen ♫- ♫ inspegningsröret ♫[Del 4](/blog/building-a-lawyer-gpt-for-your-blog-part4)), Windowsclient  ([Del 5](/blog/building-a-lawyer-gpt-for-your-blog-part5)), Embeddinger och vektorsökningar ([Del 3](/blog/building-a-lawyer-gpt-for-your-blog-part3)), och GPU-uppsättning ([Del 2](/blog/building-a-lawyer-gpt-for-your-blog-part2)). Nu kommer det spännande med att integrera ett lokalt LLM för att faktiskt generera skrivande förslag

> NOTET: Det här är en del av mina experiment med AI ( assisterad redigering ) + mitt eget redigerande M SK4 Samma röst, , samma pragmatism,; bara snabbare fingrar

Det är här som vi slutligen gör "AI" del av ♫ "AI-skrivareassistenten ♫ МSK3 ♫ arbeten ♫. ♫ Vi ♫

[TOC]

## Varför lokal LLM?

Innan du dyker in i, ska vi förstå varför vi kör modeller lokalt istället för att använda OpenAI, ' och API.

### Lokal vs API jämförelse

| Aspect | Lokal LLM | API OpenAI, och så vidare
|--------|-----------|-------------------|
| **Privatliv** | ✅ Compleet | | | ❌ | Data skickad till en tredje part |
| **kostnaderna** | ✅ Gratis efter inställning ♫ ♫ | ♫
| **Tillfällighet** | ✅ ♫ ♫ <1 ♫ sekund ♫
| **Customisering** | ✅ Hela kontroll | ❌ Limited M|
| **Modellval** | ✅ Vilken GGUF-modell som helst
| **Offline** | ✅ Fungerar otillräckligt ♫ ♫ | ♫
| **Konfiguration** |

För en skriftassistent, privatliv och kostnadsproblem. Vi vill inte att blog-utskrifter skickas till externa API' sM SK3 och per - att tokenprissättningen ökar snabbt för ett dagligt skrivverktyg

## LLM integrationsoptioner för C#

Det finns flera sätt att köra LLMs i 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
```

**Mitt val: LLamaSharp**

Varför?

- Infödda C# bindningar för llama .cpp ( snabbaste uträkningsbiblioteketM SK3
- Ondersteuner GGUF-formatet (moderna , kvantiserade modeller)
- CUDA-acceleration byggt-in
- Aktiv utveckling och stor gemenskap
- Fungerar med Llama, Mistral, PhiM SK2 Gemma , och mer

## Understanding Model Formats & Quantisering

### GGUF Format

[GGUF](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md) (GPT

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

**Kvantisering förklarad**:

- Originalmodell: M SK1bitfloats (very large, very accurate
- Q4: 4-bit integer (75% mindreM SK3 minimalt kvalitetnedgångMSC4
- Q5/QM SK1 Sött ställe för de flesta användande fall
- Q8: näraM SK1 ursprunglig kvalitet , fortfarande 4x mindre

### Modellselektion genom hårdvara

| Modell | | | Storleken |( | Q | МSK3 | K | _ | ) || | VRAM tillämpning | | | Passar | s.k8 | S.k9 | | | Pastar | l.k11 | L.k12
|-------|---------------|------------|-----------|------------|------------|---------|
| **Phi-3 Mini (3.8BM SK2** | 2.3GB | | | ~4GB
| **Llama 2  7B** | 4.1GB | | | ~6GB
| **Mistral 7B** | 4.1GB | | | ~6GB
| **Gemma 7B** | 4.1GB | | | ~6GB
| **Llama 3  8B** | 4.7GB | | | ~7GB
| **Llama 2  13B** | 7.4GB | | | ~10GB

**Empfehlunger av GPU:**

- **8GB VRAM**: Börja med **Mistral 7B** eller **Phi-3 Mini** (safest
- **12GB VRAM**: **Llama 3  8B** ( bäst kvalitet ) eller **Mistral 7B** ( snabbare )
- **16GB VRAM**: **Llama 3  8B** eller försöka **13B-modeller**
- **CPU- endast**: Vilken modell som helst fungerarM SK1 bara mycket långsammare ( starta med Phi-3 Mini för hastigheten

**Min suositus**: **[Mistral 7B](https://mistral.ai/)** ( senaste versionen ) eller **[Llama 3](https://ai.meta.com/llama/)** 8B

- Utmärkt kvalitet för teknisk skrift
- Fungerar över alla GPU-storlekar
- Fast nog för interaktivt användande
- Bra på att följa instruktioner

## Att ladda ner modeller

Modeller är distribuerade på Hugging Face. Vi ' Vi använder kvantifierade versioner av GGUF

### Att hitta GGUF-modeller

1. Gå till [Haggrande ansikte](https://huggingface.co/models)
2. sökare: `"mistral 7b gguf"`
3. Leta efter TheBloke's kvantiseringar (mesta populäraM SK2

**Direkta länkar** (TheBloke

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

### ladda ner specifik kvantisering

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

Eller ladda ner manualt:

1. Titta på tab "Dater och versioner "
2. Hitta `mistral-7b-instruct-v0.2.Q5_K_M.gguf` (~4.8GB)
3. klicka för att ladda ned
4. spara till `C:\models\mistral-7b\`

## LLamaSharp uppsättning

### Installera NuGet-paket

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

**Varför två paket?**

- `[LLamaSharp](https://github.com/SciSharp/LLamaSharp)` - Kernbibliotek
- `LLamaSharp.Backend.Cuda12` - [CUDA](https://developer.nvidia.com/cuda-toolkit) 12 binärer för GPU-accelerationer

### Verifiera CUDA Backend

LLamaSharp kommer automatiskt att upptäcka CUDA om den är korrekt installerad.

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

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

Om `false`, kolla

1. CUDA 12.x installerad (Teil 2)
2. `LLamaSharp.Backend.Cuda12` paket installerat
3. PATH inkluderar CUDA bin katalog

## Att bygga LLM-tjänsterna

### Modellparameter

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

**Förklaringar till parametrer**:

- **Kontextstorlek**: Hur mycket text kan modellen se på samma gång
  
  - 4096 tokens ≈ 3000 ord
  - Större = mer sammanhang men långsammare och mer VRAM

- **GpuLayerCount**: Hur många transformeringslayer körs på GPU
  
  - 7B-modeller har ~32 lager
  - 35 ♫ = ♫ sätter allt på GPU ♫
  - lägre värden = använder mindre VRAM men långsammare

- **Temperatur**: Kontrollerar slumpmässighet
  
  - 0.0 = väljer alltid det mest troliga tecknet ♫ ♫ ( ♫ skrämmande ♫
  - 0.7 = bra balans ( vårt standard
  - 1.0+ = mycket kreativt

- **TopP**: Kolsämpling
  
  - 0.9 = tar hänsyn till tokens som utgör 90% av sannolikhetsmassa
  - Försämrar att ta prover från mycket osannolika tokens

### LLM Service Implementation

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

**Hur det fungerar**:

1. **Modelllagning**: Lader GGUF-modellen till VRAM med hjälp av specifikerade parametrar
2. **Interaktiv Executor**: LLamaSharp
3. **InferAsync**: Strängar token som de genereras, '
4. **Kontextbyggnad**: Kombinerar användarens prompt med hämtade bloggare chunks
5. **Anti-- prompter**: Stoppar generering vid vissa strängar ( förhindrar rambling

### Testning av tjänsten

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

**Oväntad utgång**:

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

Fantastiskt! Modellet fungerar och genererar en konsekvent, kontextM SK2 medveten textMSC3

## Integrering med förslagspanelen

Låt oss nu integrera LLM-generationen i vår Windows-client från

### uppdatera förslagstjänster

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

### Update SuggestionsViewModel

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

## Performanceoptimering

### Modell- Caching

Håll modellen laddad mellan begäran:

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

### KV Cache återanvändning

LLamaSharp supporterar KV-キャッシュ återanvändning för snabbare efterföljande generationer:

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

Detta är särskilt användbart för vårt användandefall. - kontexten stannar likadan, ♫ , ♫ bara användaren, | ' ♫ frågorna ändras ♫

### Batchning

För flera förslag

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

## Vinniga ingenjörskonst för att skriva hjälp

Bra instruktioner = bra utgång. Här är templater för olika scenarion

### Fortsätt skrivande

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

### Suggest sektioners struktur

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

### Ett exempel på kod

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

## Att sköta minnet

Med stora modeller är minneshantering avgörande

### Monitora användandet av VRAM

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

### Lade upp modellen när den är oaktiv

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

## Fehler i hantering

LLM kan misslyckas på oväntade sätt

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

## sammanfattning

Vi' har integrerat framgångsrikt den lokala LLM-förklaringen

1. ✅ Välj [LLamaSharp](https://github.com/SciSharp/LLamaSharp) för C# integrering
2. ✅ Understood [GGUF-format](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md) och kvantisering
3. ✅ Utvalda lämpligt model ([Mistral 7B](https://mistral.ai/) / [Llama 3](https://ai.meta.com/llama/) 8BM SK1
4. ✅ Implementerad LlmService med CUDA-acceleration
5. ✅ Integrerad med Windows-client för förslag
6. ✅ Rakensatt prompt ingenjörskonst för skrivande uppgifter
7. ✅ Hinsatta performance-optimeringar ♫ ( ♫ Caching ♫, ♫ Batchning ♫
8. ✅ Handled memory management and errors

## Vad's Nästa?

I **[Del 7: innehållsgenerering & Vinniga ingenjörskonst](/blog/building-a-lawyer-gpt-for-your-blog-part7)**, vi ' fokuserar på den kompletta innehållsproduktionskedjan

- Advanced prompt engineering techniques
- Multi-turn konversation för iterativ raffinering
- Kontextfenster-Managementstrategier
- Kvaliteets utvärdering och filtrering
- Stilkonsistens-övervakning
- Handlpande kodblock generering
- Verkliga usagesmönster i världen

Vi' gör systemet faktiskt användbart för dagliga bloggar

## Seri Navigation

- [Del 1: Inleiding & Arkitektur](/blog/building-a-lawyer-gpt-for-your-blog-part1)
- [Del 2: GPU Setup & CUDA i C#](/blog/building-a-lawyer-gpt-for-your-blog-part2)
- [Del 3: Understanding Embeddings | & | Vektordatabaser](/blog/building-a-lawyer-gpt-for-your-blog-part3)
- [Del 4: Byggnaden av införingsledning](/blog/building-a-lawyer-gpt-for-your-blog-part4)
- [Del 5: Windows Client](/blog/building-a-lawyer-gpt-for-your-blog-part5)
- **Del 6: Lokal LLM integration** (this postM SK1
- [Del 7: innehållsgenerering & Vinniga ingenjörskonst](/blog/building-a-lawyer-gpt-for-your-blog-part7)
- [Del 8: Utvecklade egenskaper & Tillverkning av produktion](/blog/building-a-lawyer-gpt-for-your-blog-part8)

## resurser

- [LLamaSharp Dokumentation](https://scisharp.github.io/LLamaSharp/)
- [GGUF Format Spesifikation](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md)
- [Modellkollektionen för TheBloke'](https://huggingface.co/TheBloke)
- [llama.cpp GitHub](https://github.com/ggerganov/llama.cpp)

Se er i [Del 7](/blog/building-a-lawyer-gpt-for-your-blog-part7)!