Elaborazione intelligente dei documenti con i servizi di intelligenza artificiale AWS e Amazon Bedrock

Gestione avanzata dei documenti con l'intelligenza artificiale di AWS e Amazon Bedrock

Le aziende dei settori della sanità, della finanza, del legale, del commercio al dettaglio e della produzione gestiscono spesso grandi quantità di documenti come parte delle loro operazioni quotidiane. Questi documenti contengono spesso informazioni vitali che guidano decisioni tempestive, essenziali per garantire la massima soddisfazione dei clienti e ridurre il churn dei clienti. Tradizionalmente, l’estrazione dei dati dai documenti è manuale, rendendola lenta, soggetta a errori, costosa e difficile da scalare. Spesso comporta il lavoro manuale che toglie tempo dalle attività critiche. Sebbene il settore sia stato in grado di raggiungere un certo livello di automazione tramite strumenti OCR tradizionali, questi metodi si sono rivelati fragili, costosi da mantenere e aumentano il debito tecnico. Con l’Intelligent Document Processing (IDP) basata sull’intelligenza artificiale (AI), il compito di estrarre dati da grandi quantità di documenti con tipi e strutture diverse diventa efficiente e accurato. Ciò consente decisioni aziendali tempestive e di alta qualità, riducendo le spese complessive.

Inoltre, l’IA generativa con i Large Language Models (LLM) sta aggiungendo potenti funzionalità alle soluzioni IDP, colmando spesso le lacune che un tempo esistevano anche con modelli di apprendimento automatico altamente addestrati. In questo articolo, discuterò brevemente le varie fasi dell’IDP e come l’IA generativa viene utilizzata per potenziare i carichi di lavoro esistenti dell’IDP o sviluppare nuovi carichi di lavoro dell’IDP.

Fasi dell’Elaborazione Intelligente dei Documenti

A livello generale, un flusso di lavoro standard dell’IDP consiste in quattro fasi: Archiviazione dei Documenti, seguita da Classificazione dei Documenti, Estrazione ed Arricchimento. È importante notare che non tutti i casi d’uso prevedono l’implementazione di tutte queste fasi, ma i casi d’uso più comuni sono una combinazione di più di una di queste fasi, con le fasi di classificazione dei documenti ed estrazione dei documenti tra le più popolari. Il diagramma seguente mostra come visualizziamo queste fasi dell’IDP. In questo articolo, ci concentreremo principalmente sulla classificazione dei documenti e sulle fasi di estrazione e sugli elementi e meccanismi di AI coinvolti. Per ciascuna di queste fasi dell’IDP, discuteremo brevemente l’importanza della fase e approfondiremo ulteriormente l’implementazione con AI generativa e apprendimento automatico. Discuteremo alcuni dei servizi di AI basati su cloud come Amazon Comprehend, Amazon Textract e modelli LLM tramite Amazon Bedrock. Discuteremo anche i dettagli di implementazione con la popolare libreria open-source LangChain Python.

Figura 1: Fasi dell’Elaborazione Intelligente dei Documenti

Classificazione dei Documenti

Una sfida comune nel trattare grandi quantità di documenti è identificare i documenti, suddividerli in categorie e quindi elaborarli ulteriormente. Questo è tradizionalmente un processo basato su umani o euristici, ma man mano che il volume dei documenti aumenta, questi metodi diventano colli di bottiglia dei processi aziendali e dei risultati. L’idea di base di questa fase è automatizzare la categorizzazione o classificazione utilizzando l’IA. In questa fase, i documenti altrimenti sconosciuti o che possono essere ordinatamente suddivisi in categorie distintive vengono classificati ed etichettati in modo automatizzato utilizzando l’IA. Per la classificazione dei documenti, utilizziamo modelli di classificatori personalizzati di Amazon Comprehend.

EVENTO – ODSC West 2023

Conferenza In-Person e Virtuale

30 ottobre – 2 novembre

Unisciti a noi per una profonda immersione nelle ultime tendenze, strumenti e tecniche di data science e AI, dai LLM all’analisi dei dati e dall’apprendimento automatico all’IA responsabile.

Con Amazon Comprehend otteniamo la possibilità di addestrare il nostro modello di classificazione dei documenti personalizzato che è specificamente creato per identificare i documenti nel tuo caso di utilizzo. Il modello tiene conto della struttura del documento e del suo contenuto (testo) per eseguire la classificazione dei documenti. È possibile addestrare un singolo modello per eseguire la classificazione dei documenti per un massimo di 1000 classi diverse e i documenti possono essere in formato PDF, JPG, PNG, DOCX o TXT. I documenti possono essere singole pagine o documenti multipagina. Per i documenti multipagina, il modello fornisce la classe del documento a livello di pagina insieme ai punteggi di fiducia.

La classificazione dei documenti con LLM è un’altra tecnica emergente che le organizzazioni possono adottare per migliorare il loro processo di classificazione. Questo è utile quando nel processo compaiono documenti più recenti, con i quali i modelli non sono stati addestrati. È anche utile quando un modello di classificazione addestrato esistente classifica un documento con una precisione estremamente bassa. Questa è una situazione molto comune nei carichi di lavoro del machine learning, poiché i processi aziendali evolvono. Ecco come potrebbe apparire un’implementazione possibile della classificazione dei documenti con il modello Amazon Bedrock e Anthropic Claude-v1. Utilizziamo le capacità di estrazione dei documenti di Amazon Textract con LangChain per ottenere il testo dal documento e quindi utilizziamo l’elaborazione delle prompt per identificare la possibile categoria del documento. LangChain utilizza l’API DetectDocumentText di Amazon Textract per estrarre il testo da documenti stampati, scannerizzati o scritti a mano.

Figura 2: Classificazione a basso punteggio instradata a LLM per la classificazione

 

```from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/document.png")document = loader.load()template = """Dato un elenco di classi, classifica il documento in una di queste classi. Ometti qualsiasi parte introduttiva e fornisce solo il nome della classe.<classi>FATTURA, ESTRATTO_CONTO, PIANO_SANITARIO, RICETTA</classi><documento>{doc_text}</documento><classificazione>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)class_name = llm_chain.run(document[0].page_content)print(f"Il documento fornito è = {class_name}")—-Il documento fornito è = PIANO_SANITARIO```

Nota che qui stiamo utilizzando il modello anthropic.claude-v1 che ha una finestra di contesto dei token di 100.000 token. Questa azione può essere eseguita anche con il modello Anthropic Claude v2, che ha anch’esso una finestra di contesto dei token di 100.000, tuttavia il costo può variare notevolmente a seconda del modello scelto. In generale, i modelli Anthropic Claude Instant e Claude v1 sono eccellenti modelli multiuso e sono adatti per un gran numero di casi d’uso. Il seguente codice dimostra un meccanismo di tracciamento che mostra il conteggio dei token sia del prompt di input che del testo generato.

```prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")num_in_tokens = bedrock_llm.get_num_tokens(document[0].page_content)print (f"Il nostro prompt ha {num_in_tokens} token \n\n=========================")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)class_name = llm_chain.run(document[0].page_content)num_out_tokens = bedrock_llm.get_num_tokens(class_name)print (f"Il nostro output ha {num_out_tokens} token \n\n=========================")print (f"Totale token = {num_in_tokens + num_out_tokens}")—-Il nostro prompt ha 1295 token =========================Il nostro output ha 9 token =========================Totale token = 1304```

Estrazioni di Documenti

L’estrazione di documenti è forse la fase più popolare del flusso di lavoro IDP (Intelligent Document Processing). La maggior parte dei casi d’uso che incontro nel mio lavoro quotidiano con l’IDP è fortemente orientata verso meccanismi diversi per estrarre informazioni di vario tipo da una vasta gamma di documenti. I documenti vanno da certificati di nascita, atti ipotecari, moduli fiscali, curriculum vitae, rapporti di studi medici, documenti assicurativi sanitari, documenti di identità (passaporti, patenti, ecc.), materiali di marketing, ritagli di giornale e la lista continua. Come puoi immaginare, i formati e i tipi di documenti variano enormemente da caso d’uso a caso d’uso e molte volte all’interno di uno stesso caso d’uso. Pertanto, esistono diversi modi per estrarre informazioni da tutti questi tipi di documenti diversi. Tuttavia, è importante tenere presente che non esiste un modello di intelligenza artificiale “one size fits all” in grado di estrarre tutte queste informazioni dai documenti nel formato desiderato, almeno per il momento. Ma la buona notizia è che esistono molti modelli dedicati così come modelli multiuso che possono aiutarci a raggiungere i nostri obiettivi di estrazione di documenti.

Amazon Textract fornisce una serie di funzioni ad uso generale come l’estrazione di moduli, l’estrazione di tabelle, le query e il layout. Queste funzioni funzionano su qualsiasi tipo di documento e sono ottime per l’estrazione generica di documenti come l’estrazione da moduli o documenti contenenti dati tabulari. Amazon Textract fornisce anche alcuni modelli di intelligenza artificiale appositamente creati come AnalyzeID per il riconoscimento e l’estrazione da documenti di identità US, AnalyzeExpense che può leggere ed estrarre fatture e ricevute, e AnalyzeLending che è in grado di identificare ed estrarre documenti di mutui e prestiti. Puoi leggere di più su come funzionano questi modelli nella documentazione collegata sopra, ma in questa sezione ci concentreremo sulle tecniche di estrazione di documenti basate su LLM. In particolare, ci concentreremo sui due usi più comuni: l’estrazione di entità chiave-valore normalizzate basate su template e la Q&A dei documenti con grandi modelli di lingua.

Estrazioni normalizzate basate su template

In quasi tutti i casi d’uso di IDP, i dati estratti vengono eventualmente inviati a un sistema secondario per ulteriori elaborazioni o analisi. Diventa sempre più importante avere un output normalizzato da estrazioni basate su intelligenza artificiale in modo che il meccanismo di consumo e il codice di integrazione siano facili da mantenere, più affidabili e meno fragili. Un set di chiavi deterministiche può fare molta differenza nel codice di integrazione, rispetto a chiavi non deterministiche. Ad esempio, considera un caso d’uso che coinvolge l’estrazione del nome, cognome e data di nascita di un candidato. Ma i documenti coinvolti possono o meno avere questi nomi chiaramente etichettati come “Nome”, “Cognome”, “Data di nascita” e possono essere scritti in modo diverso.

Elaborazione intelligente di documenti con servizi AI AWS e Amazon BedrockFigura 3: Output effettivo dell’estrazione di documenti vs. output desiderato

Nota la differenza tra l’output effettivo e l’output desiderato. L’output desiderato segue uno schema più deterministico che rende la nostra logica di post-elaborazione molto più semplice, facile da mantenere e meno costosa da sviluppare. Questo è possibile tramite un grande modello di lingua come viene dimostrato nel codice qui sotto.

```from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/document.png")document = loader.load()output_template= {    "first_name":{ "type": "string", "description": "Il nome del candidato" },    "last_name":{ "type": "string", "description": "Il cognome del candidato" },    "dob":{ "type": "string", "description": "La data di nascita del candidato" },}template = """Sei un assistente disponibile. Estrarre i seguenti dettagli dal documento e formattare l'output come JSON utilizzando le chiavi. Omettere qualsiasi testo preliminare e generare la risposta finale.<dettagli>{details}</dettagli><chiavi>{keys}</chiavi><documento>{doc_text}</documento><risposta_finale>"""details = "\n".join([f"{key}: {value['description']}" for key, value in output_template.items()])keys = "\n".join([f"{key}" for key, value in output_template.items()])prompt = PromptTemplate(template=template,                         input_variables=["details", "keys", "doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v1")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)output = llm_chain.run({"doc_text": full_text, "details": details, "keys": keys})print(output)—-{  "first_name": "John",  "last_name": "Doe",  "dob": "26-GIU-1981"}```

In questo caso, semplicemente creando la nostra richiesta con istruzioni chiare per l’LLM siamo riusciti non solo a estrarre le entità, ma anche a generare l’output in un formato conforme al nostro schema. Questo è significativo dal punto di vista della post-elaborazione ora che il nostro codice di integrazione è molto più semplice e deterministico. Oltre a ciò, LangChain fornisce anche un modo integrato per creare queste istruzioni in modo più modulare. Ecco come appare il codice.

“`from langchain.output_parsers import ResponseSchema
from langchain.output_parsers import StructuredOutputParser

response_schems = list()
for key, value in output_template.items():
schema = ResponseSchema(name=key,
description=value[‘description’],
type=value[‘type’])
response_schems.append(schema)

output_parser = StructuredOutputParser.from_response_schemas(response_schems)
format_instructions= output_parser.get_format_instructions()
print(format_instructions)

—-L’output dovrebbe essere uno snippet di codice markdown formattato secondo lo schema seguente, inclusi ““`json” e ““`quot; iniziali e finali:
“`json
{“first_name”: string // Nome del richiedente
“provider_id”: string // Cognome del richiedente
“dob”: string // Data di nascita del richiedente}
“`
“`

Successivamente possiamo semplicemente utilizzare questa istruzione di formattazione pre-generata (nella variabile format_instruction) con la nostra catena LLM come segue.

“`template = “””You are a helpful assistant. Please extract the following details from the document and strictly follow the instructions described in the format instructions to format the output. Skip any preamble text and generate the final answer.

{details}

{format_instructions}{doc_text}”””llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)output = llm_chain.run({“doc_text”: full_text,
“details”: details,
“format_instructions”: format_instructions})parsed_output= output_parser.parse(output)parsed_output“`

Domanda e risposta sui documenti con generazione potenziata tramite recupero (RAG)

Il secondo approccio più comune per estrarre informazioni dai documenti consiste nell’utilizzare un metodo di domanda e risposta simile a una chat. Questo metodo prevede di sollecitare l’LLM con il contenuto del documento e una domanda, nella speranza di ottenere una risposta dal documento stesso (se disponibile). Tuttavia, ci sono un paio di problemi che richiedono una mitigazione proattiva: la prevenzione delle allucinazioni del modello e il limite della finestra del contesto dei token.

I modelli di lingua pre-addestrati di grandi dimensioni mostrano risultati all’avanguardia su molte attività di NLP grazie alla conoscenza fattuale memorizzata. Tuttavia, la loro precisione nella manipolazione delle conoscenze è limitata, il che comporta prestazioni subottimali nelle attività intensive di conoscenza. Per mitigare questo problema, è stato sviluppato un approccio noto come Generazione potenziata tramite recupero (Retrieval Augmented Generation – RAG) che si è rivelato molto utile. Questo metodo non solo aiuta l’LLM a rispondere alla domanda in modo preciso e a rimanere all’interno del contesto del documento, ma impedisce anche la comparsa di allucinazioni e si attiene ai limiti del contesto dei token per documenti di grandi dimensioni. L’idea del RAG è quella di raccogliere solo le parti rilevanti del documento che sono semanticamente più vicine alla domanda posta. Ciò viene ottenuto suddividendo il contenuto del documento in una serie di parti più piccole, generando vettori di embedding di esse e memorizzando quindi gli embedding in un database vettoriale. Il database vettoriale può quindi eseguire una ricerca di similarità o una ricerca di marginalità massima (MMR) per raccogliere le parti più importanti e rilevanti del documento. Una volta ottenute queste parti rilevanti, viene creato un contesto completo insieme alla domanda, con un certo ingegneraggio della traccia per ottenere la risposta più accurata possibile dal modello.

Elaborazione intelligente dei documenti con i servizi AI di AWS e Amazon BedrockFigura 4: Generazione potenziata tramite recupero con embedding dei documenti e database vettoriale

Nella figura precedente, utilizziamo il modello Titan Embeddings G1 – Text tramite Amazon Bedrock per generare embedding dei segmenti di testo. Gran parte del meccanismo RAG può essere eseguito con moduli incorporati utili della libreria LangChain, inclusa la suddivisione in segmenti, la generazione di embedding e il caricamento in un database vettoriale a tua scelta, quindi eseguire il Q&A basato su RAG con il contenuto del documento utilizzando il database vettoriale come recuperatore. Il seguente codice fornisce una panoramica di una possibile implementazione di tale meccanismo utilizzando la catena di RetrievalQA di LangChain che esegue la ricerca di pertinenza, la costruzione del contesto, l’aggiunta della traccia utilizzando internamente il contesto. In questo esempio utilizziamo il database vettoriale [FAISS](https://ai.meta.com/tools/faiss/#:~:text=FAISS%20(Facebook%20AI%20Similarity%20Search,more%20scalable%20similarity%20search%20functions.).

```from langchain.embeddings import BedrockEmbeddingsfrom langchain.vectorstores import FAISSfrom langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader(f"./samples/document.png")document = loader.load()text_splitter = RecursiveCharacterTextSplitter(chunk_size=400,                                               separators=["\n\n", "\n", ".", "!", "?", ",", " ", ""],                                               chunk_overlap=0)texts = text_splitter.split_documents(document)embeddings = BedrockEmbeddings(client=bedrock,                               model_id="amazon.titan-embed-text-v1")vector_db = FAISS.from_documents(documents=texts,                                  embedding=embeddings)retriever = vector_db.as_retriever(search_type='mmr',                                    search_kwargs={"k": 3})template = """Rispondi alla domanda il più sinceramente possibile utilizzando solo il testo fornito, e se la risposta non è contenuta nel testo, rispondi "Non lo so". Salta qualsiasi testo introduttivo e ragionamento e fornisci solo la risposta.<text>{document}</text><question>{question}</question><answer>"""prompt = PromptTemplate(template=template,                         input_variables=["document","question"])bedrock_llm = Bedrock(client=bedrock,                       model_id="anthropic.claude-v1")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)answer = llm_chain.run(document=full_context,                        question="Qual è l'importo fuori tasca per persona presso la farmacia?")print(f"La risposta è = {answer.strip()}")—-La risposta è = $6,000```

In questo esempio, abbiamo estratto un documento con Amazon Textract ottenendo il testo per pagina. Successivamente, abbiamo diviso tutte le pagine del documento in frammenti di 400 caratteri. In seguito, abbiamo generato gli embedding vettoriali dei frammenti e li abbiamo memorizzati in un archivio vettoriale FAISS e utilizzato tale archivio vettoriale come recuperatore per il nostro meccanismo di domande e risposte basato su RAG. Fare riferimento a questo repository di GitHub per un set completo di Python Notebooks che spiegano il processo passo dopo passo in dettaglio.

Conclusione

In questo articolo, abbiamo discusso le varie fasi dell’elaborazione intelligente dei documenti ed esplorato alcuni dei modi in cui l’IA generativa con Amazon Bedrock viene utilizzata per migliorare un flusso di lavoro di IDP. Ci sono altri tipi di estrazioni che non abbiamo trattato in questo articolo, come la sintesi, la Q&A delle tabelle autonome, la standardizzazione, ecc. È possibile approfondire ognuno di questi tipi di estrazioni utilizzando i notebook Python nel repository GitHub sopra menzionato. Se si sta già utilizzando un flusso di lavoro di IDP per il proprio caso d’uso, l’IA generativa offre un intero nuovo mondo di possibilità con le capacità LLM di migliorare il flusso di lavoro. Se si è nella fase decisionale di un flusso di lavoro basato su IDP per il proprio caso d’uso, vale la pena esplorare tutti i diversi modi in cui l’IA generativa può aggiungere valore.

Informazioni sull’autore

Anjan Biswas è un Senior AI Specialist Solutions Architect presso Amazon Web Services (AWS). Anjan è specializzato in Computer Vision, NLP e tecnologie di intelligenza artificiale generative e trascorre gran parte del suo tempo lavorando su casi d’uso di Intelligent Document Processing (IDP). Ha oltre 16 anni di esperienza nella costruzione di sistemi enterprise su larga scala nei settori supply-chain, retail, tecnologia e sanità, ed è appassionato di data science e machine learning.