# AI-Powered Alt Text Generation med mestadels lucid.llmlltText

Vill du få fin, beskrivande alt text för bilder på dina webbplatser eller jsut extrahera text från dem? `mostlylucid.llmalttext` använder Microsofts Florence-2 vision språkmodell för att generera högkvalitativa alt text automatiskt - körs helt lokalt på din maskin, inga API-nycklar krävs.

> Observera: Jag måste uppdatera detta dokument nu [nuget- paket ](https://www.nuget.org/packages/Mostlylucid.LlmAltText)- Om du tittar... [här](https://github.com/scottgal/mostlylucid.nugetpackages/tree/main/Mostlylucid.AltText.Demo) du kommer att fina en nifty demo webbplats som du kan ladda ner och använda. Jag kommer att uppdatera detta med detaljer under de kommande dagarna.

<datetime class="hidden">2025-11-24T10:00</datetime>

<!-- category -- ASP.NET, Accessibility, AI, NuGet, Florence-2, Image Processing -->
[![Hämta](https://img.shields.io/nuget/v/mostlylucid.llmaltText.svg)](https://www.nuget.org/packages/mostlylucid.llmalttext) [![Licens: Olicensierad](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)

# Inledning

Alt text spelar roll. Skärmläsare beror på det, SEO ranking faktor det i, och det är helt enkelt rätt sak att göra för tillgänglighet. Men att skriva bra alt text för hundratals bilder? Det är där de flesta av oss misslyckas.

Detta paket löser det problemet med att använda Microsofts Florence-2 vision språkmodell - kör helt lokalt på din maskin, inga API-nycklar krävs.

**Källkod:** [github.com/scottgal/mestlylucid.nugetpaket](https://github.com/scottgal/mostlylucid.nugetpackages/tree/main/Mostlylucid.LlmAltText)

[TOC]

# Problemet

Var och en `<img>` Tagg bör ha meningsfull alt text. Men i praktiken:

- **Manuellt skrivande är långtråkigt** - hundratals bilder betyder arbetstid
- **AI API:er kostar pengar** - OpenAI Vision, Claude, etc. summera snabbt
- **Betänkligheter i fråga om privatlivet** - du kanske inte vill skicka bilder till externa API:er
- **Inkonsekvent kvalitet** - olika människor skriver alt text annorlunda

Tänk om du kan generera högkvalitativ alt-text automatiskt, körs helt på din egen hårdvara?

# Hur den fungerar

Paketet använder Microsofts Florence-2-modell via ONNX runtime. Här är processledningen:

```mermaid
flowchart TB
    subgraph Input[Image Sources]
        A[File Path]
        B[URL]
        C[Stream]
        D[Byte Array]
    end

    subgraph Processing[Florence-2 Pipeline]
        E[Image Preprocessing]
        F[Vision Encoder]
        G[Language Decoder]
    end

    subgraph Output[Results]
        H[Alt Text]
        I[OCR Text]
        J[Content Type]
    end

    A --> E
    B --> E
    C --> E
    D --> E
    E --> F
    F --> G
    G --> H
    G --> I
    G --> J

    style A stroke:#10b981,stroke-width:2px
    style B stroke:#10b981,stroke-width:2px
    style C stroke:#10b981,stroke-width:2px
    style D stroke:#10b981,stroke-width:2px
    style F stroke:#6366f1,stroke-width:2px
    style G stroke:#6366f1,stroke-width:2px
    style H stroke:#ec4899,stroke-width:2px
    style I stroke:#ec4899,stroke-width:2px
    style J stroke:#ec4899,stroke-width:2px
```

**Huvuddrag:**

- **Lokalt genomförande** - inga API-samtal, inga kostnader, inga sekretessproblem
- **En modell på 800 MB** - nedladdningar en gång, cached för alltid
- **Flera aktivitetstyper** - korta bildtexter, detaljerade beskrivningar, OCR
- **Innehållsklassificering** - Vet om det är ett foto, diagram, skärmdump, etc.

# Snabbstart

## Anläggning

```bash
dotnet add package Mostlylucid.LlmAltText
```

## Registertjänster

```csharp
// Program.cs
builder.Services.AddAltTextGeneration();
```

Den första körningen laddar ner Florence-2 modellen (~800MB), då är du redo att gå.

## Skapa Alt- text

```csharp
public class ImageController : ControllerBase
{
    private readonly IImageAnalysisService _imageAnalysis;

    public ImageController(IImageAnalysisService imageAnalysis)
    {
        _imageAnalysis = imageAnalysis;
    }

    [HttpPost("analyze")]
    public async Task<IActionResult> Analyze(IFormFile image)
    {
        using var stream = image.OpenReadStream();
        var altText = await _imageAnalysis.GenerateAltTextAsync(stream);

        return Ok(new { altText });
    }
}
```

# Flera inmatningskällor

Tjänsten accepterar bilder från var som helst - filer, webbadresser, strömmar, eller byte arrayer.

## Från filsökväg

```csharp
var altText = await _imageAnalysis.GenerateAltTextFromFileAsync("/images/photo.jpg");
```

## Från webbadress

```csharp
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(
    "https://example.com/image.png");
```

## Från Stream

```csharp
using var stream = file.OpenReadStream();
var altText = await _imageAnalysis.GenerateAltTextAsync(stream);
```

## Från Byte Array

```csharp
var bytes = await httpClient.GetByteArrayAsync(imageUrl);
var altText = await _imageAnalysis.GenerateAltTextAsync(bytes);
```

# Uppgiftstyper: Styrning av detaljnivå

Florence-2 stöder tre bildtextlägen. Välj baserat på dina behov:

```csharp
// Brief - "A dog sitting on grass"
var brief = await _imageAnalysis.GenerateAltTextAsync(stream, "CAPTION");

// Detailed - "A golden retriever sitting on green grass in a park"
stream.Position = 0;
var detailed = await _imageAnalysis.GenerateAltTextAsync(stream, "DETAILED_CAPTION");

// Most detailed (default) - Full accessibility description
stream.Position = 0;
var full = await _imageAnalysis.GenerateAltTextAsync(stream, "MORE_DETAILED_CAPTION");
// "A happy golden retriever with light fur sitting on lush green grass
//  in a sunny park, with trees visible in the background."
```

**När ska du använda var och en av dessa:**

på aktivitetstyp  på bästa sätt för  på
|-----------|----------|
| `CAPTION` på tumnaglar, dekorativa bilder, snabba verktygstips
| `DETAILED_CAPTION` Sociala medier, grundläggande tillgänglighet
| `MORE_DETAILED_CAPTION` på full tillgänglighet, skärmläsare (rekommenderas)

# OCR- textutdrag

Florence-2 kan också extrahera text från bilder - användbart för skärmdumpar, dokument och diagram.

```csharp
// Extract text only
var extractedText = await _imageAnalysis.ExtractTextAsync(stream);

// Get both alt text and extracted text
var (altText, ocrText) = await _imageAnalysis.AnalyzeImageAsync(stream);

Console.WriteLine($"Alt: {altText}");
Console.WriteLine($"OCR: {ocrText}");
```

# Klassificering av innehållstyp

Inte alla bilder är desamma. Ett fotografi behöver beskrivande alt text; ett dokument behöver sitt textinnehåll. Klassificeringsfunktionen hjälper dig att hantera var och en på lämpligt sätt:

```csharp
var result = await _imageAnalysis.AnalyzeWithClassificationAsync(stream);

Console.WriteLine($"Type: {result.ContentType}");        // e.g., "Photograph"
Console.WriteLine($"Confidence: {result.ContentTypeConfidence:P0}"); // e.g., "87%"
Console.WriteLine($"Has Text: {result.HasSignificantText}");
```

## Hantering av olika innehållstyper

```csharp
var result = await _imageAnalysis.AnalyzeWithClassificationAsync(stream);

switch (result.ContentType)
{
    case ImageContentType.Document:
        // Documents - prioritize extracted text
        return result.ExtractedText;

    case ImageContentType.Screenshot:
        // Screenshots - combine description with UI text
        return result.HasSignificantText
            ? $"{result.AltText}. Text visible: {result.ExtractedText}"
            : result.AltText;

    case ImageContentType.Chart:
        // Charts - describe the visualization plus data
        return $"{result.AltText}. Data: {result.ExtractedText}";

    case ImageContentType.Photograph:
    default:
        // Photos - just the description
        return result.AltText;
}
```

## Hänvisning till innehållstyp

på grund av att det inte finns några tecken på att det inte finns några tecken på att det finns några tecken som tyder på att det inte finns några tecken på att det finns några tecken som tyder på att det inte finns några tecken på att det finns några tecken på att det finns några tecken på att det finns tecken på att det finns tecken på att det finns tecken på att det finns en risk för att det finns en risk för att det finns en risk för att det finns en risk för att det finns en risk för att det finns en risk för att det finns en risk för att det finns en risk för att det finns en risk för att det uppstår en allvarlig störning.
|------|-------------|---------|
| `Photograph` Människor, landskap, produkter
| `Document` Texttungt innehåll  på PDF-filer, formulär, artiklar
| `Screenshot` till Programvaran fångar  på UI, webbplatser, appar
| `Chart` på datavisualiseringar  på grafer, pie diagram, tabeller
| `Illustration` till Ritat innehåll  på Konstverk, tecknade serier, ikoner
| `Diagram` Teknologiskisser  med flödesdiagram, UML, scheman
| `Unknown` Oklassificerade kantfall

# Tagghjälparen för automatisk Alt- text

Här blir det intressant. TagHelper genererar automatiskt alt text för alla `<img>` Tagg saknas en - i rendering tid.

## Ställ in

```csharp
// Program.cs
builder.Services.AddAltTextGeneration(options =>
{
    options.EnableTagHelper = true;
    options.EnableDatabase = true;  // Cache results
    options.DbProvider = AltTextDbProvider.Sqlite;
    options.SqliteDbPath = "./alttext.db";
});

var app = builder.Build();
await app.Services.MigrateAltTextDatabaseAsync();
```

Registrera tagghjälparen i `_ViewImports.cshtml`:

```cshtml
@addTagHelper *, Mostlylucid.LlmAltText
```

## Hur den fungerar

```mermaid
flowchart LR
    subgraph Razor[Razor View Rendering]
        A[img tag found]
        B{Has alt attribute?}
        C[Skip - use existing]
        D{In cache?}
        E[Return cached]
        F[Fetch image]
        G[Generate alt text]
        H[Cache result]
        I[Render with alt]
    end

    A --> B
    B -->|Yes| C
    B -->|No| D
    D -->|Yes| E
    D -->|No| F
    F --> G
    G --> H
    H --> I
    E --> I

    style A stroke:#10b981,stroke-width:2px
    style B stroke:#6366f1,stroke-width:2px
    style G stroke:#ec4899,stroke-width:2px
    style I stroke:#8b5cf6,stroke-width:2px
```

## Vad som blir bearbetat

```html
<!-- NO ALT - Will be processed -->
<img src="https://example.com/photo.jpg" />

<!-- HAS ALT - Skipped (respects your text) -->
<img src="https://example.com/photo.jpg" alt="My custom description" />

<!-- EMPTY ALT - Skipped (decorative image per a11y standards) -->
<img src="https://example.com/decorative.jpg" alt="" />

<!-- EXPLICIT SKIP - Skipped -->
<img src="https://example.com/photo.jpg" data-skip-alt="true" />

<!-- DATA URI - Skipped (can't fetch) -->
<img src="data:image/png;base64,..." />

<!-- RELATIVE PATH - Skipped (needs absolute URL) -->
<img src="/images/photo.jpg" />
```

## Områdesbegränsningar

För säkerhet kan du begränsa vilka domäner TagHelper hämtar från:

```csharp
options.AllowedImageDomains = new List<string>
{
    "mycdn.example.com",
    "images.mysite.org",
    "cdn.githubusercontent.com"
};
```

# Databascachelagring

Utan caching, varje sida rendering skulle regenerera alt text. Det är långsamt och slösaktigt. Databasen cache lagrar resultat som nyckel i bild URL.

## SQLite (Utveckling)

```csharp
builder.Services.AddAltTextGeneration(options =>
{
    options.EnableDatabase = true;
    options.DbProvider = AltTextDbProvider.Sqlite;
    options.SqliteDbPath = "./alttext.db";
    options.CacheDurationMinutes = 60;
});
```

## PostgreSQL (Produktion)

```csharp
builder.Services.AddAltTextGeneration(options =>
{
    options.EnableDatabase = true;
    options.DbProvider = AltTextDbProvider.PostgreSql;
    options.ConnectionString = Configuration.GetConnectionString("AltTextDb");
});
```

# Inställningsreferens

```csharp
builder.Services.AddAltTextGeneration(options =>
{
    // Model location (~800MB downloaded here)
    options.ModelPath = "./models";

    // Default task type for alt text generation
    options.DefaultTaskType = "MORE_DETAILED_CAPTION";

    // Maximum word count for alt text
    options.MaxWords = 90;

    // Enable detailed logging
    options.EnableDiagnosticLogging = true;

    // TagHelper settings
    options.EnableTagHelper = true;
    options.EnableDatabase = true;
    options.AutoMigrateDatabase = true;

    // Database provider
    options.DbProvider = AltTextDbProvider.Sqlite;
    options.SqliteDbPath = "alttext.db";
    // or
    options.DbProvider = AltTextDbProvider.PostgreSql;
    options.ConnectionString = "Host=localhost;Database=alttext;...";

    // Security
    options.AllowedImageDomains = new List<string> { "cdn.example.com" };
    options.SkipSrcPrefixes = new List<string> { "data:", "blob:" };

    // Caching
    options.CacheDurationMinutes = 60;
});
```

# Real-World Exempel: Batch Processing

Så här använder jag den för att behandla bilder när jag importerar blogginlägg:

```csharp
public class ImageProcessor
{
    private readonly IImageAnalysisService _imageAnalysis;
    private readonly ILogger<ImageProcessor> _logger;

    public ImageProcessor(
        IImageAnalysisService imageAnalysis,
        ILogger<ImageProcessor> logger)
    {
        _imageAnalysis = imageAnalysis;
        _logger = logger;
    }

    public async Task ProcessMarkdownImagesAsync(string markdownPath)
    {
        var imageDir = Path.Combine(Path.GetDirectoryName(markdownPath)!, "images");
        if (!Directory.Exists(imageDir)) return;

        var images = Directory.GetFiles(imageDir, "*.*")
            .Where(f => IsImageFile(f));

        foreach (var imagePath in images)
        {
            try
            {
                var result = await _imageAnalysis
                    .AnalyzeWithClassificationFromFileAsync(imagePath);

                _logger.LogInformation(
                    "Processed {File}: {Type} ({Confidence:P0})",
                    Path.GetFileName(imagePath),
                    result.ContentType,
                    result.ContentTypeConfidence);

                // Store alt text for later use
                await SaveAltTextAsync(imagePath, result.AltText);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to process {File}", imagePath);
            }
        }
    }

    private static bool IsImageFile(string path)
    {
        var ext = Path.GetExtension(path).ToLowerInvariant();
        return ext is ".jpg" or ".jpeg" or ".png" or ".gif" or ".webp" or ".bmp";
    }
}
```

# Prestandaöverväganden

## Vad man kan förvänta sig

"Metriskt värde" Typiskt värde
|--------|--------------|
Första körningen Långsammare (~800MB-modell nedladdning)
på modellbelastning 1-3 sekunder
Bearbetning per bild  på 500–2000 ms
på minnesanvändning 2GB+ rekommenderas
på Diskutrymme  på ~800MB för modeller

## Tips för produktion

```csharp
// 1. Register as Singleton (model load is expensive)
builder.Services.AddAltTextGeneration(); // Already singleton internally

// 2. Check readiness before processing
if (!_imageAnalysis.IsReady)
{
    return StatusCode(503, "AI model still initializing");
}

// 3. Use cancellation tokens for timeouts
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var altText = await _imageAnalysis.GenerateAltTextFromUrlAsync(url, cts.Token);

// 4. Process in batches, not parallel (memory constraints)
foreach (var image in images)
{
    await ProcessImageAsync(image); // Sequential is safer
}
```

# Integrering av öppentelemetri

Paketet innehåller inbyggd spårning:

```csharp
builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.AddSource("Mostlylucid.LlmAltText");
    });
```

**Spårade aktiviteter:**

- `llmalttext.generate_alt_text`
- `llmalttext.extract_text`
- `llmalttext.analyze_image`
- `llmalttext.classify_content_type`

# Hälsokontroller

Lägg till en hälsokontroll för att övervaka modellstatus:

```csharp
public class AltTextHealthCheck : IHealthCheck
{
    private readonly IImageAnalysisService _service;

    public AltTextHealthCheck(IImageAnalysisService service)
        => _service = service;

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        return Task.FromResult(_service.IsReady
            ? HealthCheckResult.Healthy("Florence-2 model ready")
            : HealthCheckResult.Unhealthy("Model not initialized"));
    }
}

// Registration
builder.Services.AddHealthChecks()
    .AddCheck<AltTextHealthCheck>("alttext");
```

# Felsökning

## Modellnedladdning misslyckas

```
Error: Failed to download model files
```

**Lösningar:**

- Kontrollera internetanslutning
- Verifiera brandvägg tillåter Hugging Face nedladdningar
- Säkerställ ~800MB diskutrymme tillgängligt
- Kontrollera skrivbehörigheter på `ModelPath`

## Tjänsten är inte klar

```csharp
_imageAnalysis.IsReady // Returns false
```

**Lösningar:**

- Vänta på initiering av modellen (1-3 sekunder)
- Kontrollera loggar för initialiseringsfel
- Kontrollera tillräckligt minne (2GB+)

## Dålig kvalitet Alt text

**Lösningar:**

- Användning `MORE_DETAILED_CAPTION` (förval)
- Se till att indatabilder är tydliga
- Kontrollera att bilden inte är för liten eller suddig

## Tagghjälpare fungerar inte

**Lösningar:**

- Verifiera `EnableTagHelper = true`
- Kontrollera `@addTagHelper` i `_ViewImports.cshtml`
- Använd absoluta webbadresser (relativa sökvägar hoppar över)
- Kontrollera `AllowedImageDomains` inställning

# Tillgänglighet bästa praxis

Genererad alt text är en utgångspunkt. För bästa resultat:

1. **Översyn av resultaten** - AI är inte perfekt, verifiera exakthet
2. **Håll det koncist** - 90-100 ord max.
3. **Var beskrivande** - omfattar ämnen, åtgärder, sammanhang
4. **Undvik redundans** - Börja inte med "Bild av..."
5. **Överväg syftet** - alt text ska tjäna bildens roll på sidan
6. **Använd tom alt för dekorativa** - Färdiga. `alt=""` för enbart dekorativa bilder
7. **Inkludera synlig text** - om bilden innehåller text, inkludera den

# Slutsatser

`Mostlylucid.LlmAltText` ger AI-driven tillgänglighet till dina .NET-program utan kostnader eller integritet oro externa API:er. TagHelper gör det särskilt enkelt - bara aktivera det och din `<img>` taggar få automatisk alt text.

Paketet är Olicensierat (public domain), så gör vad du vill med det.

## Resurser

- **- Vad är det?** [Mestlylucid.LlmAltText](https://www.nuget.org/packages/Mostlylucid.LlmAltText)
- **Källa:** [github.com/scottgal/mestlylucid.nugetpaket](https://github.com/scottgal/mostlylucid.nugetpackages/tree/main/Mostlylucid.LlmAltText)
- **Frågor:** [GitHub-frågor](https://github.com/scottgal/mostlylucidweb/issues)
- **Florence-2:** [Microsofts vision språkmodell](https://huggingface.co/microsoft/Florence-2-base)