Back to "Χτίζοντας μια "δικηγόρος GPT" για το blog σας - Μέρος 9: Κατάποση Εγγράφων με Dockling"

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

Χτίζοντας μια "δικηγόρος GPT" για το blog σας - Μέρος 9: Κατάποση Εγγράφων με Dockling

Monday, 15 December 2025

Καλώς ήρθατε στο Μέρος 9! Σε προηγούμενα μέρη, έχουμε χτίσει ένα ισχυρό σύστημα RAG που επεξεργάζεται markdown blog posts και τα καθιστά διαθέσιμα μέσα από σημασιολογικές καταχωρήσεις. Τώρα ήρθε η ώρα να επεκτείνουμε τις δυνατότητές μας με Αποκωδικοποίηση - μια ισχυρή βιβλιοθήκη επεξεργασίας εγγράφων που μπορεί να καταπιεί PDF, DOCX, και άλλες μορφές, καθιστώντας μας Δικηγόρος GPT πραγματικά περιεκτική.

ΣΗΜΕΙΩΣΗ: Αυτό είναι μέρος των πειραμάτων μου με AI (βοηθητική σύνταξη) + δική μου επεξεργασία. Ίδια φωνή, ίδιος πραγματισμός? απλά γρηγορότερα δάχτυλα.

Όχι ότι το χρειάζομαι αυτό για το blog (είναι όλα Markdown), αλλά για την ολοκλήρωση σκέφτηκα να δείξω πώς να προσθέσω εύκολα δυνατότητες κατάποσης εγγράφων στον αγωγό σας RAG. Αυτό είναι ιδιαίτερα χρήσιμο αν φτιάχνετε ένα σύστημα που πρέπει να επεξεργαστεί νομικά έγγραφα, συμβόλαια, ή άλλα επιχειρηματικά έγγραφα.

Γιατί Θέματα Εισόδου Εγγράφων για Νομική AI

Οι σύγχρονες νομικές πρακτικές ασχολούνται με μια ποικιλία μορφών εγγράφων πέρα από το κείμενο.

  • Συμβάσεις PDF και νομικές συμφωνίες
  • Σλιπ DOCX και προτάσεις
  • Κλωστές ηλεκτρονικού ταχυδρομείου και αλληλογραφία
  • Κονσερβοποιημένα έγγραφα (μέσω OCR)
  • Υπολογιστικά φύλλα με δεδομένα περίπτωσης

Το Dockling επιτρέπει στο Δικηγόρο μας GPT να επεξεργαστεί αυτές τις μορφές και να τις κάνει αναζητήσιμες, δημιουργώντας μια πραγματικά περιεκτική βάση γνώσεων που καθρεφτίζει το πώς οι σύγχρονες δικηγορικές εταιρείες χρησιμοποιούν AI.

Τι είναι το Ντόκλινγκ;

Αποκωδικοποίηση είναι ένα εργαλείο επεξεργασίας εγγράφων ανοικτού κώδικα από την IBM που:

  • Μετατρέπει PDFs, DOCX, PPTX, HTML και άλλες μορφές σε δομημένη markdown ή JSON
  • Διατηρεί τη μορφοποίηση, πίνακες, και τη δομή του εγγράφου
  • Υποστηρίζει OCR για σαρωμένα έγγραφα
  • Λειτουργεί ως υπηρεσία Docker μέσω Σερβίρετε DocklingName
  • Εκθέτει ένα REST API για εύκολη ενσωμάτωση με οποιαδήποτε γλώσσα

Ρύθμιση σερβιρίσματος@ label: inlistbox

Docker Service Development

Docling Serve είναι ο ευκολότερος τρόπος για να εκτελέσετε Docling ως υπηρεσία.

# Using the official container image from Quay.io
docker run -p 5001:5001 quay.io/docling-project/docling-serve

# Or with the UI enabled for testing
docker run -p 5001:5001 -e DOCLING_SERVE_ENABLE_UI=1 quay.io/docling-project/docling-serve

Διαθέσιμες εικόνες εμπορευματοκιβωτίων:

Εικόνα > Περιγραφή Μέγεθος > |-------|-------------|------| | quay.io/docling-project/docling-serve Εικόνα βάσης (πακέτα PyPI) □ ~8.7GB (amd64) | quay.io/docling-project/docling-serve-cpu Μοναδική παραλλαγή CPU ~4.4GB ~ | quay.io/docling-project/docling-serve-cu126 CUDA 12.6 για GPU ~10GB ~ | quay.io/docling-project/docling-serve-cu128 CUDA 12.8 για GPU ~11.4GB ~

Τελικά σημεία:

  • API: http://localhost:5001
  • Τεκμηρίωση API (Swagger): http://localhost:5001/docs
  • Παιδική χαρά UI: http://localhost:5001/ui (όταν είναι ενεργοποιημένο)

Ρύθμιση συνδυασμού DockerName

Για την παραγωγή, προσθέστε Dockling στην υπάρχουσα σας docker-compose.yml:

services:
  docling:
    image: quay.io/docling-project/docling-serve:latest
    ports:
      - "5001:5001"
    environment:
      - DOCLING_SERVE_ENABLE_UI=0
      - DOCLING_SERVE_MAX_WORKERS=4
    volumes:
      - docling_cache:/root/.cache
    restart: unless-stopped
    
volumes:
  docling_cache:

Δοκιμή Dockling με μπούκλες

Πριν την ενσωμάτωση με το C#, ας δοκιμάσουμε το API:

# Convert a PDF from URL
curl -X 'POST' \
  'http://localhost:5001/v1/convert/source' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "sources": [{"kind": "http", "url": "https://arxiv.org/pdf/2501.17887"}],
    "options": {
      "to_formats": ["md"]
    }
  }'

# Convert a local file (upload)
curl -X 'POST' \
  'http://localhost:5001/v1/convert/file' \
  -H 'accept: application/json' \
  -F '[email protected]'

C# Ενσωμάτωση

Δεδομένου ότι το Docling είναι μια υπηρεσία Python, θα ενσωματώσουμε μέσω HTTP. Ας οικοδομήσουμε ένα ισχυρό πελάτη C#.

Μελέτη μοντέλων API

using System.Text.Json.Serialization;

namespace Mostlylucid.BlogLLM.Core.Models
{
    /// <summary>
    /// Request to convert documents from URLs or base64 content
    /// </summary>

    public class DoclingConvertRequest
    {
        [JsonPropertyName("sources")]
        public List<DoclingSource> Sources { get; set; } = new();

        [JsonPropertyName("options")]
        public DoclingOptions? Options { get; set; }
    }

    public class DoclingSource
    {
        [JsonPropertyName("kind")]
        public string Kind { get; set; } = "http"; // "http", "base64", "file"

        [JsonPropertyName("url")]
        public string? Url { get; set; }

        [JsonPropertyName("base64")]
        public string? Base64Content { get; set; }

        [JsonPropertyName("filename")]
        public string? Filename { get; set; }
    }

    public class DoclingOptions
    {
        [JsonPropertyName("to_formats")]
        public List<string> ToFormats { get; set; } = new() { "md" }; // "md", "json", "text"

        [JsonPropertyName("ocr")]
        public bool Ocr { get; set; } = true;

        [JsonPropertyName("table_mode")]
        public string TableMode { get; set; } = "accurate"; // "fast", "accurate"
    }

    /// <summary>
    /// Response from Docling conversion
    /// </summary>

    public class DoclingConvertResponse
    {
        [JsonPropertyName("document")]
        public DoclingDocument? Document { get; set; }

        [JsonPropertyName("status")]
        public string Status { get; set; } = string.Empty;

        [JsonPropertyName("errors")]
        public List<string>? Errors { get; set; }
    }

    public class DoclingDocument
    {
        [JsonPropertyName("md_content")]
        public string? MarkdownContent { get; set; }

        [JsonPropertyName("json_content")]
        public object? JsonContent { get; set; }

        [JsonPropertyName("text_content")]
        public string? TextContent { get; set; }

        [JsonPropertyName("metadata")]
        public DoclingMetadata? Metadata { get; set; }
    }

    public class DoclingMetadata
    {
        [JsonPropertyName("filename")]
        public string? Filename { get; set; }

        [JsonPropertyName("page_count")]
        public int? PageCount { get; set; }

        [JsonPropertyName("file_type")]
        public string? FileType { get; set; }
    }

    /// <summary>
    /// Our internal document model
    /// </summary>

    public class ProcessedDocument
    {
        public string DocumentId { get; set; } = Guid.NewGuid().ToString();
        public string FileName { get; set; } = string.Empty;
        public string OriginalFormat { get; set; } = string.Empty;
        public string MarkdownContent { get; set; } = string.Empty;
        public string? TextContent { get; set; }
        public DateTime ProcessedDate { get; set; } = DateTime.UtcNow;
        public string[] Categories { get; set; } = Array.Empty<string>();
        public int? PageCount { get; set; }
        public string ContentHash { get; set; } = string.Empty;
    }
}

Εξυπηρέτηση Πελάτη

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Mostlylucid.BlogLLM.Core.Models;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

namespace Mostlylucid.BlogLLM.Core.Services
{
    public class DoclingClientOptions
    {
        public string BaseUrl { get; set; } = "http://localhost:5001";
        public int TimeoutSeconds { get; set; } = 300; // 5 minutes for large documents
        public bool EnableOcr { get; set; } = true;
        public string TableMode { get; set; } = "accurate";
    }

    public class DoclingClient : IDisposable
    {
        private readonly HttpClient _httpClient;
        private readonly ILogger<DoclingClient> _logger;
        private readonly DoclingClientOptions _options;

        public DoclingClient(
            HttpClient httpClient,
            ILogger<DoclingClient> logger,
            IOptions<DoclingClientOptions> options)
        {
            _httpClient = httpClient;
            _logger = logger;
            _options = options.Value;

            _httpClient.BaseAddress = new Uri(_options.BaseUrl);
            _httpClient.Timeout = TimeSpan.FromSeconds(_options.TimeoutSeconds);
        }

        /// <summary>
        /// Convert a document from a URL
        /// </summary>

        public async Task<ProcessedDocument?> ConvertFromUrlAsync(
            string url,
            string[]? categories = null,
            CancellationToken cancellationToken = default)
        {
            _logger.LogInformation("Converting document from URL: {Url}", url);

            var request = new DoclingConvertRequest
            {
                Sources = new List<DoclingSource>
                {
                    new() { Kind = "http", Url = url }
                },
                Options = new DoclingOptions
                {
                    ToFormats = new List<string> { "md", "text" },
                    Ocr = _options.EnableOcr,
                    TableMode = _options.TableMode
                }
            };

            return await SendConversionRequestAsync(request, categories, cancellationToken);
        }

        /// <summary>
        /// Convert a local file
        /// </summary>

        public async Task<ProcessedDocument?> ConvertFileAsync(
            string filePath,
            string[]? categories = null,
            CancellationToken cancellationToken = default)
        {
            if (!File.Exists(filePath))
            {
                _logger.LogError("File not found: {FilePath}", filePath);
                return null;
            }

            _logger.LogInformation("Converting local file: {FilePath}", filePath);

            // Read file and convert to base64
            var fileBytes = await File.ReadAllBytesAsync(filePath, cancellationToken);
            var base64Content = Convert.ToBase64String(fileBytes);
            var fileName = Path.GetFileName(filePath);

            var request = new DoclingConvertRequest
            {
                Sources = new List<DoclingSource>
                {
                    new()
                    {
                        Kind = "base64",
                        Base64Content = base64Content,
                        Filename = fileName
                    }
                },
                Options = new DoclingOptions
                {
                    ToFormats = new List<string> { "md", "text" },
                    Ocr = _options.EnableOcr,
                    TableMode = _options.TableMode
                }
            };

            return await SendConversionRequestAsync(request, categories, cancellationToken);
        }

        /// <summary>
        /// Convert a file using multipart form upload (more efficient for large files)
        /// </summary>

        public async Task<ProcessedDocument?> ConvertFileUploadAsync(
            string filePath,
            string[]? categories = null,
            CancellationToken cancellationToken = default)
        {
            if (!File.Exists(filePath))
            {
                _logger.LogError("File not found: {FilePath}", filePath);
                return null;
            }

            _logger.LogInformation("Uploading and converting file: {FilePath}", filePath);

            try
            {
                using var fileStream = File.OpenRead(filePath);
                using var content = new MultipartFormDataContent();
                using var streamContent = new StreamContent(fileStream);

                var fileName = Path.GetFileName(filePath);
                content.Add(streamContent, "files", fileName);

                var response = await _httpClient.PostAsync(
                    "/v1/convert/file",
                    content,
                    cancellationToken);

                if (!response.IsSuccessStatusCode)
                {
                    var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
                    _logger.LogError("Docling conversion failed: {StatusCode} - {Error}",
                        response.StatusCode, errorContent);
                    return null;
                }

                var result = await response.Content.ReadFromJsonAsync<DoclingConvertResponse>(
                    cancellationToken: cancellationToken);

                return MapToProcessedDocument(result, fileName, categories);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error uploading file to Docling: {FilePath}", filePath);
                return null;
            }
        }

        private async Task<ProcessedDocument?> SendConversionRequestAsync(
            DoclingConvertRequest request,
            string[]? categories,
            CancellationToken cancellationToken)
        {
            try
            {
                var response = await _httpClient.PostAsJsonAsync(
                    "/v1/convert/source",
                    request,
                    cancellationToken);

                if (!response.IsSuccessStatusCode)
                {
                    var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
                    _logger.LogError("Docling conversion failed: {StatusCode} - {Error}",
                        response.StatusCode, errorContent);
                    return null;
                }

                var result = await response.Content.ReadFromJsonAsync<DoclingConvertResponse>(
                    cancellationToken: cancellationToken);

                var filename = request.Sources.FirstOrDefault()?.Filename
                    ?? request.Sources.FirstOrDefault()?.Url
                    ?? "unknown";

                return MapToProcessedDocument(result, filename, categories);
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "HTTP error calling Docling API");
                return null;
            }
            catch (TaskCanceledException ex)
            {
                _logger.LogError(ex, "Docling conversion timed out");
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Unexpected error calling Docling API");
                return null;
            }
        }

        private ProcessedDocument? MapToProcessedDocument(
            DoclingConvertResponse? response,
            string filename,
            string[]? categories)
        {
            if (response?.Document == null)
            {
                _logger.LogWarning("Docling returned empty document");
                return null;
            }

            var markdownContent = response.Document.MarkdownContent ?? string.Empty;

            return new ProcessedDocument
            {
                DocumentId = Guid.NewGuid().ToString(),
                FileName = Path.GetFileName(filename),
                OriginalFormat = Path.GetExtension(filename).TrimStart('.').ToLower(),
                MarkdownContent = markdownContent,
                TextContent = response.Document.TextContent,
                ProcessedDate = DateTime.UtcNow,
                Categories = categories ?? Array.Empty<string>(),
                PageCount = response.Document.Metadata?.PageCount,
                ContentHash = ComputeHash(markdownContent)
            };
        }

        private static string ComputeHash(string content)
        {
            using var sha256 = SHA256.Create();
            var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(content));
            return Convert.ToBase64String(bytes);
        }

        public void Dispose()
        {
            _httpClient?.Dispose();
        }
    }
}

Υπηρεσία Εισόδου Εγγράφων

Τώρα ας ενσωματώσουμε το Dockling με τον υφιστάμενο αγωγό RAG μας:

using Microsoft.Extensions.Logging;
using Mostlylucid.BlogLLM.Core.Models;

namespace Mostlylucid.BlogLLM.Core.Services
{
    public class DocumentIngestionService
    {
        private readonly ILogger<DocumentIngestionService> _logger;
        private readonly DoclingClient _doclingClient;
        private readonly MarkdownParserService _markdownParser;
        private readonly ChunkingService _chunker;
        private readonly BatchEmbeddingService _embedder;
        private readonly QdrantVectorStore _vectorStore;

        public DocumentIngestionService(
            ILogger<DocumentIngestionService> logger,
            DoclingClient doclingClient,
            MarkdownParserService markdownParser,
            ChunkingService chunker,
            BatchEmbeddingService embedder,
            QdrantVectorStore vectorStore)
        {
            _logger = logger;
            _doclingClient = doclingClient;
            _markdownParser = markdownParser;
            _chunker = chunker;
            _embedder = embedder;
            _vectorStore = vectorStore;
        }

        /// <summary>
        /// Process a document file and add to vector store
        /// </summary>

        public async Task<bool> ProcessDocumentAsync(
            string filePath,
            string[]? categories = null,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("Processing document: {FilePath}", filePath);

                // Step 1: Convert with Docling
                var document = await _doclingClient.ConvertFileUploadAsync(
                    filePath, categories, cancellationToken);

                if (document == null)
                {
                    _logger.LogError("Failed to convert document: {FilePath}", filePath);
                    return false;
                }

                return await ProcessConvertedDocumentAsync(document, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing document {FilePath}", filePath);
                return false;
            }
        }

        /// <summary>
        /// Process a document from URL and add to vector store
        /// </summary>

        public async Task<bool> ProcessDocumentFromUrlAsync(
            string url,
            string[]? categories = null,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("Processing document from URL: {Url}", url);

                // Step 1: Convert with Docling
                var document = await _doclingClient.ConvertFromUrlAsync(
                    url, categories, cancellationToken);

                if (document == null)
                {
                    _logger.LogError("Failed to convert document from URL: {Url}", url);
                    return false;
                }

                return await ProcessConvertedDocumentAsync(document, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing document from URL {Url}", url);
                return false;
            }
        }

        private async Task<bool> ProcessConvertedDocumentAsync(
            ProcessedDocument document,
            CancellationToken cancellationToken)
        {
            _logger.LogInformation("Document converted: {FileName} ({PageCount} pages)",
                document.FileName, document.PageCount ?? 0);

            // Step 2: Parse the markdown content
            var post = _markdownParser.ParseMarkdownFromContent(
                document.MarkdownContent,
                document.FileName);
            post.Categories = document.Categories;

            // Step 3: Chunk the content
            var chunks = _chunker.ChunkBlogPost(post);
            _logger.LogInformation("Created {ChunkCount} chunks from {FileName}",
                chunks.Count, document.FileName);

            if (chunks.Count == 0)
            {
                _logger.LogWarning("No chunks created for document: {FileName}", document.FileName);
                return false;
            }

            // Step 4: Generate embeddings
            var progress = new Progress<int>(processed =>
            {
                _logger.LogDebug("Embedded {Processed}/{Total} chunks",
                    processed, chunks.Count);
            });

            await _embedder.GenerateEmbeddingsAsync(chunks, progress, cancellationToken);

            // Step 5: Store in vector database
            await _vectorStore.UpsertChunksAsync(chunks);

            _logger.LogInformation("Successfully processed document: {FileName} ({ChunkCount} chunks)",
                document.FileName, chunks.Count);

            return true;
        }

        /// <summary>
        /// Batch process multiple documents
        /// </summary>

        public async Task<(int success, int failed)> ProcessDocumentBatchAsync(
            IEnumerable<string> filePaths,
            string[]? categories = null,
            CancellationToken cancellationToken = default)
        {
            int success = 0;
            int failed = 0;

            foreach (var filePath in filePaths)
            {
                if (cancellationToken.IsCancellationRequested)
                    break;

                var result = await ProcessDocumentAsync(filePath, categories, cancellationToken);
                if (result)
                    success++;
                else
                    failed++;
            }

            _logger.LogInformation("Batch processing complete: {Success} succeeded, {Failed} failed",
                success, failed);

            return (success, failed);
        }
    }
}

Ρύθμιση εγχύσεων εξάρτησης

using Microsoft.Extensions.DependencyInjection;
using Mostlylucid.BlogLLM.Core.Services;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddDoclingServices(
        this IServiceCollection services,
        Action<DoclingClientOptions>? configureOptions = null)
    {
        // Configure options
        if (configureOptions != null)
        {
            services.Configure(configureOptions);
        }
        else
        {
            services.Configure<DoclingClientOptions>(options =>
            {
                options.BaseUrl = "http://localhost:5001";
                options.TimeoutSeconds = 300;
                options.EnableOcr = true;
            });
        }

        // Register HttpClient with configuration
        services.AddHttpClient<DoclingClient>((serviceProvider, client) =>
        {
            var options = serviceProvider
                .GetRequiredService<IOptions<DoclingClientOptions>>().Value;
            client.BaseAddress = new Uri(options.BaseUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
        });

        // Register services
        services.AddScoped<DocumentIngestionService>();

        return services;
    }
}

Ρύθμιση

Προσθήκη στο δικό σας appsettings.json:

{
  "Docling": {
    "BaseUrl": "http://localhost:5001",
    "TimeoutSeconds": 300,
    "EnableOcr": true,
    "TableMode": "accurate"
  }
}

Παραδείγματα χρήσης

Επεξεργασία διαφορετικών τύπων εγγράφων

// PDF Processing
await documentIngestionService.ProcessDocumentAsync(
    "C:\\documents\\client_contract.pdf",
    new[] { "legal", "contracts", "client-agreements" });

// DOCX Processing
await documentIngestionService.ProcessDocumentAsync(
    "C:\\documents\\motion_to_dismiss.docx",
    new[] { "legal", "briefs", "motions" });

// URL Processing (great for public documents)
await documentIngestionService.ProcessDocumentFromUrlAsync(
    "https://arxiv.org/pdf/2501.17887",
    new[] { "research", "ai", "docling" });

// Batch Processing
var files = Directory.GetFiles("C:\\documents\\legal", "*.pdf");
var (success, failed) = await documentIngestionService.ProcessDocumentBatchAsync(
    files,
    new[] { "legal", "batch-import" });
Console.WriteLine($"Processed {success} files, {failed} failures");

Παρατηρητής αρχείων για αυτόματη κατάποση

public class DocumentWatcherService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<DocumentWatcherService> _logger;
    private FileSystemWatcher? _watcher;
    private readonly string _watchPath;

    public DocumentWatcherService(
        IServiceProvider serviceProvider,
        ILogger<DocumentWatcherService> logger,
        IConfiguration configuration)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
        _watchPath = configuration["DocumentWatch:Path"] ?? "C:\\documents\\incoming";
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        if (!Directory.Exists(_watchPath))
        {
            Directory.CreateDirectory(_watchPath);
        }

        _watcher = new FileSystemWatcher(_watchPath)
        {
            NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite,
            IncludeSubdirectories = false
        };

        // Watch for common document types
        _watcher.Filters.Add("*.pdf");
        _watcher.Filters.Add("*.docx");
        _watcher.Filters.Add("*.doc");
        _watcher.Filters.Add("*.pptx");

        _watcher.Created += OnFileCreated;
        _watcher.EnableRaisingEvents = true;

        _logger.LogInformation("Watching for documents in: {Path}", _watchPath);

        return Task.CompletedTask;
    }

    private async void OnFileCreated(object sender, FileSystemEventArgs e)
    {
        _logger.LogInformation("New document detected: {FileName}", e.Name);

        // Wait for file to be fully written
        await Task.Delay(1000);

        using var scope = _serviceProvider.CreateScope();
        var ingestionService = scope.ServiceProvider
            .GetRequiredService<DocumentIngestionService>();

        await ingestionService.ProcessDocumentAsync(e.FullPath);
    }

    public override void Dispose()
    {
        _watcher?.Dispose();
        base.Dispose();
    }
}

Εκτιμήσεις Απόδοσης

Επίδραση μεγέθους εγγράφου

Τύπος εγγράφου ~ Τυπικό μέγεθος ~ Επεξεργασία εγγράφου ~ Χρόνος ενσωμάτωσης ~ |--------------|-------------|-------------------|----------------| Απλή PDF (1-5 σελίδες) 100KB-500KB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Συγκρότημα PDF (20+ σελίδες) 1-5MB 10-30 δευτερόλεπτα Κονσερβοποιημένο PDF με OCR 1-10MB 30-120 δευτερόλεπτα

  • DOCX Document - 50KB-500KB - 1-3 δευτερόλεπτα Παρουσίαση PPTX 1-20MB 5-30 seconds 1-3 seconds

Συμβουλές βελτιστοποίησης

  1. Χρήση εικόνων GPU για τις βαριές εργασίες OCR (docling-serve-cu126 ή docling-serve-cu128)
  2. Απενεργοποίηση OCR για ψηφιακό-ιθαγενή PDF για την επιτάχυνση της επεξεργασίας
  3. Χρήση fast Λειτουργία τραπεζιού όταν η ακρίβεια του πίνακα δεν είναι κρίσιμη
  4. Διαδικασία παρτίδας κατά τη διάρκεια ωρών εκτός αιχμής για μεγάλα σύνολα εγγράφων
  5. Αποτελέσματα Cache - αποθήκευση του περιεχομένου για την αποφυγή της επεξεργασίας των αμετάβλητων εγγράφων

Περίληψη

Έχουμε ενσωματώσει με επιτυχία το σύστημα Δικηγόρων GPT, επιτρέποντας:

  1. Επεξεργασία PDF, DOCX, PPTX και άλλων μορφοτύπων εγγράφων
  2. Υποστήριξη OCR για σαρωμένα έγγραφα
  3. Καθαρή ενσωμάτωση με τον υφιστάμενο αγωγό AGG μας
  4. Ανάπτυξη Docker για επεκτασιμότητα
  5. Δυνατότητες επεξεργασίας παρτίδας
  6. Αυτόματη παρακολούθηση αρχείων για hands-off κατάποση

Αυτό επεκτείνει τη βάση γνώσεων μας πέρα από τις δημοσιεύσεις blog για να περιλαμβάνει νομικά έγγραφα, συμβόλαια, ερευνητικά έγγραφα, και άλλα σημαντικά υλικά.

Πλοήγηση σειράς

Πόροι

logo

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