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

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

AI AI-Article C# Docling LLM mostlylucid.blogllm RAG

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

Monday, 15 December 2025

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.

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

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 :

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:

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

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

curl -X POST 'http://localhost:5001/v1/convert/file' \
  -F '[email protected]'

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:

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

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:

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

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.

Ressources

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.