Skip to main content

Document Processing

Il motore di document processing trasforma un documento in un insieme versionato e verificabile di evidenze. Non appartiene a uno specifico verticale: ogni applicazione sceglie un workflow pubblicato e il control plane ne esegue il grafo.

Principi

  • Il workflow è un DAG versionato nel database; nodi e archi non sono codificati nei worker.
  • Il control plane decide routing, join, condizioni, priorità e retry.
  • Ogni worker svolge un solo compito, completa il job BullMQ e comunica l'esito al control plane.
  • I worker non scelgono il passo successivo.
  • PostgreSQL conserva la verità e la provenance; Qdrant contiene indici derivati e ricostruibili.
  • I metadati persistenti passano da data-service. I worker non accedono direttamente a DataHub o PostgreSQL.
  • Ogni job conserva userId, documentId, processingRunId, versione del workflow e riferimenti agli artefatti. Gli accessi sono nuovamente verificati da data-service.
  • I payload di coda trasportano identificativi e riferimenti, non il PDF o grandi risultati di elaborazione.

Contratto universale dei worker

I workflow rimangono versionati e pubblicati nel database. I worker, invece, non conoscono il workflow né il verticale che li sta usando. Un job riutilizzabile contiene:

  • inputArtifact: metadati e accesso temporaneo/opaco al contenuto;
  • outputTarget: endpoint del servizio proprietario a cui consegnare gli artefatti;
  • workflowRunId e taskRunId: correlazione tecnica con il control plane;
  • options: soli parametri tecnici dell'elaborazione;
  • passthrough: contesto opaco che il worker restituisce senza interpretarlo.

L'accesso a input e output usa un internal JWT ristretto per audience e scope. Il worker non chiama API verticali, datahub o PostgreSQL e non inserisce file o grandi risultati in Redis. Il provider di origine decide come leggere il documento; il provider di destinazione decide come persistere il risultato. Questo permette allo stesso container di elaborare, in sequenza, documenti rAInty, Bandi o di futuri verticali.

Il contratto precedente di File resta temporaneamente supportato dagli stessi worker per garantire la non regressione durante la migrazione degli adapter di acquisizione e persistenza.

Workflow Bandi con OCR condizionale

Da bandi-call-document-processing@1.1.0, Document Intelligence esegue un probe della qualità del layer testuale. I PDF con testo sufficiente proseguono direttamente; quelli image-only passano dalla stessa coda document.text.extract usata dagli altri workflow. Il risultato OCR è persistito da Bandi e i due rami confluiscono, con join ANY, nel parsing strutturale.

Documento acquisito -> probe contenuto ---- testo nativo ----|
| |
+-- OCR condiviso -----+--> Document Intelligence
|
v
Call Package & Rubric

Workflow corrente

Il workflow pubblicato file-text-only@1.5.0 ha due ingressi: LIVE, con priorità alta, e BATCH, con priorità inferiore.

LIVE / BATCH
|
v
Fingerprint SHA-256
|
+-- copia esatta --> collega documento canonico --> Completed
|
+-- contenuto nuovo
|-------------------------------|
v v
Text extraction Visual extraction
| |
v v
Index text Index visuals/layout
| |
+-------------- join -----------+
|
v
Similar-document search
|
v
Completed

Text e visual extraction lavorano in parallelo. Anche l'indicizzazione è incrementale: ciascun ramo può salvare il proprio contributo senza attendere l'altro; il terminale viene raggiunto soltanto quando entrambi sono conclusi.

Workflow esteso

Il workflow corrente ricerca documenti simili, risolve e arricchisce l'issuer, consolida le evidenze e infine classifica il documento.

Text indexed --------------------|
+--> Similar-document search --------|
Visual/layout indexed -----------| |
+--> Evidence fusion
Text + visual evidence ----------+--> Local issuer resolution --------| |
v
issuer sufficientemente certo?
| sì | no
| v
| Web issuer enrichment
| |
+---- join+
|
v
Classification context
|
v
Document classification

La ricerca di similarità e la raccolta dei candidati issuer possono iniziare dopo il join degli indici. La fusione usa entrambi i risultati. L'accesso al web è un fallback condizionale e non blocca workflow che non lo consentono.

Stato dei componenti

ComponenteStatoResponsabilità
document-processing-control-planeOperativoEsecuzione del DAG, code, join, retry e osservabilità
document-fingerprint-workerOperativoHash SHA-256 e rilevazione copie esatte
document-text-extraction-workerOperativoTesto PDF e fallback OCR
document-visual-extraction-workerOperativoRendering, elementi grafici, layout e normalizzazione
document-knowledge-indexing-workerOperativoCatalogo delle evidenze e indici Qdrant
document-similarity-workerOperativoRicerca e ranking multimodale dei documenti simili
document-issuer-resolution-workerOperativoRisoluzione locale e deterministica dell'issuer
issuer-web-enrichment-workerOperativoRicerca web controllata degli issuer non risolti
document-evidence-consolidation-workerOperativoSnapshot immutabile delle evidenze e controllo di readiness
document-classification-workerOperativoClassificazione tassonomica con regole, similarità, issuer e fallback LLM
structured-data-extraction-workerOperativoEstrazione JSON versionata, deterministica/inferenziale, guidata da classificazione e schema

Dati e isolamento

Le evidenze appartenenti a un documento, i candidati di similarità e le osservazioni issuer sono sempre scoped per utente/tenant. Il catalogo verificato degli issuer può essere globale, ma non deve rivelare documenti, testo o relazioni di altri utenti. Ogni query Qdrant deve applicare il filtro di ownership presente nel payload.

La classificazione di un documento simile è un'evidenza, non una verità: una conferma umana pesa più di una classificazione automatica. Le associazioni issuer -> document type devono essere apprese solo da conferme o da politiche esplicite ad alta confidenza, evitando cicli di auto-conferma.

Contratto di avanzamento

Ogni worker produce un output piccolo e versionato, salva gli artefatti tramite i servizi proprietari e completa il job. Il control plane riceve l'esito tramite l'avanzamento BullMQ idempotente e valuta gli archi uscenti. Job concorrenti possono terminare insieme: l'idempotenza e lo stato persistito del run rendono sicura la valutazione del join.