我第一次发现Diffbot是在 2021 年,当时我为 Adobe 开发者博客( “自然语言处理、Adobe PDF Extract 和 Deep PDF Intelligence” )构建了他们的 API 演示。
当时,我对 Diffbot 的 API 的简单性和响应速度印象深刻。我有一段时间没有查看他们的 API,但几天前,他们宣布了对文本摘要的新支持。我认为这与Adobe PDF Extract API结合起来会是一件很棒的事情。这是我发现的。
首先,如果您想自己尝试一下,您需要:
好吧,让我们看看摘要流程是如何工作的。
Extract API (抱歉,“Adobe PDF Extract API”,等等,这是我的博客,我可以缩短内容!)非常强大。它使用 AI 智能解析 PDF,以正确找到文档中的每个元素详细信息。
文本、字体、颜色、位置等等。它还可以查找图像和表格数据,这导致了一些非常强大的用例。 (有关这方面的一个很好的例子,请参阅我的博客文章,其中我扫描了多种科学期刊来收集和汇总天文数据并创建报告。)
对于这个演示,我们实际上只需要文本。为此,我将使用 REST API。可用 PDF 服务的几乎所有方面的“流程”是:
请注意,您还可以使用 SDK,但我发现我们的 REST API 非常简单,我只需直接访问端点即可。这是我编写的用于执行提取过程的脚本。这基本上就是我上面所说的一切,并指向我本地文件系统中的源 PDF。
/* 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.');
好吧,希望你还在阅读。一般来说,我会尽量避免发布这样的巨大代码块,但如果您关注最后的行,您会发现我只是点击了执行上面流程中描述的功能的实用程序函数。进行身份验证、要求上传 PDF、启动作业、检查并下载结果。
我要补充一点。 Extract 返回一个 zip 文件,其中包含 JSON 结果集以及可选的表格和图像。 REST API 的一大好处是我可以直接获取 JSON 并存储它。
JSON 结果可能非常巨大。对于我的三页源 PDF(一份极其无聊的 Adobe 安全文档),生成的 JSON 长度为 4560 行。您可以在这里找到我的 PDF 源文件,以及Extract的原始输出。
让我展示一个片段 - API 找到的两个独特元素,而不是将所有 4.5k 行放在这里:
{ "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" } },
在上面的示例中,您可以看到第一个元素是文本并包含Text
属性,而第二个元素是图形。对于我的演示,我只需要使用Text
属性(如果存在)。让我们看看实际情况。
我之前提到过 Diffbot API 使用起来相当简单。让我证明一下。
首先,我将设置一些变量并读取从第一步获得的 JSON。需要明确的是,我可以在一个进程中完成所有操作,但多次运行 Extract 确实没有意义。很酷的是 - 我实际上可以对结果进行多次调用。
例如,Diffbot 的另一项很酷的功能是从文本中获取实体,即文档所谈论的内容(人物、地点等)。无论如何,这是开始:
/* 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}.`);
接下来,我需要从提取结果中解析出文本:
let text = data.elements.reduce((text, el) => { if(el.Text) text += el.Text + '\n'; return text; },'');
接下来,我向 Diffbot 发送 HTTP 请求。检查他们的文档以获取更多信息。
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();
就是这样。作为最后一步,我简单地输出它:
console.log(`Summary of PDF:\n${result[0].summary}`);
给定源PDF,最终结果为:
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.
我的三页 PDF 现在变成了一个简单的段落。您可以想象这对于拥有数百万文档的组织来说有多么有用。将此与其他服务(如我之前提到的实体功能)结合起来,可以使大型库的使用变得更加容易。
如果您想自己检查一下,可以在此处获取所有代码:https: //github.com/cfjedimaster/document-services-demos/tree/main/random_demos/extract_diffbot_summary 。正如我所说,这里的所有内容都可以免费测试,因此请尝试一下,并在下面的评论中告诉我您的想法。