# Établissement d’un "Lawyer GPT" pour votre blog - Partie 9: Ingestion de documents avec Docling

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

Bienvenue à la Partie 9! Dans les parties précédentes, nous avons construit un système RAG robuste qui permet de traiter les articles sur le blog et de les rendre consultables grâce aux embeddings sémantiques. **Méthode de travail** - une puissante bibliothèque de traitement des documents qui peut incorporer les PDFs , DOCX, et d’autres formats

> 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

Ce n’est pas que j’ai besoin de ce pour le blog (it 's all markdown), mais pour terminer, j’avais pensé qu’il m’appartiendrait de montrer comment ajouter facilement les capacités d’ingestion des documents à votre pipeline RAG.

[TOC]

## Pourquoi l'ingestion de documents est importante

Jusqu’à présent, notre avocat GPT ne peut comprendre que les fichiers de démarrage. Celle-ci' est bon pour un blogM SK2 mais une base de connaissances réelle -contiennent des bases de données mondiales

- **Contrats PDF** - la vitalité du travail juridique
- **Documents Word** - mémoiresM SK1 motions , correspondance
- **Présentations PowerPoint** - pitches des clients, résumés de cas
- **Documents scannés** - dossiers plus anciens qui ont besoin d’un OCR
- **Pages HTML** - contenu Web, ressources en ligne

Si nous voulons que notre système fonctionne comme un véritable assistant juridique de l’AI, il doit consommer tous ces éléments.

## Qu'est-ce que Docling?

[Méthode de travail](https://github.com/docling-project/docling) est une trousse d’outils de traitement des documents à source ouverte de IBM.

Pourquoi le marquage?? Parce qu’il s’agit là de ce que notre pipeline existant comprend déjà.

**Ce que Docling gère:**

- Extraction PDF (both native and scanned via OCR)
- DOCX et fichiers DOC
- Présentations PPTX
- Pages HTML
- Images avec texte (via OCR)

**Qu’est-ce qui le rend spécial:**

- Préserve la structure du document (entêtes ,listesM SK2tableaux)
- Appuyer les layouts complexes (multiM SK1column,mixed contentMSC3
- L'extraction de tableaux fonctionne effectivement (comparativement à plusieurs parsateurs PDF)
- Fonctionne localement - aucune donnée envoyée aux services externes

## Exécution de la documentation en tant que service

La documentation elle-même est une bibliothèque Python, mais l'équipe fournit [Services de doctrine](https://github.com/docling-project/docling-serve) - un wrapper REST API que nous pouvons appeler à partir de CM SK1 Ce chemin d’intégration est le plus propre.

### Démarrage du service

La façon la plus facile de faire Docling est par Docker:

```bash
docker run -p 5001:5001 quay.io/docling-project/docling-serve
```

Que's it. Vous avez maintenant une API de conversion des documents qui fonctionne à `http://localhost:5001`.

Vous voulez y jouer interactivement? Activer l'interface :

```bash
docker run -p 5001:5001 -e DOCLING_SERVE_ENABLE_UI=1 quay.io/docling-project/docling-serve
```

Ensuite visitez `http://localhost:5001/ui` pour arracher les documents-etM SK1 et voir les résultats.

### Choix de l'image droite

Docling offre plusieurs images de conteneurs selon votre matériel:

| Image | Case d'utilisation MSC2 Taille MSC3
|-------|----------|------|
| `docling-serve` | Utilisation généraleM SK1 fonctionne partout | ~8.7GB S|
| `docling-serve-cpu` | Moins grosM SK1 CPU-seulement | MSC4GB MSC5
| `docling-serve-cu126` | GPU NVIDIA avec CUDA
| `docling-serve-cu128` | GPU NVIDIA avec CUDA

Si vous 'effectuez un travail lourd d’OCR (documents scannés), les images GPU sont dignes de la taille additionnelleM SK3 Pour le numériqueMSC4 documents PDF et Word natifsMNK5 le CPU est bonMRK6

### Ajout à Docker Compose

Pour la production, ajouter Docling à votre pile existante:

```yaml
services:
  docling:
    image: quay.io/docling-project/docling-serve:latest
    ports:
      - "5001:5001"
    volumes:
      - docling_cache:/root/.cache
    restart: unless-stopped
```

Le volume du cache est important - Docling télécharge les modèles ML au premier démarrage, et vous n’avez pas besoin de les renouveler 'de les télécharger chaque fois que le contenant se redémarre

## L'API de Docling

Avant de se plonger dans le code C# , laissez ' comprendre ce que nous travaillons avecM SK3 . Le service d’aiguillage expose un simple API REST

### Converter un document à partir d'une URL

```bash
curl -X POST 'http://localhost:5001/v1/convert/source' \
  -H 'Content-Type: application/json' \
  -d '{
    "sources": [{"kind": "http", "url": "https://example.com/contract.pdf"}],
    "options": {"to_formats": ["md"]}
  }'
```

### La mise à jour d'un fichier local

```bash
curl -X POST 'http://localhost:5001/v1/convert/file' \
  -F 'files=@contract.pdf'
```

Les deux retournent JSON contenant la valeur de marquage convertie, plus des métadonnées comme le nombre de pages et le type de fichier détecté.

### Options clés

- **`to_formats`**: Quel résultat vous voulez - `md` (markdownM SK1 `json` (structuredM SK1 ou `text` (plainM SK1
- **`ocr`**: ActiverM SK1 désactiver la lecture par ordinateur (défault: activéMSC4
- **`table_mode`**: `fast` ou `accurate` - vitesse de commerce pour la qualité des tables

## Intégration avec C#

Étant donné que Docling est un service REST, l’intégration est simple des appels HTTP . Là' c’est l’approcheM SK3

### 1. Créer un client de documentation

Nous avons besoin d’un service qui gère la communication HTTP:

```csharp
public class DoclingClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl;

    public DoclingClient(HttpClient httpClient, string baseUrl = "http://localhost:5001")
    {
        _httpClient = httpClient;
        _baseUrl = baseUrl;
    }

    public async Task<string?> ConvertFromUrlAsync(string documentUrl)
    {
        var request = new
        {
            sources = new[] { new { kind = "http", url = documentUrl } },
            options = new { to_formats = new[] { "md" } }
        };

        var response = await _httpClient.PostAsJsonAsync(
            $"{_baseUrl}/v1/convert/source", request);

        if (!response.IsSuccessStatusCode)
            return null;

        var result = await response.Content.ReadFromJsonAsync<DoclingResponse>();
        return result?.Document?.MarkdownContent;
    }

    public async Task<string?> ConvertFileAsync(string filePath)
    {
        using var content = new MultipartFormDataContent();
        using var fileStream = File.OpenRead(filePath);
        content.Add(new StreamContent(fileStream), "files", Path.GetFileName(filePath));

        var response = await _httpClient.PostAsync(
            $"{_baseUrl}/v1/convert/file", content);

        if (!response.IsSuccessStatusCode)
            return null;

        var result = await response.Content.ReadFromJsonAsync<DoclingResponse>();
        return result?.Document?.MarkdownContent;
    }
}
```

L’incertitude clé: nous recevons une réduction de marquage en retour , qui s’écoule directement dans notre pipeline existant.

### 2. Distribution dans le pipeline existant

Rappelez-vous de notre pipeline d'ingestion à partir de la partie 4? Il prend le marquage , en fragments

```csharp
public async Task ProcessDocumentAsync(string filePath)
{
    // Step 1: Convert to markdown with Docling
    var markdown = await _doclingClient.ConvertFileAsync(filePath);
    
    if (string.IsNullOrEmpty(markdown))
    {
        _logger.LogError("Failed to convert {File}", filePath);
        return;
    }

    // Step 2: Parse the markdown (reuse existing code!)
    var document = _markdownParser.ParseFromContent(markdown, Path.GetFileName(filePath));

    // Step 3: Chunk it (reuse existing code!)
    var chunks = _chunker.ChunkDocument(document);

    // Step 4: Generate embeddings (reuse existing code!)
    await _embedder.GenerateEmbeddingsAsync(chunks);

    // Step 5: Store in vector database (reuse existing code!)
    await _vectorStore.UpsertChunksAsync(chunks);
}
```

Voir combien peu de nouveau code nous avons besoin? La beauté de construire un pipeline autour du marquage est que tout nouveau format d’entrée n’a qu’un convertisseur - tout en aval demeure le mêmeM SK2

### 3. Gérer différents types de documents

Différents documents peuvent nécessiter un traitement différent:

```csharp
public async Task ProcessDocumentAsync(string filePath, string[] categories)
{
    var extension = Path.GetExtension(filePath).ToLower();
    
    // Scanned PDFs need OCR, which is slower
    var useOcr = extension == ".pdf" && await IsScannedPdfAsync(filePath);
    
    var markdown = await _doclingClient.ConvertFileAsync(filePath, new ConvertOptions
    {
        EnableOcr = useOcr,
        TableMode = extension == ".xlsx" ? "accurate" : "fast"
    });

    // ... rest of pipeline
}
```

## Considérations relatives au rendement

La conversion du document n’est pas't instantanéeM SK1 Là's ce à quoi on peut s’attendreMSC3

| Type de document
|--------------|--------------|
| PDF simple (1-5 pages
| PDF complexe MSC1 pagesMSc2 MSc3 | | 4 | secondes | 5 |
| PDF scanné à l'aide d'un format OCR | MSC2 secondes MSC3
| Document de texte | MSC2 secondes MSC3
| PowerPoint

**Conseils pour la production:**

1. **Processus asynchrone** - DonM SK1t bloc sur la conversion des documents. Documents en file d'attente et processus dans l'arrière-plan

2. **Résultats du cache** - Entreposer le marquage converti. Si un document n’a pas changéM SK2t  vérifier le fichier hashMST4 ne pas changerM ST5 ne reconvertirM st6

3. **Utiliser GPU pour l'OCR** - Si vous processez beaucoup de documents scannés, les images du CUDA sont :

4. **Passer à l'OCR lorsque possible** - DigitaleM SK1les PDF natifs ne sont pas requises 'ne nécessitent pas le format OCR. auto-doclageMNK4détecteMMK5 mais vous pouvez l’exclure pour les sources numériques connuesMRK6

## Surveillance automatique des documents

Pour une expérience à la main-off, regardez un dossier pour de nouveaux documentsM SK2

```csharp
public class DocumentWatcher : BackgroundService
{
    private FileSystemWatcher _watcher;

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _watcher = new FileSystemWatcher("/documents/incoming")
        {
            Filters = { "*.pdf", "*.docx", "*.pptx" }
        };

        _watcher.Created += async (s, e) => 
        {
            await Task.Delay(1000); // Wait for file to finish writing
            await _ingestionService.ProcessDocumentAsync(e.FullPath);
        };

        _watcher.EnableRaisingEvents = true;
        return Task.CompletedTask;
    }
}
```

Mettre un PDF dans le dossier, et il est automatiquement converti, chunkedM SK2 embedded , et rendu recherchableMSC4

## Ce qui en fait possible

Avec Docling intégré, notre avocat GPT peut maintenant:

- **Instaurer des contrats avec les clients** - Télécharger un PDF, poser des questions au sujet de clauses spécifiques
- **Rechercher à travers les mémoires** - Trouver l’argument que vous avez fait dans un cas similaire
- **Documents de recherche** - Ajouter des PDF universitaires à votre base de connaissance
- **Traiter les documents héréditaires** - OCR les anciens dossiers scannés

Le principal point de vue est que le format du document n’est qu’un problème d’entrée.

## Résumé

Nous avons ajouté l’ingestion de documents à notre avocat GPT:

1. **Méthode de travail** Convert PDFs, DOCX, PPTX à nettoyer le marquage
2. **Services de doctrine** en un API REST que nous pouvons appeler à partir de C#
3. **Notre pipeline existante** gère tout de là - aucun changement n'est nécessaire

C’est le pouvoir de bâtir autour d’un format commun.

## 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](/blog/building-a-lawyer-gpt-for-your-blog-part6)
- [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)
- **Partie 9: Ingestion de documents avec le doctage** (le présent articleM SK1

## Ressources

- [Docling GitHub](https://github.com/docling-project/docling)
- [Docling Serve GitHub](https://github.com/docling-project/docling-serve)
- [Document de travail (arXiv)](https://arxiv.org/abs/2501.17887)
- [Documentation API](http://localhost:5001/docs) ( lorsqu'il fonctionne localementM SK1