AI-documentextractie voor Delphi en .NET

· Componenten
AI-documentextractie voor Delphi en .NET

De meeste bedrijfssoftware heeft nog altijd ergens een persoon die een PDF leest en de cijfers ervan in een formulier typt. Leveranciersfacturen, kassabonnen, de scan van een identiteitskaart aan de balie. De grote taalmodellen lezen die documenten tegenwoordig goed, maar als je een model om "de factuurgegevens" vraagt, krijg je lopende tekst, of JSON in een vorm die het toevallig heeft gekozen, zonder enige manier om te zien over welke waarden het onzeker was.

sgcWebSockets 2026.10 voegt TsgcAIDocumentExtractor toe voor Delphi, C++Builder en .NET. Je geeft het een PDF of een afbeelding, het stelt de vraag aan het model dat je al gebruikt via TsgcAIChat, en het levert JSON terug die tegen een schema is gevalideerd, met een betrouwbaarheid voor elk veld. De component maakt geen deel uit van de huidige download. Hij komt met de 2026.10-release.

TsgcAIDocumentExtractor leest een echte factuur-PDF met Anthropic Claude en levert gevalideerde JSON met een betrouwbaarheid per veld. Ook op YouTube.

Een PDF erin, JSON eruit

Zet een TsgcAIChat en een TsgcAIDocumentExtractor op een formulier, wijs de extractor naar de chat, kies een preset en roep ExtractFile aan. OpenAI, Anthropic en Gemini lezen PDF-bestanden zoals ze zijn. DeepSeek, Grok, Mistral en Ollama nemen alleen afbeeldingen aan, dus voor die providers stuur je de pagina's als PNG of 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;

Dit is de flow die in de video wordt getoond, en hij is live geverifieerd tegen Anthropic Claude op een echte factuur-PDF. ExtractFiles stuurt meerdere pagina's van één document in een enkel verzoek, en ExtractAttachments neemt documenten aan die je al als base64 in het geheugen hebt.

De extractor doet zijn werk via TsgcAIChat, dat dezelfde mogelijkheden krijgt voor je eigen prompts. ChatWithDocument stuurt een PDF of een afbeelding mee met een bericht, ChatWithAttachments stuurt er meteen meerdere, en ChatJSONWithAttachments vraagt om een JSON-antwoord daarover. Een nieuwe property TLSOptions stelt de OpenSSL-versie, de IOHandler en de certificaten in die voor elke provider worden gebruikt.

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;

Presets en je eigen schema

Drie presets dekken de veelvoorkomende documenten: dpInvoice, dpReceipt en dpIDCard. Elke preset brengt zijn eigen JSON-schema en zijn extractie-instructies mee, zodat er verder niets te configureren valt. Voor elk ander document zet je Preset op dpCustom en schrijf je het schema zelf.

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.';

Bij OpenAI wordt het schema in strict mode verstuurd, dus het moet aan de strikte regels voldoen: elk object declareert "additionalProperties": false, elke property staat vermeld in required, en een optionele waarde gebruikt een nullable type zoals ["string", "null"]. De ingebouwde presets volgen die regels al. Om van één daarvan te vertrekken en een veld toe te voegen, kopieer je hem met TsgcAIDocumentExtractor.GetPresetSchema(dpInvoice).

Validatie en opnieuw proberen

Het antwoord bereikt je code nooit ongecontroleerd. De extractor valideert het lokaal tegen het schema: types, verplichte properties, geneste objecten en arrays, en enums. Als het niet overeenkomt, vertelt de component het model wat er fout was en vraagt het nog eens. ValidationRetries stelt in hoe vaak, en staat standaard op 1.

Als de data na de nieuwe pogingen nog steeds ongeldig is, werpt de extractor een exception. Zet RaiseOnInvalid op False om de data toch te krijgen en de problemen te lezen uit LastResult.ValidationErrors, elk als een regel path: message.

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);

Betrouwbaarheid en menselijke controle

Geldige JSON is niet hetzelfde als correcte JSON. Een onscherp totaalbedrag of een vervaagde datum kan nog altijd een keurig gevormd getal opleveren. Daarom rapporteert het model ook hoe zeker het is over elk veld dat het heeft geëxtraheerd, en de extractor geeft je die waarden door. LastResult.Confidence is de laagste ervan, LastResult.FieldConfidence('total') geeft de waarde voor één pad terug, en OnLowConfidence gaat af voor elk veld onder 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;

Dat maakt van een controlewachtrij iets waar een mens doorheen komt: ze controleren de twee velden waarover het model twijfelde, niet de hele factuur.

Lokale OCR, niets verlaat de machine

Sommige documenten mogen helemaal niet naar een clouddienst gaan. Koppel een OCR-component aan de extractor en kies de engine die bij je past. TsgcAIOCRTesseract stuurt de op de machine geïnstalleerde Tesseract OCR-engine aan. TsgcAIOCRWindows gebruikt de tekstherkenning die ingebouwd is in Windows 10 en hoger, dus er hoeft niets geïnstalleerd te worden. Met OCRMode op domAlways worden de afbeeldingen nooit naar het model gestuurd. De OCR-engine leest de tekst lokaal, en een tekstmodel zoals Ollama doet de extractie, zodat de hele pipeline op je eigen hardware draait.

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');

De Windows-engine accepteert een BCP-47-taaltag zoals en-US, of een lege Language om de talen van het gebruikersprofiel te gebruiken.

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

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

domFallback, gebruikt in dit tweede voorbeeld, is de andere optie. De extractor probeert eerst het visie-verzoek en gebruikt de herkende tekst pas wanneer dat verzoek mislukt, waarbij OnOCRFallback afgaat zodat je weet dat het is gebeurd. LastResult.UsedOCR en LastResult.OCRText vertellen je achteraf welk pad de data heeft geproduceerd. De OCR-stap leest afbeeldingen, dus een gescande PDF gaat erin als paginabeelden.

C# voor .NET

De .NET-editie van sgcWebSockets heeft dezelfde componenten met dezelfde namen in de namespace esegece.sgcWebSockets. De presets, de betrouwbaarheidswaarden en de events werken op dezelfde manier, en beide OCR-engines, TsgcAIOCRTesseract en TsgcAIOCRWindows, zijn er ook.

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}");

Beschikbaarheid

TsgcAIDocumentExtractor, TsgcAIOCRTesseract, TsgcAIOCRWindows en de nieuwe TsgcAIChat-methoden komen in sgcWebSockets 2026.10, voor Delphi, C++Builder en .NET. Ze zitten niet in de versie die je vandaag kunt downloaden. Zodra 2026.10 verschijnt, staat hij op de downloadpagina.

De volledige referentie, met elke property en event en een stapsgewijze factuurgids, staat in de TsgcAIDocumentExtractor-help. Voor al het andere dat de AI-componenten doen, zie de sgcAI-productpagina en de sgcWebSockets AI-pagina.

Lees verder

Vragen, feedback of hulp bij migratie? Neem contact op. Je krijgt een antwoord van de mensen die de code hebben geschreven.