paint-brush
Como usar serviços de IA e PDF para automatizar resumos de documentospor@raymondcamden
5,329 leituras
5,329 leituras

Como usar serviços de IA e PDF para automatizar resumos de documentos

por Raymond Camden8m2024/02/04
Read on Terminal Reader

Muito longo; Para ler

Portanto, texto, fontes, cores, posição e assim por diante. Ele também pode encontrar imagens e dados tabulares, o que leva a alguns casos de uso bastante poderosos. (Para um bom exemplo disso, veja minha postagem no blog, onde examino várias revistas científicas para coletar e agregar dados astronômicos e criar relatórios.) Para esta demonstração, precisamos literalmente apenas do texto. Para isso, farei uso das APIs REST. O “fluxo” para quase todos os aspectos dos serviços PDF disponíveis são:
featured image - Como usar serviços de IA e PDF para automatizar resumos de documentos
Raymond Camden HackerNoon profile picture


Eu descobri o Diffbot pela primeira vez em 2021, quando criei uma demonstração de suas APIs para o blog Adobe Developer ( "Natural Language Processing, Adobe PDF Extract e Deep PDF Intelligence" ).


Naquela época, fiquei impressionado com a facilidade da API do Diffbot e também com a rapidez com que ela respondeu. Fazia algum tempo que eu não via a API deles, mas há alguns dias eles anunciaram um novo suporte para resumir texto. Achei que seria ótimo combinar isso com a API Adobe PDF Extract . Aqui está o que eu encontrei.


Em primeiro lugar, se quiser experimentar você mesmo, você precisará de:


  • Credenciais dos serviços Adobe PDF. Eles são gratuitos e você recebe 500 transações por mês gratuitamente. Para quem talvez não saiba, trabalho para a Adobe e este é um dos produtos que abordo.


  • Credenciais do Diffbot. Eles oferecem um teste gratuito de duas semanas, mas nenhum nível gratuito. Dito isso, tive que contatá-los algumas vezes durante a construção de coisas, e eles me deram um ótimo suporte, então definitivamente acho que vale a pena conferir.


Tudo bem, vamos ver como um fluxo de resumo pode funcionar.

Passo Um – Extraia o Texto

A API Extract (desculpe, a "API Adobe PDF Extract", espere, este é o meu blog, posso encurtar as coisas!) É muito poderosa. Ele usa IA para analisar um PDF de forma inteligente e encontrar corretamente todos os detalhes dos elementos do documento.


Portanto, texto, fontes, cores, posição e assim por diante. Ele também pode encontrar imagens e dados tabulares, o que leva a alguns casos de uso bastante poderosos. (Para um bom exemplo disso, veja minha postagem no blog , onde examino várias revistas científicas para coletar e agregar dados astronômicos e criar relatórios.)


Para esta demonstração, precisamos literalmente apenas do texto. Para isso, farei uso das APIs REST. O “fluxo” para quase todos os aspectos dos serviços PDF disponíveis são:


  • Trocar credenciais por um token de acesso


  • Peça para fazer upload de um arquivo para entrada (neste caso, um PDF a ser extraído)


  • Carregar o documento


  • Dê o pontapé inicial no trabalho


  • Enquete para conclusão


  • Baixe os bits


Observe que também existem SDKs que você pode usar, mas achei nossas APIs REST tão simples que acabei de acessar os endpoints diretamente. Aqui está o script que escrevi para fazer o processo de extração. É basicamente tudo o que eu disse acima e apontando para um PDF de origem em meu sistema de arquivos local.


 /* This demo is a two step process. This file, step one, handles extracting and storing the JSON from a PDF. */ import 'dotenv/config'; import fs from 'fs'; import { Readable } from 'stream'; import { finished } from 'stream/promises'; const SOURCE_PDF = '../../source_pdfs/boring_adobe_security_doc.pdf'; const REST_API = "https://pdf-services.adobe.io/"; const CLIENT_ID = process.env.CLIENT_ID; const CLIENT_SECRET = process.env.CLIENT_SECRET; async function delay(x) { return new Promise(resolve => { setTimeout(() => resolve(), x); }); } async function getAccessToken(id, secret) { const params = new URLSearchParams(); params.append('client_id', id); params.append('client_secret', secret); let resp = await fetch('https://pdf-services-ue1.adobe.io/token', { method: 'POST', headers: { 'Content-Type':'application/x-www-form-urlencoded' }, body:params }); let data = await resp.json(); return data.access_token; } async function getUploadData(mediaType, token, clientId) { let body = { 'mediaType': mediaType }; body = JSON.stringify(body); let req = await fetch(REST_API+'assets', { method:'post', headers: { 'X-API-Key':clientId, 'Authorization':`Bearer ${token}`, 'Content-Type':'application/json' }, body: body }); let data = await req.json(); return data; } async function uploadFile(url, filePath, mediaType) { let stream = fs.createReadStream(filePath); let stats = fs.statSync(filePath); let fileSizeInBytes = stats.size; let upload = await fetch(url, { method:'PUT', redirect:'follow', headers: { 'Content-Type':mediaType, 'Content-Length':fileSizeInBytes }, duplex:'half', body:stream }); if(upload.status === 200) return; else { throw('Bad result, handle later.'); } } async function pollJob(url, token, clientId) { let status = null; let asset; while(status !== 'done') { let req = await fetch(url, { method:'GET', headers: { 'X-API-Key':clientId, 'Authorization':`Bearer ${token}`, } }); let res = await req.json(); status = res.status; if(status === 'done') { asset = res; } else { await delay(2000); } } return asset; } async function downloadFile(url, filePath) { let res = await fetch(url); const body = Readable.fromWeb(res.body); const download_write_stream = fs.createWriteStream(filePath); return await finished(body.pipe(download_write_stream)); } async function extractJob(asset, token, clientId) { let body = { 'assetID': asset.assetID } let resp = await fetch(REST_API + 'operation/extractpdf', { method: 'POST', headers: { 'Authorization':`Bearer ${token}`, 'X-API-KEY':clientId, 'Content-Type':'application/json' }, body:JSON.stringify(body) }); return resp.headers.get('location'); } let accessToken = await getAccessToken(CLIENT_ID, CLIENT_SECRET); console.log('Got our access token.'); let uploadedAsset = await getUploadData('application/pdf', accessToken, CLIENT_ID); await uploadFile(uploadedAsset.uploadUri, SOURCE_PDF, 'application/pdf'); console.log('Source PDF Uploaded.'); let job = await extractJob(uploadedAsset, accessToken, CLIENT_ID); console.log('Job created. Now to poll it.'); let result = await pollJob(job, accessToken, CLIENT_ID); console.log('Job is done.'); await downloadFile(result.content.downloadUri, 'extract.json'); console.log('All done.');

Ok, espero que você ainda esteja lendo. Em geral, tento evitar postar blocos gigantes de código como esse, mas se você focar nas linhas do final, verá que estou apenas acessando funções utilitárias que fazem o que descrevi no fluxo acima. Autentique, peça para fazer upload de um PDF, inicie um trabalho, verifique e baixe o resultado.


Uma observação que acrescentarei. Extract retorna um arquivo zip contendo um conjunto de resultados JSON e, opcionalmente, tabelas e imagens. Uma coisa legal sobre a API REST é que posso acessar diretamente o JSON e simplesmente armazená-lo.


O resultado JSON pode ser bastante grande. Para meu PDF de origem (um documento de segurança incrivelmente chato da Adobe) de três páginas, o JSON resultante tem 4.560 linhas. Você pode encontrar meu PDF de origem aqui e a saída bruta do Extract aqui .


Em vez de colocar todas as 4,5 mil linhas aqui, deixe-me mostrar um trecho - dois elementos exclusivos encontrados pela API:


 { "Bounds": [ 44.62139892578125, 756.9429931640625, 245.0037841796875, 766.3184967041016 ], "Font": { "alt_family_name": "* Arial", "embedded": true, "encoding": "Identity-H", "family_name": "* Arial", "font_type": "CIDFontType0", "italic": false, "monospaced": false, "name": "*Arial-6539", "subset": false, "weight": 400 }, "HasClip": false, "Lang": "en", "Page": 0, "Path": "//Document/Sect/P", "Text": "Adobe Vendor Security Review Program White Paper ", "TextSize": 8.5, "attributes": { "SpaceAfter": 18 } }, { "Bounds": [ 0.0, 0.0, 630.0, 820.7799987792969 ], "ClipBounds": [ 548.72802734375, 739.1929931640625, 602.5444488525391, 820.7799987792969 ], "Page": 0, "Path": "//Document/Sect/Figure", "attributes": { "BBox": [ 548.9779999999737, 739.4429999999993, 587.61599999998, 790.920999999973 ], "Placement": "Block" } },

No exemplo acima, você pode ver que o primeiro elemento é textual e contém uma propriedade Text , enquanto o segundo é uma figura. Para minha demonstração, só preciso usar a propriedade Text quando ela existir. Vamos ver isso em ação.

Passo Dois – Crie o Resumo

Mencionei anteriormente que a API Diffbot era bastante simples de usar. Deixe-me demonstrar isso.


Primeiro, vou configurar algumas variáveis e ler o JSON que obtive na primeira etapa. Para ser claro, eu poderia fazer tudo em um processo, mas não faz sentido executar o Extract mais de uma vez. O que é legal é que eu poderia fazer várias chamadas com base no resultado.


Por exemplo, outro recurso interessante que o Diffbot possui é obter entidades de texto, ou seja, sobre o que um documento está falando (pessoas, lugares, etc). De qualquer forma, aqui está o começo:


 /* In this file, we take the result from our Extract operation and pass it to Diffbot */ import 'dotenv/config'; import fs from 'fs'; const DIFFBOT_KEY = process.env.DIFFBOT_KEY; const SOURCE_JSON = './extract.json'; const data = JSON.parse(fs.readFileSync(SOURCE_JSON, 'utf8')); console.log(`Read in source data from ${SOURCE_JSON}.`);


Em seguida, preciso analisar o texto do resultado da Extração:


 let text = data.elements.reduce((text, el) => { if(el.Text) text += el.Text + '\n'; return text; },'');


Em seguida, crio uma solicitação HTTP para o Diffbot. Verifique seus documentos para obter mais informações.


 let fields = 'summary'; let url = `https://nl.diffbot.com/v1/?fields=${fields}&token=${DIFFBOT_KEY}`; let body = [{ content:text, lang:'en', format:'plain text' }]; console.log('Passing text to Diffbot.'); let req = await fetch(url, { method:'POST', body:JSON.stringify(body), headers: { 'Content-Type':'application/json' } }); let result = await req.json();


E é isso. Como etapa final, simplesmente produzo:


 console.log(`Summary of PDF:\n${result[0].summary}`);


Dado o PDF de origem, o resultado final é:


 Adobe has a vendor security review program that evaluates vendors that collect, store, process, transmit, or dispose of Adobe data outside of Adobe-controlled physical offices or data center locations. The VSR program includes requirements for vendors to follow when handling sensitive data and assigns a risk level score to vendors based on their compliance with Adobe standards. If a vendor fails the VSR program, Adobe holds discussions with the business owner to understand the details of the vendor's security practices and determine whether or not to continue working with them.


Meu PDF de três páginas agora é um parágrafo simples. Você pode imaginar como isso seria útil para organizações com milhões de documentos. Combine isso com outros serviços (como o recurso de entidades que mencionei anteriormente) e isso torna muito mais fácil trabalhar com grandes bibliotecas.

Tente!

Se você quiser verificar isso sozinho, pode obter todo o código aqui: https://github.com/cfjedimaster/document-services-demos/tree/main/random_demos/extract_diffbot_summary . Como eu disse, tudo aqui pode ser testado gratuitamente, então experimente e deixe-me saber o que você achou em um comentário abaixo.