PDF document processing with Argilla and IBM Deep Search

🔍 使用 Argilla 和 IBM Deep Search 处理 PDF 文档

2023 年 5 月 18 日

Michele Dolfi (IBM), David Berenstein

当进行大规模文档处理并希望能够大规模连接非结构化数据时,IBM 的 Deep Search 是理想选择,并与 Argilla 完美集成,用于数据集的整理。

Deep Search 使用自然语言处理技术来摄取和分析海量数据——结构化和非结构化数据。研究人员可以比以往更快地提取、探索和建立联系。

开始结构化数据

在本示例中,我们将使用 Deep Search 转换文档的输出,在 Argilla 中填充数据集。这使得用户可以为多种目的注释文本段,例如文本分类、命名实体识别等,以及训练适合其目的的自定义模型。

首先,我们从文件 ../../ds-auth.json 中包含的凭据初始化 Deep Search 客户端。这可以使用 !deepsearch login --output ../../ds-auth.json 生成。更多详细信息请参阅文档

初始化 Argilla

即使你们中的大多数人可能都熟悉 Argilla 的设置,我们还是提供一个简短的回顾。设置您自己实例的最简单方法是使用 🤗 Hugging Face Space,文档请见 https://hugging-face.cn/docs/hub/spaces-sdks-docker-argilla,或使用任何其他 Argilla 部署方法,列表请见 https://docs.argilla.com.cn/en/latest/getting_started/installation/deployments/deployments.html

export ARGILLA_API_URL="" # for example https://<USER>-<NAME>.hf.spaceexport ARGILLA_API_KEY="" # for example "admin.apikey"

配置

为了简明扼要地概述此集成中使用的参数和包,下面的代码片段提供了集成的概述。

import osfrom pathlib import Path# Deep Search configurationCONFIG_FILE = Path("../../ds-auth.json")PROJ_KEY = "1234567890abcdefghijklmnopqrstvwyz123456"INPUT_FILE = Path("../../data/samples/2206.00785.pdf")# Argilla configurationARGILLA_API_URL = os.environ["ARGILLA_API_URL"]  # required env varARGILLA_API_KEY = os.environ["ARGILLA_API_KEY"]  # required env varARGILLA_DATASET = "deepsearch-documents"# TokenizationSPACY_MODEL = "en_core_web_sm"

现在下载 spaCy 模型,该模型将用于文本标记化。

!python -m spacy download {SPACY_MODEL}

导入所需的依赖项。

# Import standard dependenicesimport jsonimport tempfileimport typingfrom zipfile import ZipFile# IPython utilitiesfrom IPython.display import display, Markdown, HTML, display_html# Import the deepsearch-toolkitimport deepsearch as ds# Import specific to the exampleimport argilla as rgimport spacyfrom pydantic import BaseModel

最后,我们将定义一个 pydantic 模型,以确保我们可以将 Deep Search 文档部分映射到 Argilla 友好的结构。

class DocTextSegment(BaseModel):    page: int  # page number    idx: int  # index of text segment in the document    title: str  # title of the document    name: str  # flavour of text segment    type: str  # type of text segment    text: str  # content of the text segment    text_classification: typing.Any = (        None  # this could be used to store predictions of text classification    )    token_classification: typing.Any = (        None  # this could be used to store predictions of token classification    )

要使用 Deep Search 转换文档,您需要将包含一个或多个文件的 source_path 传递给他们的文档转换 API。这将在服务器端完成,确保使用他们强大而快速的模型生态系统,该系统通过解析文档中的所有内容(如文本、位图图像和线条路径)将您的非结构化文档转换为结构良好的文本(标题和段落)、表格和图像。

Documents

# Initialize the Deep Search client from the config fileconfig = ds.DeepSearchConfig.parse_file(CONFIG_FILE)client = ds.CpsApiClient(config)api = ds.CpsApi(client)# Launch the docucment conversion and download the resultsdocuments = ds.convert_documents(    api=api, proj_key=PROJ_KEY, source_path=INPUT_FILE, progress_bar=True)

文档处理完成后,我们可以从他们的服务器下载文档。在本示例中,我们将仅使用 .json 文件,其中包含 Argilla 的文本数据,因此我们不考虑边界框检测,Deep Search 也提供了边界框检测。

output_dir = tempfile.mkdtemp()documents.download_all(result_dir=output_dir, progress_bar=True)converted_docs = {}for output_file in Path(output_dir).rglob("json*.zip"):    with ZipFile(output_file) as archive:        all_files = archive.namelist()        for name in all_files:            if not name.endswith(".json"):                continue            doc_jsondata = json.loads(archive.read(name))            converted_docs[f"{output_file}//{name}"] = doc_jsondataprint(f"{len(converted_docs)} documents have been loaded after conversion.")

提取文本段

我们现在可以使用 converted_docs JSON 文件,将我们的数据映射到我们之前定义的 DocTextSegment 数据模型中。请注意,通常您可能需要添加一些预处理启发式方法,以评估每个段的相关性,然后再上传。同样,这可以用于在将其记录到 Argilla 之前预先过滤某些信息。在大多数情况下,一个简单的分类器甚至一个基本的关键词匹配器就已经足够了。

text_segments = []for doc in converted_docs.values():    doc_title = doc.get("description").get("title")    for idx, text_segment in enumerate(doc["main-text"]):        # filter only components with text        if "text" not in text_segment:            continue        # append to the component to the list of segments        text_segments.append(            DocTextSegment(                title=doc_title,                page=text_segment.get("prov", [{}])[0].get("page"),                idx=idx,                name=text_segment.get("name"),                type=text_segment.get("type"),                text=text_segment.get("text"),            )        )print(f"{len(text_segments)} text segments got extracted from the document")

将文本段记录到 Argilla

我们现在可以将提取的段记录到 Argilla 中。首先,我们将使用整个段落和段落为 TokenClassification 创建记录

# Initialize the Argilla SDKrg.init(api_url=ARGILLA_API_URL, api_key=ARGILLA_API_KEY)# Initialize the spaCy NLP model for the tokenization of the textnlp = spacy.load("en_core_web_sm")

首先,记录一些文本分类记录

# Prepare text segments for text classificationrecords_text_classificaiton = []for segment in text_segments:    records_text_classificaiton.append(        rg.TextClassificationRecord(            text=segment.text,            vectors={},            prediction=segment.text_classification,            metadata=segment.dict(                exclude={"text", "text_classification", "token_classification"}            ),        )    )# Submit text for classificationrg.log(records_text_classificaiton, name=f"{ARGILLA_DATASET}-text")

其次,记录一些 Token Classification 记录

# Prepare text segments for token classificationrecords_token_classificaiton = []for segment in text_segments:    records_token_classificaiton.append(        rg.TokenClassificationRecord(            text=segment.text,            tokens=[token.text for token in nlp(segment.text)],            prediction=segment.token_classification,            vectors={},            metadata=segment.dict(                exclude={"text", "text_classification", "token_classification"}            ),        )    )rg.log(records_token_classificaiton, name=f"{ARGILLA_DATASET}-token")

Screen shot

下一步是什么?

现在文档已转换并上传到 Argilla,您可以使用上传的记录来注释和训练您自己的模型,以包含在 Deep Search 生态系统中。

访问 Deep Search 网站GitHub 存储库,了解他们的功能,并查看他们出色的出版物示例