Estrazione documenti AI per Delphi e .NET

· Componenti
Estrazione documenti AI per Delphi e .NET

Molti software aziendali hanno ancora qualcuno che legge un PDF e ne digita i numeri in un modulo. Fatture dei fornitori, scontrini di cassa, la scansione di una carta d'identità alla reception. Oggi i grandi modelli linguistici leggono bene questi documenti, ma chiedere a un modello "i dati della fattura" restituisce prosa, oppure JSON nella forma che ha deciso di scrivere in quel momento, senza alcun modo di sapere su quali valori non era sicuro.

sgcWebSockets 2026.10 aggiunge TsgcAIDocumentExtractor per Delphi, C++Builder e .NET. Gli fornisci un PDF o un'immagine, lui interroga il modello che già usi tramite TsgcAIChat, e restituisce JSON validato rispetto a uno schema, con un livello di confidenza per ogni campo. Il componente non fa parte del download attuale. Arriva con la versione 2026.10.

TsgcAIDocumentExtractor che legge una fattura PDF reale con Anthropic Claude e restituisce JSON validato con un livello di confidenza per ogni campo. Anche su YouTube.

Un PDF in ingresso, JSON in uscita

Trascina un TsgcAIChat e un TsgcAIDocumentExtractor su un form, punta l'extractor verso la chat, scegli un preset e chiama ExtractFile. OpenAI, Anthropic e Gemini leggono i file PDF così come sono. DeepSeek, Grok, Mistral e Ollama richiedono immagini, quindi per questi provider invii le pagine come PNG o 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;

Questo è il flusso mostrato nel video, verificato dal vivo con Anthropic Claude su una fattura PDF reale. ExtractFiles invia più pagine di un unico documento in un'unica richiesta, e ExtractAttachments accetta documenti già presenti in memoria come base64.

L'extractor svolge il proprio lavoro tramite TsgcAIChat, che acquisisce le stesse capacità per i tuoi prompt. ChatWithDocument invia un PDF o un'immagine insieme a un messaggio, ChatWithAttachments ne invia più di uno alla volta, e ChatJSONWithAttachments chiede una risposta in JSON su di essi. Una nuova proprietà TLSOptions imposta la versione di OpenSSL, l'IOHandler e i certificati usati da ogni provider.

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;

Preset e schema personalizzato

Tre preset coprono i documenti più comuni: dpInvoice, dpReceipt e dpIDCard. Ognuno porta con sé il proprio schema JSON e le proprie istruzioni di estrazione, quindi non c'è altro da configurare. Per qualsiasi altro documento, imposta Preset su dpCustom e scrivi lo schema tu stesso.

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

Con OpenAI lo schema viene inviato in modalità strict, quindi deve rispettare le regole rigide: ogni oggetto dichiara "additionalProperties": false, ogni proprietà è elencata in required, e un valore opzionale usa un tipo nullable come ["string", "null"]. I preset integrati rispettano già queste regole. Per partire da uno di essi e aggiungere un campo, copialo con TsgcAIDocumentExtractor.GetPresetSchema(dpInvoice).

Validazione e nuovo tentativo

La risposta non arriva mai al tuo codice senza controlli. L'extractor la valida localmente rispetto allo schema: tipi, proprietà obbligatorie, oggetti e array annidati, ed enum. Quando non corrisponde, il componente dice al modello cosa non andava e chiede di nuovo. ValidationRetries imposta quante volte, ed è 1 per impostazione predefinita.

Se i dati sono ancora non validi dopo i tentativi, l'extractor solleva un'eccezione. Imposta RaiseOnInvalid su False per ottenere comunque i dati e leggere i problemi da LastResult.ValidationErrors, una riga path: message per ciascuno.

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

Confidenza e revisione umana

JSON valido non è la stessa cosa di JSON corretto. Un totale sfocato o una data macchiata possono comunque produrre un numero ben formato. Per questo il modello riporta anche quanto è sicuro di ogni campo estratto, e l'extractor ti fornisce questi valori. LastResult.Confidence è il più basso tra tutti, LastResult.FieldConfidence('total') restituisce il valore per un percorso, e OnLowConfidence scatta una volta per ogni campo sotto 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;

Questo trasforma una coda di revisione in qualcosa che una persona può davvero gestire: controlla i due campi su cui il modello aveva dei dubbi, non l'intera fattura.

OCR locale, nulla lascia la macchina

Alcuni documenti non devono proprio raggiungere un servizio cloud. Collega un componente OCR all'extractor e scegli il motore più adatto a te. TsgcAIOCRTesseract esegue il motore OCR Tesseract installato sulla macchina. TsgcAIOCRWindows usa il riconoscimento del testo integrato in Windows 10 e versioni successive, quindi non c'è nulla da installare. Con OCRMode impostato su domAlways, le immagini non vengono mai inviate al modello. Il motore OCR legge il testo localmente, e un modello testuale come Ollama esegue l'estrazione, così l'intera pipeline gira sul tuo hardware.

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

Il motore di Windows accetta un tag di lingua BCP-47 come en-US, oppure un Language vuoto per usare le lingue del profilo utente.

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

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

domFallback, usato in questo secondo esempio, è l'altra opzione. L'extractor tenta prima la richiesta vision e usa il testo riconosciuto solo se quella richiesta fallisce, facendo scattare OnOCRFallback così sai che è successo. LastResult.UsedOCR e LastResult.OCRText ti dicono in seguito quale percorso ha prodotto i dati. Il passaggio OCR legge immagini, quindi un PDF scansionato entra come immagini di pagina.

C# per .NET

L'edizione .NET di sgcWebSockets ha gli stessi componenti con gli stessi nomi nel namespace esegece.sgcWebSockets. I preset, i valori di confidenza e gli eventi funzionano allo stesso modo, e anche entrambi i motori OCR, TsgcAIOCRTesseract e TsgcAIOCRWindows, sono presenti.

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

Disponibilità

TsgcAIDocumentExtractor, TsgcAIOCRTesseract, TsgcAIOCRWindows e i nuovi metodi di TsgcAIChat arrivano in sgcWebSockets 2026.10, per Delphi, C++Builder e .NET. Non sono nella versione che puoi scaricare oggi. Quando uscirà la 2026.10, sarà sulla pagina di download.

Il riferimento completo, con ogni proprietà ed evento e una guida passo passo per le fatture, è nella guida di TsgcAIDocumentExtractor. Per tutto il resto che fanno i componenti AI, vedi la pagina di prodotto sgcAI e la pagina AI di sgcWebSockets.

Continua a leggere

Domande, feedback o aiuto con la migrazione? Mettiti in contatto. Riceverai una risposta dalle persone che hanno scritto il codice.