Ekstrakcja dokumentów AI dla Delphi i .NET

· Komponenty
Ekstrakcja dokumentów AI dla Delphi i .NET

Większość oprogramowania biznesowego wciąż ma gdzieś osobę, która czyta PDF i wpisuje jego liczby do formularza. Faktury od dostawców, paragony z kasy, skan dowodu osobistego w recepcji. Duże modele językowe dziś dobrze czytają takie dokumenty, ale poproszenie modelu o "dane z faktury" daje w odpowiedzi zwykły tekst albo JSON w dowolnej formie, jaką akurat wybrał, bez żadnego sposobu, by sprawdzić, których wartości nie był pewien.

sgcWebSockets 2026.10 dodaje TsgcAIDocumentExtractor dla Delphi, C++Buildera i .NET. Podajesz mu PDF lub obraz, on pyta model, którego już używasz przez TsgcAIChat, i zwraca JSON zwalidowany względem schematu, z poziomem pewności dla każdego pola. Komponent nie jest częścią obecnej wersji do pobrania. Pojawi się wraz z wydaniem 2026.10.

TsgcAIDocumentExtractor odczytuje prawdziwą fakturę PDF za pomocą Anthropic Claude i zwraca zwalidowany JSON z poziomem pewności dla każdego pola. Również w serwisie YouTube.

PDF na wejściu, JSON na wyjściu

Umieść TsgcAIChat i TsgcAIDocumentExtractor na formularzu, wskaż extractorowi czat, wybierz preset i wywołaj ExtractFile. OpenAI, Anthropic i Gemini odczytują pliki PDF w takiej postaci, w jakiej są. DeepSeek, Grok, Mistral i Ollama przyjmują tylko obrazy, więc dla tych dostawców wysyłasz strony jako PNG lub JPEG.

uses
  sgcAI, sgcAI_Chat, sgcAI_DocumentExtractor;

procedure TForm1.btnExtractClick(Sender: TObject);
begin
  oChat := TsgcAIChat.Create(Self);
  oChat.Provider := aicpAnthropic;
  oChat.ChatOptions.ApiKey := 'your-api-key';

  oExtractor := TsgcAIDocumentExtractor.Create(Self);
  oExtractor.AIChat := oChat;
  oExtractor.Preset := dpInvoice;

  Memo1.Lines.Text := oExtractor.ExtractFile('invoice.pdf');
end;

To jest przepływ pokazany w wideo, zweryfikowany na żywo z Anthropic Claude na prawdziwej fakturze PDF. ExtractFiles wysyła kilka stron jednego dokumentu w jednym żądaniu, a ExtractAttachments przyjmuje dokumenty, które masz już w pamięci, zakodowane jako base64.

Extractor wykonuje swoją pracę za pośrednictwem TsgcAIChat, który zyskuje te same możliwości dla twoich własnych promptów. ChatWithDocument wysyła PDF lub obraz razem z wiadomością, ChatWithAttachments wysyła kilka naraz, a ChatJSONWithAttachments prosi o odpowiedź w formacie JSON na ich temat. Nowa właściwość TLSOptions ustawia wersję OpenSSL, IOHandler i certyfikaty używane przez każdego dostawcę.

Memo1.Lines.Text := oChat.ChatWithDocument('Summarize this contract', 'contract.pdf');

oFiles := TsgcAIChatAttachments.Create;
try
  oFiles.AddFile('page1.png');
  oFiles.AddFile('page2.png');
  Memo1.Lines.Text := oChat.ChatJSONWithAttachments(
    'List every line item as JSON', oFiles);
finally
  oFiles.Free;
end;

Presety i własny schemat

Trzy presety pokrywają typowe dokumenty: dpInvoice, dpReceipt i dpIDCard. Każdy z nich przynosi własny schemat JSON i własne instrukcje ekstrakcji, więc nie trzeba konfigurować niczego więcej. Dla każdego innego dokumentu ustaw Preset na dpCustom i napisz schemat samodzielnie.

oExtractor.Preset := dpCustom;
oExtractor.SchemaName := 'purchase_order';
oExtractor.Schema.Text :=
  '{"type": "object", "additionalProperties": false,' +
  ' "required": ["order_number", "supplier", "total"],' +
  ' "properties": {' +
  '   "order_number": {"type": "string"},' +
  '   "supplier": {"type": ["string", "null"]},' +
  '   "total": {"type": "number"}}}';
oExtractor.Instructions.Text := 'Write every amount without a currency symbol.';

Wysyłany do OpenAI schemat działa w trybie ścisłym (strict mode), więc musi spełniać jego reguły: każdy obiekt deklaruje "additionalProperties": false, każda właściwość jest wymieniona w required, a wartość opcjonalna używa typu dopuszczającego null, na przykład ["string", "null"]. Wbudowane presety już spełniają te reguły. Aby wyjść od jednego z nich i dodać pole, skopiuj go za pomocą TsgcAIDocumentExtractor.GetPresetSchema(dpInvoice).

Walidacja i ponowna próba

Odpowiedź nigdy nie trafia do twojego kodu niesprawdzona. Extractor waliduje ją lokalnie względem schematu: typy, wymagane właściwości, zagnieżdżone obiekty i tablice oraz wartości enum. Gdy coś się nie zgadza, komponent mówi modelowi, co było nie tak, i prosi jeszcze raz. ValidationRetries ustala, ile razy, a domyślna wartość to 1.

Jeśli dane wciąż są nieprawidłowe po wyczerpaniu prób, extractor zgłasza wyjątek. Ustaw RaiseOnInvalid na False, aby i tak otrzymać dane i odczytać problemy z LastResult.ValidationErrors, po jednej linii path: message na każdy z nich.

oExtractor.ValidationRetries := 1;
oExtractor.RaiseOnInvalid := False;

Memo1.Lines.Text := oExtractor.ExtractFile('invoice.pdf');
if not oExtractor.LastResult.Valid then
  Memo1.Lines.AddStrings(oExtractor.LastResult.ValidationErrors);

Pewność i weryfikacja przez człowieka

Prawidłowy JSON to nie to samo, co poprawny JSON. Zamazana suma albo rozmazana data wciąż mogą dać poprawnie sformatowaną liczbę. Dlatego model podaje też, jak bardzo jest pewien każdego wyodrębnionego pola, a extractor przekazuje te wartości dalej. LastResult.Confidence to najniższa z nich, LastResult.FieldConfidence('total') zwraca wartość dla jednej ścieżki, a OnLowConfidence uruchamia się raz dla każdego pola poniżej MinConfidence.

oExtractor.MinConfidence := 0.8;
oExtractor.OnLowConfidence := OnLowConfidenceEvent;
Memo1.Lines.Text := oExtractor.ExtractFile('invoice.pdf');

if oExtractor.LastResult.FieldConfidence('total') < 0.8 then
  ShowMessage('Check the total by hand');

procedure TForm1.OnLowConfidenceEvent(Sender: TObject; const aField: string;
  aConfidence: Double);
begin
  lstReview.Items.Add(Format('%s: %.2f', [aField, aConfidence]));
end;

Dzięki temu kolejka do weryfikacji staje się czymś, co człowiek jest w stanie realnie przejrzeć: sprawdza te dwa pola, co do których model miał wątpliwości, a nie całą fakturę.

Lokalny OCR, nic nie opuszcza maszyny

Niektóre dokumenty w ogóle nie mogą trafić do żadnej usługi w chmurze. Połącz komponent OCR z extractorem i wybierz silnik, który ci odpowiada. TsgcAIOCRTesseract uruchamia zainstalowany na maszynie silnik OCR Tesseract. TsgcAIOCRWindows korzysta z rozpoznawania tekstu wbudowanego w Windows 10 i nowsze, więc nie trzeba niczego instalować. Gdy OCRMode jest ustawione na domAlways, obrazy nigdy nie są wysyłane do modelu. Silnik OCR odczytuje tekst lokalnie, a ekstrakcję wykonuje model tekstowy, na przykład Ollama, więc cały proces działa na twoim własnym sprzęcie.

oOCR := TsgcAIOCRTesseract.Create(Self);
oOCR.Language := 'eng';

oChat.Provider := aicpOllama;
oChat.ChatOptions.Model := 'llama3.1';

oExtractor.OCR := oOCR;
oExtractor.OCRMode := domAlways;
oExtractor.Preset := dpReceipt;
Memo1.Lines.Text := oExtractor.ExtractFile('receipt.png');

Silnik Windows przyjmuje znacznik języka BCP-47, na przykład en-US, albo pusty Language, aby użyć języków z profilu użytkownika.

oWinOCR := TsgcAIOCRWindows.Create(Self);
oWinOCR.Language := 'en-US';

oExtractor.OCR := oWinOCR;
oExtractor.OCRMode := domFallback;
Memo1.Lines.Text := oExtractor.ExtractFile('invoice.png');

domFallback, użyty w tym drugim przykładzie, to druga opcja. Extractor najpierw próbuje żądania z rozpoznawaniem obrazu i sięga po rozpoznany tekst dopiero, gdy to żądanie się nie powiedzie, wywołując przy tym OnOCRFallback, żebyś o tym wiedział. LastResult.UsedOCR i LastResult.OCRText mówią potem, która ścieżka dała dane. Krok OCR odczytuje obrazy, więc zeskanowany PDF wchodzi jako obrazy stron.

C# dla .NET

Edycja .NET sgcWebSockets ma te same komponenty pod tymi samymi nazwami w przestrzeni nazw esegece.sgcWebSockets. Presety, wartości pewności i zdarzenia działają tak samo, a oba silniki OCR, TsgcAIOCRTesseract i TsgcAIOCRWindows, też tam są.

using esegece.sgcWebSockets;

var chat = new TsgcAIChat();
chat.Provider = TsgcAIChatProvider.aicpAnthropic;
chat.ChatOptions.ApiKey = "your-api-key";

var extractor = new TsgcAIDocumentExtractor();
extractor.AIChat = chat;
extractor.Preset = TsgcAIDocumentPreset.dpInvoice;
extractor.MinConfidence = 0.8;
extractor.OnLowConfidence += (sender, field, confidence) =>
    Console.WriteLine($"review {field}: {confidence:0.00}");

string json = extractor.ExtractFile("invoice.pdf");
Console.WriteLine(json);
Console.WriteLine($"valid: {extractor.LastResult.Valid}, confidence: {extractor.LastResult.Confidence:0.00}");

Dostępność

TsgcAIDocumentExtractor, TsgcAIOCRTesseract, TsgcAIOCRWindows i nowe metody TsgcAIChat pojawią się w sgcWebSockets 2026.10, dla Delphi, C++Buildera i .NET. Nie ma ich w wersji, którą można pobrać dzisiaj. Gdy 2026.10 zostanie wydane, znajdziesz je na stronie pobierania.

Pełna dokumentacja referencyjna, z każdą właściwością i zdarzeniem oraz przewodnikiem krok po kroku dla faktur, znajduje się w pomocy TsgcAIDocumentExtractor. Wszystko inne, co robią komponenty AI, opisuje strona produktu sgcAI oraz strona AI w sgcWebSockets.

Czytaj dalej

Masz pytania, uwagi lub potrzebujesz pomocy przy migracji? Skontaktuj się z nami. Otrzymasz odpowiedź od osób, które napisały ten kod.