paint-brush
Comment utiliser les services AI et PDF pour automatiser les résumés de documentspar@raymondcamden
5,329 lectures
5,329 lectures

Comment utiliser les services AI et PDF pour automatiser les résumés de documents

par Raymond Camden8m2024/02/04
Read on Terminal Reader

Trop long; Pour lire

Donc le texte, les polices, les couleurs, la position, etc. Il peut également trouver des images et des données tabulaires, ce qui conduit à des cas d'utilisation assez puissants. (Pour un bon exemple, consultez mon article de blog dans lequel je parcoure plusieurs revues scientifiques pour collecter et regrouper des données astronomiques et créer des rapports.) Pour cette démo, nous n’avons littéralement besoin que du texte. Pour cela, j'utiliserai les API REST. Le « flux » pour presque tous les aspects des services PDF disponibles est :
featured image - Comment utiliser les services AI et PDF pour automatiser les résumés de documents
Raymond Camden HackerNoon profile picture


J'ai découvert Diffbot pour la première fois en 2021 lorsque j'ai créé une démo de leurs API pour le blog Adobe Developer ( « Traitement du langage naturel, Adobe PDF Extract et Deep PDF Intelligence » ).


À cette époque, j'ai été impressionné par la simplicité de l'API de Diffbot et par la rapidité avec laquelle elle répondait. Je n'avais pas regardé leur API depuis un moment, mais il y a quelques jours, ils ont annoncé un nouveau support pour résumer du texte. J'ai pensé que ce serait une bonne chose à combiner avec l' API Adobe PDF Extract . Voici ce que j'ai trouvé.


Tout d’abord, si vous voulez essayer vous-même, vous aurez besoin de :


  • Identifiants Adobe PDF Services . Celles-ci sont gratuites et vous bénéficiez de 500 transactions gratuites par mois. Pour ceux qui ne le savent peut-être pas, je travaille pour Adobe et c'est l'un des produits que je couvre.


  • Identifiants Diffbot. Ils offrent un essai gratuit de deux semaines, mais pas de niveau gratuit. Cela étant dit, j'ai dû les contacter à plusieurs reprises lors de la création de trucs, et ils m'ont apporté un très grand soutien, donc je pense vraiment qu'ils valent la peine d'être vérifiés.


Très bien, regardons comment un flux récapitulatif pourrait fonctionner.

Première étape - Extraire le texte

L' API Extract (désolé, "Adobe PDF Extract API", attendez, c'est mon blog, je peux raccourcir les choses !) est assez puissante. Il utilise l'IA pour analyser intelligemment un PDF afin de trouver correctement chaque détail d'élément dans le document.


Donc le texte, les polices, les couleurs, la position, etc. Il peut également trouver des images et des données tabulaires, ce qui conduit à des cas d'utilisation assez puissants. (Pour un bon exemple, consultez mon article de blog dans lequel je parcoure plusieurs revues scientifiques pour collecter et regrouper des données astronomiques et créer des rapports.)


Pour cette démo, nous n’avons littéralement besoin que du texte. Pour cela, j'utiliserai les API REST. Le « flux » pour presque tous les aspects des services PDF disponibles est :


  • Échanger des informations d'identification contre un jeton d'accès


  • Demander de télécharger un fichier en saisie (dans ce cas, un PDF à extraire)


  • Téléchargez le document


  • Commencez le travail


  • Sondage à compléter


  • Téléchargez les morceaux


Notez qu'il existe également des SDK que vous pouvez utiliser, mais j'ai trouvé nos API REST si simples que je viens d'atteindre directement les points de terminaison. Voici le script que j'ai écrit pour effectuer le processus d'extraction. C'est essentiellement tout ce que j'ai dit ci-dessus et pointant vers un PDF source dans mon système de fichiers 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, j'espère que vous êtes toujours en train de lire. En général, j'essaie d'éviter de publier des blocs de code géants comme celui-là, mais si vous vous concentrez sur les lignes à la fin, vous verrez que je frappe simplement des fonctions utilitaires qui font ce que j'ai décrit dans le flux ci-dessus. Authentifiez-vous, demandez à télécharger un PDF, lancez un travail, vérifiez-le et téléchargez le résultat.


Une remarque que j'ajouterai. Extract renvoie un fichier zip contenant un jeu de résultats JSON et éventuellement des tableaux et des images. Une chose intéressante à propos de l'API REST est que je peux accéder directement au JSON et simplement le stocker.


Le résultat JSON peut être assez énorme. Pour mon PDF source (un document de sécurité Adobe incroyablement ennuyeux) de trois pages, le JSON résultant compte 4 560 lignes. Vous pouvez trouver mon PDF source ici et la sortie brute d'Extract ici .


Au lieu de mettre les 4,5 000 lignes ici, permettez-moi de montrer un extrait - deux éléments uniques trouvés par l'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" } },

Dans l'exemple ci-dessus, vous pouvez voir que le premier élément est textuel et contient une propriété Text , tandis que le second est une figure. Pour ma démo, j'ai juste besoin d'utiliser la propriété Text lorsqu'elle existe. Voyons cela en action.

Deuxième étape - Créer le résumé

J'ai mentionné plus tôt que l'API Diffbot était assez simple à utiliser. Permettez-moi de le démontrer.


Tout d'abord, je vais configurer quelques variables et lire le JSON que j'ai obtenu lors de la première étape. Pour être clair, je pourrais tout faire en un seul processus, mais cela ne sert vraiment à rien d’exécuter Extract plus d’une fois. Ce qui est cool, c'est que je pourrais en fait faire plusieurs appels sur le résultat.


À titre d'exemple, une autre fonctionnalité intéressante de Diffbot est d'obtenir des entités à partir d'un texte, c'est-à-dire de quoi parle un document (personnes, lieux, etc.). Quoi qu'il en soit, voici le début :


 /* 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}.`);


Ensuite, je dois analyser le texte du résultat de l'extraction :


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


Ensuite, je crée une requête HTTP à Diffbot. Consultez leurs documents pour plus d’informations.


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


Et c'est tout. Comme dernière étape, je l'affiche simplement :


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


Étant donné le PDF source, le résultat final est :


 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.


Mon PDF de trois pages est désormais un simple paragraphe. Vous pouvez imaginer à quel point cela serait utile pour les organisations possédant des millions de documents. Combinez cela avec d'autres services (comme la fonctionnalité d'entités que j'ai mentionnée précédemment) et cela facilite grandement le travail avec de grandes bibliothèques.

Essayez-le !

Si vous souhaitez vérifier cela vous-même, vous pouvez récupérer tout le code ici : https://github.com/cfjedimaster/document-services-demos/tree/main/random_demos/extract_diffbot_summary . Comme je l'ai dit, tout ici peut être testé gratuitement, alors essayez-le et dites-moi ce que vous en pensez dans un commentaire ci-dessous.