Unstructured 库的核心功能
Unstructured 库包含用于分区(partition)、分块(chunk)、清理(clean)和预处理(stage)原始源文档的函数。这些函数是库中的主要公共接口,提供了处理非结构化文档的基本工具。
在阅读本节后,您应该了解以下内容:
-
如何将文档分区为 JSON 或 CSV 格式。
-
如何使用清理函数从文档元素中移除不需要的内容。
-
如何使用提取函数从文档中提取特定内容。
-
如何使用预处理函数为下游用例准备数据。
-
如何对分区后的文档进行分块,以适用于诸如检索增强生成(Retrieval Augmented Generation,RAG)等用例。
下面,我们将详细解释每个功能,并提供示例代码帮助您理解。
1. 将文档分区为 JSON 或 CSV 格式
Unstructured 库提供了 partition
函数,可以将文档分解为结构化的元素,例如标题、段落、列表项等。这些元素可以进一步转换为 JSON 或 CSV 格式,方便后续处理或分析。
示例:
from unstructured.partition.auto import partition
from unstructured.staging.base import convert_to_dict, convert_to_csv
# 分区文档,生成元素列表
elements = partition(filename="example-docs/example.pdf")
# 将元素列表转换为字典列表(JSON 格式)
elements_dict = convert_to_dict(elements)
# 将元素列表转换为 CSV 格式
elements_csv = convert_to_csv(elements)
# 保存为 JSON 文件
import json
with open("elements.json", "w") as f:
json.dump(elements_dict, f, indent=4)
# 保存为 CSV 文件
with open("elements.csv", "w") as f:
f.write(elements_csv)
2. 使用清理函数移除文档元素中的不需要内容
在处理文档时,可能会遇到文本中的不需要字符、特殊符号或不良格式。Unstructured 库的清理函数可以帮助您清理这些不需要的内容。
常用清理函数:
clean_bullets
: 移除文本开头的项目符号。clean_dashes
: 移除破折号。clean_non_ascii_chars
: 移除非 ASCII 字符。replace_unicode_quotes
: 替换 Unicode 引号字符。
示例:
from unstructured.cleaners.core import clean_bullets, clean_dashes, replace_unicode_quotes
from unstructured.documents.elements import NarrativeText
# 示例文本
text = "• This is an example text — with some “special” characters."
# 创建文档元素
element = NarrativeText(text)
# 应用清理函数
element.apply(clean_bullets)
element.apply(clean_dashes)
element.apply(replace_unicode_quotes)
# 输出清理后的文本
print(element.text)
# 输出结果:"This is an example text with some "special" characters."
3. 使用提取函数从文档中提取特定内容
Unstructured 库提供了提取函数,可以从文本中提取特定的信息,如日期、电子邮件地址、IP 地址、电话号码等。
常用提取函数:
extract_email_address
: 提取电子邮件地址。extract_ip_address
: 提取 IP 地址。extract_us_phone_number
: 提取美国电话号码。
示例:
from unstructured.cleaners.extract import extract_email_address, extract_ip_address, extract_us_phone_number
text = "Contact us at info@example.com or call 123-456-7890. Server IP: 192.168.1.1"
# 提取电子邮件地址
emails = extract_email_address(text)
print(emails)
# 输出:['info@example.com']
# 提取 IP 地址
ips = extract_ip_address(text)
print(ips)
# 输出:['192.168.1.1']
# 提取电话号码
phone_number = extract_us_phone_number(text)
print(phone_number)
# 输出:'123-456-7890'
4. 使用预处理函数为下游用例准备数据
预处理(staging)函数可以帮助您将文档元素格式化为适合下游系统或工具的数据格式,例如用于机器学习模型的输入格式、标注工具的数据格式等。
常用预处理函数:
stage_for_label_studio
: 格式化输出,适用于 LabelStudio。stage_for_prodigy
: 格式化输出,适用于 Prodigy。stage_for_transformers
: 准备文本元素,以供 Transformers 管道处理。stage_for_weaviate
: 将元素对象列表准备好,以便导入到 Weaviate 向量数据库。
示例:
from unstructured.documents.elements import NarrativeText
from unstructured.staging.label_studio import stage_for_label_studio
import json
# 创建元素列表
elements = [NarrativeText(text="This is a sample text for labeling.")]
# 使用预处理函数
label_studio_data = stage_for_label_studio(elements)
# 保存为 JSON 文件,供 LabelStudio 上传
with open("label_studio.json", "w") as f:
json.dump(label_studio_data, f, indent=4)
5. 对分区后的文档进行分块以适用于 RAG 等用例
分块(chunking)功能可以将分区后的文档元素组合成大小适合的块,以满足特定的用例需求,例如检索增强生成(RAG)。
分块策略:
basic
: 基础分块策略,根据元素顺序和大小进行分块。by_title
: 根据标题元素,将章节内容分块。
示例:
from unstructured.partition.auto import partition
from unstructured.chunking.basic import chunk_elements
from unstructured.chunking.title import chunk_by_title
# 分区文档
elements = partition(filename="example-docs/long-article.pdf")
# 使用基础分块策略
chunks_basic = chunk_elements(elements, max_characters=1000)
# 使用按标题分块策略
chunks_by_title = chunk_by_title(elements)
# 查看分块结果
for chunk in chunks_by_title:
print(chunk.text)
print("\n" + "-"*50 + "\n")
小结
Unstructured 库提供了一套完整的工具,用于处理非结构化文档,从分区、清理、提取、预处理到分块。通过掌握这些核心功能,您可以:
- 将文档分解为结构化的元素,方便进一步的分析和处理。
- 清理文本,移除噪声和不需要的字符,提高数据质量。
- 提取特定信息,从文本中获取关键信息。
- 将数据格式化为适合下游工具或系统的格式,简化数据集成流程。
- 根据需求将文档元素分块,适应不同的用例,如 RAG。
希望通过本节的讲解,您对 Unstructured 库的核心功能有了全面的了解,并能够在实际项目中灵活运用这些功能。
分析与解释 Unstructured 库中的 Partitioning 功能
Unstructured 库中的 Partitioning(分区)功能允许用户从非结构化的原始文档中提取结构化的内容。这些功能可以将文档分解为诸如 Title(标题)、NarrativeText(叙述文本)和 ListItem(列表项)等元素,使用户能够根据特定的应用需求决定保留哪些内容。例如,如果您正在训练一个摘要模型,您可能只需要关注 NarrativeText。
简介
使用 Unstructured 库对文档进行分区的最简单方法是使用 partition
函数。调用该函数时,Unstructured 会使用 libmagic
自动确定文件类型,并调用相应的分区函数。如果 libmagic
不可用,文件类型检测将退回使用文件扩展名。
支持的文档类型
以下表格列出了 Unstructured 库当前支持的文档类型。partition
函数能够识别每种文档类型并将其路由到适当的分区函数。如果您已经知道文档类型,也可以直接使用表中列出的特定分区函数。
文档类型 | 分区函数 | 策略 | 表格支持 | 选项 |
---|---|---|---|---|
CSV 文件 (.csv) | partition_csv | N/A | 是 | 无 |
电子邮件 (.eml) | partition_email | N/A | 否 | 编码;包含头信息;最大分区;处理附件 |
电子邮件 (.msg) | partition_msg | N/A | 否 | 编码;最大分区;处理附件 |
EPUB 文件 (.epub) | partition_epub | N/A | 是 | 包含分页符 |
Excel 文档 (.xlsx/.xls) | partition_xlsx | N/A | 是 | 无 |
HTML 页面 (.html/.htm) | partition_html | N/A | 否 | 编码;包含分页符 |
图像 (.png/.jpg/.jpeg/.tiff/.bmp/.heic) | partition_image | “auto”、“hi_res”、“ocr_only” | 是 | 编码;包含分页符;推断表结构;OCR 语言;策略 |
Markdown (.md) | partition_md | N/A | 是 | 包含分页符 |
Org Mode (.org) | partition_org | N/A | 是 | 包含分页符 |
Open Office 文档 (.odt) | partition_odt | N/A | 是 | 无 |
PDF 文件 (.pdf) | partition_pdf | “auto”、“fast”、“hi_res”、“ocr_only” | 是 | 编码;包含分页符;推断表结构;最大分区;OCR 语言;策略 |
纯文本 (.txt/.text/.log) | partition_text | N/A | 否 | 编码;最大分区;段落分组器 |
PowerPoint (.ppt) | partition_ppt | N/A | 是 | 包含分页符 |
PowerPoint (.pptx) | partition_pptx | N/A | 是 | 包含分页符 |
ReStructured Text (.rst) | partition_rst | N/A | 是 | 包含分页符 |
富文本文件 (.rtf) | partition_rtf | N/A | 是 | 包含分页符 |
TSV 文件 (.tsv) | partition_tsv | N/A | 是 | 无 |
Word 文档 (.doc) | partition_doc | N/A | 是 | 包含分页符 |
Word 文档 (.docx) | partition_docx | N/A | 是 | 包含分页符 |
XML 文档 (.xml) | partition_xml | N/A | 否 | 编码;最大分区;XML 保留标签 |
代码文件 (.js/.py/.java/.cpp/.cc/.cxx/.c/.cs/.php/.rb/.swift/.ts/.go) | partition_text | N/A | 否 | 编码;最大分区;段落分组器 |
使用 partition
函数
partition
函数可以接受文件名或类文件对象作为输入。它还有一些可选参数,例如:
include_page_breaks=True
:如果设置为 True,输出将包含 PageBreak(分页符)元素(如果文件类型支持)。content_type
:可以指定文件的 MIME 类型,以绕过文件类型检测逻辑。
示例:
from unstructured.partition.auto import partition
filename = os.path.join(EXAMPLE_DOCS_DIRECTORY, "layout-parser-paper-fast.pdf")
elements = partition(filename=filename, content_type="application/pdf")
print("\n\n".join([str(el) for el in elements][:10]))
使用类文件对象:
from unstructured.partition.auto import partition
filename = os.path.join(EXAMPLE_DOCS_DIRECTORY, "layout-parser-paper-fast.pdf")
with open(filename, "rb") as f:
elements = partition(file=f, include_page_breaks=True)
print("\n\n".join([str(el) for el in elements][5:15]))
文档特定的分区函数
Unstructured 库还包括针对特定文档类型的分区函数。使用文档特定的分区函数可能有以下几个原因:
- 已知文档类型:如果您已经知道文档类型,直接使用特定函数可以避免文件类型检测,提高程序运行速度。
- 减少依赖:如果只使用特定的分区函数,不需要安装用于文件类型检测的
libmagic
。 - 额外功能:某些文档特定的函数包含额外的功能。例如,
partition_html
允许您直接传入 URL,无需本地存储.html
文件。
示例(直接从 URL 解析 HTML):
from unstructured.partition.html import partition_html
url = "https://www.cnn.com/2023/01/30/sport/empire-state-building-green-philadelphia-eagles-spt-intl/index.html"
elements = partition_html(url=url)
print("\n\n".join([str(el) for el in elements]))
各分区函数详细解释
partition_csv
partition_csv
函数用于预处理 CSV 文件。输出是一个单独的 Table
(表格)元素。元素元数据中的 text_as_html
属性将包含表格的 HTML 表示。
示例:
from unstructured.partition.csv import partition_csv
elements = partition_csv(filename="example-docs/stanley-cups.csv")
print(elements[0].metadata.text_as_html)
partition_doc
partition_doc
函数用于处理以 .doc
格式保存的 Microsoft Word 文档。该函数使用 libreoffice
将文件转换为 .docx
,然后调用 partition_docx
。使用前请确保已安装 libreoffice
。
示例:
from unstructured.partition.doc import partition_doc
elements = partition_doc(filename="example-docs/fake.doc")
partition_docx
partition_docx
函数用于处理以 .docx
格式保存的 Microsoft Word 文档。它可以接受文件名或类文件对象作为输入。
示例:
import docx
from unstructured.partition.docx import partition_docx
document = docx.Document()
document.add_paragraph("重要分析", style="Heading 1")
document.add_paragraph("这是我的第一个想法。", style="Body Text")
document.add_paragraph("这是我的第二个想法。", style="Normal")
document.save("mydoc.docx")
elements = partition_docx(filename="mydoc.docx")
with open("mydoc.docx", "rb") as f:
elements = partition_docx(file=f)
partition_email
partition_email
函数用于处理 .eml
格式的电子邮件文件,可以与 Microsoft Outlook 和 Gmail 等邮件客户端的导出文件一起使用。
- 可以接受文件名、类文件对象或原始文本作为输入。
- 可选参数:
include_headers
:设置为 True 时,返回的元素将包含电子邮件头信息。content_source
:可以设置为text/html
(默认)或text/plain
,以处理电子邮件的 HTML 或纯文本版本。
示例:
from unstructured.partition.email import partition_email
elements = partition_email(filename="example-docs/eml/fake-email.eml")
with open("example-docs/eml/fake-email.eml", "r") as f:
elements = partition_email(file=f)
with open("example-docs/eml/fake-email.eml", "r") as f:
text = f.read()
elements = partition_email(text=text)
elements = partition_email(text=text, content_source="text/plain")
elements = partition_email(text=text, include_headers=True)
partition_epub
partition_epub
函数用于处理 EPUB3 格式的电子书。该函数首先使用 pandoc
将文档转换为 HTML,然后调用 partition_html
。使用前请确保已安装 pandoc
。
示例:
from unstructured.partition.epub import partition_epub
elements = partition_epub(filename="example-docs/winter-sports.epub")
partition_html
partition_html
函数用于处理 HTML 文档,返回一系列的文档元素对象。它可以接受文件名、类文件对象、字符串或 URL 作为输入。
示例:
from unstructured.partition.html import partition_html
elements = partition_html(filename="example-docs/example-10k.html")
with open("example-docs/example-10k.html", "r") as f:
elements = partition_html(file=f)
with open("example-docs/example-10k.html", "r") as f:
text = f.read()
elements = partition_html(text=text)
# 从 URL 获取并解析内容
elements = partition_html(url="https://python.org/")
partition_image
partition_image
函数用于处理图像文件(如 .png
、.jpg
、.heic
等)。该函数支持与 partition_pdf
类似的策略参数,包括 "auto"
、"hi_res"
和 "ocr_only"
。
- 策略参数:
"auto"
:根据文档特征自动选择分区策略。"hi_res"
:使用detectron2_onnx
识别文档布局,适用于对分类准确性要求高的情况。"ocr_only"
:仅使用 Tesseract 进行 OCR,然后通过partition_text
处理原始文本。
示例:
from unstructured.partition.image import partition_image
elements = partition_image("example-docs/img/layout-parser-paper-fast.jpg")
# 使用英语和瑞典语的语言包进行 OCR
elements = partition_image("example-docs/img/layout-parser-paper-fast.jpg", languages=["eng", "swe"])
partition_md
partition_md
函数用于解析 Markdown 文件。
示例:
from unstructured.partition.md import partition_md
elements = partition_md(filename="README.md")
partition_msg
partition_msg
函数用于处理 .msg
格式的文件,这是 Microsoft Outlook 导出的电子邮件文件格式。
示例:
from unstructured.partition.msg import partition_msg
elements = partition_msg(filename="example-docs/fake-email.msg")
partition_pdf
partition_pdf
函数用于分割 PDF 文档。它支持多种策略:
- 策略参数:
"auto"
:自动选择最佳策略。"hi_res"
:使用detectron2_onnx
进行高分辨率分析。"fast"
:使用pdfminer
快速提取文本。"ocr_only"
:仅使用 Tesseract 进行 OCR。
示例:
from unstructured.partition.pdf import partition_pdf
elements = partition_pdf("example-docs/pdf/layout-parser-paper-fast.pdf")
# 使用英语和瑞典语的语言包进行 OCR
elements = partition_pdf("example-docs/pdf/layout-parser-paper-fast.pdf", languages=["eng", "swe"])
partition_ppt / partition_pptx
partition_ppt
和 partition_pptx
函数用于处理 Microsoft PowerPoint 文档分别保存为 .ppt
和 .pptx
格式。
partition_ppt
使用libreoffice
将.ppt
转换为.pptx
,然后调用partition_pptx
。
示例:
from unstructured.partition.ppt import partition_ppt
elements = partition_ppt(filename="example-docs/fake-power-point.ppt")
from unstructured.partition.pptx import partition_pptx
elements = partition_pptx(filename="example-docs/fake-power-point.pptx")
with open("example-docs/fake-power-point.pptx", "rb") as f:
elements = partition_pptx(file=f)
partition_rst
partition_rst
函数用于处理 ReStructured Text(.rst
)文档。它首先使用 pandoc
将文档转换为 HTML,然后调用 partition_html
。
示例:
from unstructured.partition.rst import partition_rst
elements = partition_rst(filename="example-docs/README.rst")
partition_rtf
partition_rtf
函数用于处理富文本文件(.rtf
)。它首先使用 pandoc
将文档转换为 HTML,然后调用 partition_html
。
示例:
from unstructured.partition.rtf import partition_rtf
elements = partition_rtf(filename="example-docs/fake-doc.rtf")
partition_text
partition_text
函数用于分割纯文本文件。可接受文件名、类文件对象和原始文本作为输入。
示例:
from unstructured.partition.text import partition_text
elements = partition_text(filename="example-docs/fake-text.txt")
with open("example-docs/fake-text.txt", "r") as f:
elements = partition_text(file=f)
with open("example-docs/fake-text.txt", "r") as f:
text = f.read()
elements = partition_text(text=text)
- 段落分组器: 如果文本中存在用于格式化的额外换行符,可使用
paragraph_grouper
参数(一个接受字符串并返回字符串的函数)来将被打断的文本分组。
示例:
from unstructured.partition.text import partition_text
from unstructured.cleaners.core import group_broken_paragraphs
text = """The big brown fox
was walking down the lane.
At the end of the lane, the
fox met a bear."""
partition_text(text=text, paragraph_grouper=group_broken_paragraphs)
partition_xml
partition_xml
函数用于处理 XML 文档。
- 参数:
xml_keep_tags
:如果设置为False
,函数仅返回标签中的文本内容。设置为True
时,返回包含标签信息的元素。xml_path
:可用于指定提取特定标签的文本。
示例:
from unstructured.partition.xml import partition_xml
elements = partition_xml(filename="example-docs/factbook.xml", xml_keep_tags=True)
elements = partition_xml(filename="example-docs/factbook.xml", xml_keep_tags=False)
小结
通过上述分区函数,Unstructured 库为处理各种文档类型提供了强大的工具。根据您的特定需求,您可以选择使用通用的 partition
函数,或直接调用特定文档类型的分区函数,以获得更多的控制和功能。无论是处理文本、图像,还是复杂的文档格式,Unstructured 都能帮助您高效地提取所需的结构化信息。
Unstructured 库中的 Cleaning(清理)功能
在为 NLP 模型准备数据的过程中,通常需要在将数据传递给模型之前对其进行清理。如果输出中存在不需要的内容,可能会影响 NLP 模型的质量。为了解决这个问题,Unstructured 库包含了一些清理函数,帮助用户在将数据发送到下游应用程序之前对输出进行清理。
自动清理函数的应用
某些清理函数会自动应用。例如,在前面的分区部分的示例中,输出中的 Philadelphia Eaglesâ\x80\x99 victory
会在 partition_html
中自动转换为 Philadelphia Eagles' victory
,这是通过 replace_unicode_quotes
清理函数实现的。下面的代码片段展示了这是如何工作的:
from unstructured.cleaners.core import replace_unicode_quotes
replace_unicode_quotes("Philadelphia Eaglesâ\x80\x99 victory")
元素的清理方法
Unstructured 中的文档元素包含一个 apply
方法,允许您在不实例化新元素的情况下对元素文本应用清理函数。apply
方法需要一个可调用对象,该对象接受一个字符串作为输入,并输出另一个字符串。在下面的示例中,我们使用 apply
方法调用了 replace_unicode_quotes
清理函数。
from unstructured.documents.elements import Text
element = Text("Philadelphia Eaglesâ\x80\x99 victory")
element.apply(replace_unicode_quotes)
print(element)
自定义清理函数
由于清理函数只是一个从字符串到字符串的函数,用户也可以轻松地包含自己的清理函数,以执行自定义的数据预处理任务。在下面的示例中,我们从一段文本中移除了引用(如 [1]
)。
import re
remove_citations = lambda text: re.sub("\[\d{1,3}\]", "", text)
element = Text("[1] 地理定位的战斗录像已确认俄罗斯在斯瓦托韦西北的德沃里奇涅地区取得了进展。")
element.apply(remove_citations)
print(element)
Unstructured 库中的清理函数列表
以下是 Unstructured 库中清理函数的完整列表。
bytes_string_to_string
将看起来像字节字符串的输出字符串转换为指定编码的字符串。当存在类似表情符号的字符,HTML 解析器无法预期时,这种情况有时会在 partition_html
中发生。在这种情况下,编码的字节会被处理。
示例:
from unstructured.cleaners.core import bytes_string_to_string
text = "Hello ð\x9f\x98\x80"
# 输出应为 "Hello 😀"
bytes_string_to_string(text, encoding="utf-8")
from unstructured.cleaners.core import bytes_string_to_string
from unstructured.partition.html import partition_html
text = """\n<html charset="utf-8"><p>Hello 😀</p></html>"""
elements = partition_html(text=text)
elements[0].apply(bytes_string_to_string)
# 输出应为 "Hello 😀"
print(elements[0].text)
clean
使用选项清理一段文本,包括移除项目符号、多余的空白、破折号和尾随标点。您还可以选择将输出转换为小写。
选项:
- 如果
bullets=True
,则应用clean_bullets
。 - 如果
extra_whitespace=True
,则应用clean_extra_whitespace
。 - 如果
dashes=True
,则应用clean_dashes
。 - 如果
trailing_punctuation=True
,则应用clean_trailing_punctuation
。 - 如果
lowercase=True
,则将输出转换为小写。
示例:
from unstructured.cleaners.core import clean
# 返回 "an excellent point!"
clean("● An excellent point!", bullets=True, lowercase=True)
# 返回 "ITEM 1A: RISK FACTORS"
clean("ITEM 1A: RISK-FACTORS", extra_whitespace=True, dashes=True)
clean_bullets
从文本开头移除项目符号。不会移除不在文本开头的项目符号。
示例:
from unstructured.cleaners.core import clean_bullets
# 返回 "An excellent point!"
clean_bullets("● An excellent point!")
# 返回 "I love Morse Code! ●●●"
clean_bullets("I love Morse Code! ●●●")
clean_dashes
从一段文本中移除破折号,也处理特殊字符(例如 \u2013
)。
示例:
from unstructured.cleaners.core import clean_dashes
# 返回 "ITEM 1A: RISK FACTORS"
clean_dashes("ITEM 1A: RISK-FACTORS\u2013")
clean_non_ascii_chars
从字符串中移除非 ASCII 字符。
示例:
from unstructured.cleaners.core import clean_non_ascii_chars
text = "\x88This text contains ®non-ascii characters!●"
# 返回 "This text contains non-ascii characters!"
clean_non_ascii_chars(text)
clean_ordered_bullets
从文本开头移除最多三级“子节”级别的字母数字项目符号。
示例:
from unstructured.cleaners.core import clean_ordered_bullets
# 返回 "This is a very important point"
clean_ordered_bullets("1.1 This is a very important point")
# 返回 "This is a very important point ●"
clean_ordered_bullets("a.b This is a very important point ●")
clean_postfix
如果字符串匹配指定模式,则移除字符串的后缀。
选项:
- 如果
ignore_case=True
,则忽略大小写。默认值为False
。 - 如果
strip=True
,则移除尾随的空白。默认值为True
。
示例:
from unstructured.cleaners.core import clean_postfix
text = "The end! END"
# 返回 "The end!"
clean_postfix(text, r"(END|STOP)", ignore_case=True)
clean_prefix
如果字符串匹配指定模式,则移除字符串的前缀。
选项:
- 如果
ignore_case=True
,则忽略大小写。默认值为False
。 - 如果
strip=True
,则移除前导的空白。默认值为True
。
示例:
from unstructured.cleaners.core import clean_prefix
text = "SUMMARY: This is the best summary of all time!"
# 返回 "This is the best summary of all time!"
clean_prefix(text, r"(SUMMARY|DESCRIPTION):", ignore_case=True)
clean_trailing_punctuation
移除一段文本的尾随标点符号。
示例:
from unstructured.cleaners.core import clean_trailing_punctuation
# 返回 "ITEM 1A: RISK FACTORS"
clean_trailing_punctuation("ITEM 1A: RISK FACTORS.")
group_broken_paragraphs
将因视觉或格式化目的而使用换行符分隔的段落组合在一起。这在 .txt
文件中很常见。默认情况下,group_broken_paragraphs
将通过 \n
分隔的行组合在一起。您可以使用 line_split
参数更改此行为。该函数默认将 \n\n
视为段落分隔符。您可以使用 paragraph_split
参数更改此行为。
示例:
from unstructured.cleaners.core import group_broken_paragraphs
text = """The big brown fox
was walking down the lane.
At the end of the lane, the
fox met a bear."""
group_broken_paragraphs(text)
import re
from unstructured.cleaners.core import group_broken_paragraphs
para_split_re = re.compile(r"(\s*\n\s*){3}")
text = """The big brown fox
was walking down the lane.
At the end of the lane, the
fox met a bear."""
group_broken_paragraphs(text, paragraph_split=para_split_re)
remove_punctuation
从字符串中移除 ASCII 和 Unicode 标点符号。
示例:
from unstructured.cleaners.core import remove_punctuation
# 返回 "A lovely quote"
remove_punctuation("“A lovely quote!”")
replace_unicode_quotes
替换字符串中的 Unicode 引号字符,例如 \x91
。
示例:
from unstructured.cleaners.core import replace_unicode_quotes
# 返回 "“A lovely quote!”"
replace_unicode_quotes("\x93A lovely quote!\x94")
# 返回 "‘A lovely quote!’"
replace_unicode_quotes("\x91A lovely quote!\x92")
translate_text
translate_text
清理函数用于在语言之间翻译文本。translate_text
使用来自 transformers
的 Helsinki NLP MT 模型进行机器翻译。适用于俄语、中文、阿拉伯语等多种语言。
参数:
text
:要翻译的输入字符串。source_lang
:文本的源语言的两字母语言代码。如果未指定source_lang
,将使用langdetect
自动检测语言。target_lang
:目标翻译语言的两字母语言代码。默认值为"en"
。
示例:
from unstructured.cleaners.translate import translate_text
# 输出为 "I'm a Berliner!"
translate_text("Ich bin ein Berliner!")
# 输出为 "I can also translate Russian!"
translate_text("Я тоже могу переводить русский язык!", "ru", "en")
小结
Unstructured 库提供了多种清理函数,帮助用户在将数据传递给 NLP 模型或其他应用程序之前,对文本进行预处理和清理。这些函数既可以自动应用,也可以通过元素的 apply
方法手动应用。此外,用户还可以轻松地创建自定义清理函数,以满足特定的数据处理需求。
通过使用这些清理工具,您可以提高数据的质量,从而改进下游模型和应用程序的性能。
Unstructured 库中的 Extracting(提取)功能
Unstructured 库提供了一系列函数,用于从非结构化文本中提取有用的信息。这些提取函数可以帮助用户从文本中获取日期、时间、电子邮件地址、IP 地址、电话号等信息,以及处理文本中的特殊格式。
以下是 Unstructured 库中提取函数的详细说明。
提取函数列表
extract_datetimetz
功能:
- 从
.eml
文件的 Received 字段中提取日期、时间和时区。 - 接受一个字符串作为输入,返回一个
datetime.datetime
对象。
示例:
from unstructured.cleaners.extract import extract_datetimetz
text = """from ABC.DEF.local ([ba23::58b5:2236:45g2:88h2]) by
\n ABC.DEF.local2 ([ba23::58b5:2236:45g2:88h2%25]) with mapi id\
n 32.88.5467.123; Fri, 26 Mar 2021 11:04:09 +1200"""
# 返回 datetime.datetime(2021, 3, 26, 11, 4, 9, tzinfo=datetime.timezone(datetime.timedelta(seconds=43200)))
extract_datetimetz(text)
extract_email_address
功能:
- 从输入字符串中提取电子邮件地址。
- 返回输入字符串中的所有电子邮件地址列表。
示例:
from unstructured.cleaners.extract import extract_email_address
text = """Me me@email.com and You <You@email.com>
([ba23::58b5:2236:45g2:88h2]) (10.0.2.01)"""
# 返回 ['me@email.com', 'you@email.com']
extract_email_address(text)
extract_ip_address
功能:
- 从输入字符串中提取 IPv4 和 IPv6 的 IP 地址。
- 返回输入字符串中的所有 IP 地址列表。
示例:
from unstructured.cleaners.extract import extract_ip_address
text = """Me me@email.com and You <You@email.com>
([ba23::58b5:2236:45g2:88h2]) (10.0.2.01)"""
# 返回 ['ba23::58b5:2236:45g2:88h2', '10.0.2.01']
extract_ip_address(text)
extract_ip_address_name
功能:
- 从
.eml
文件的 Received 字段中提取每个 IP 地址对应的名称。 - 接受一个字符串作为输入,返回输入字符串中所有 IP 地址的名称列表。
示例:
from unstructured.cleaners.extract import extract_ip_address_name
text = """from ABC.DEF.local ([ba23::58b5:2236:45g2:88h2]) by
\n ABC.DEF.local2 ([ba23::58b5:2236:45g2:88h2%25]) with mapi id\
n 32.88.5467.123; Fri, 26 Mar 2021 11:04:09 +1200"""
# 返回 ['ABC.DEF.local', 'ABC.DEF.local2']
extract_ip_address_name(text)
extract_mapi_id
功能:
- 从
.eml
文件的 Received 字段中提取 mapi id。 - 接受一个字符串作为输入,返回输入字符串中 mapi id 的列表。
示例:
from unstructured.cleaners.extract import extract_mapi_id
text = """from ABC.DEF.local ([ba23::58b5:2236:45g2:88h2]) by
\n ABC.DEF.local2 ([ba23::58b5:2236:45g2:88h2%25]) with mapi id\
n 32.88.5467.123; Fri, 26 Mar 2021 11:04:09 +1200"""
# 返回 ['32.88.5467.123']
extract_mapi_id(text)
extract_ordered_bullets
功能:
- 从文本开头提取最多三级“子节”级别的字母数字项目符号。
示例:
from unstructured.cleaners.extract import extract_ordered_bullets
# 返回 ('1', '1', None)
extract_ordered_bullets("1.1 This is a very important point")
# 返回 ('a', '1', None)
extract_ordered_bullets("a.1 This is a very important point")
extract_text_after
功能:
- 提取指定模式之后的文本。
选项:
index
:如果设置了index
,则提取第(index + 1)
次出现的模式之后的文本。默认值为0
(第一次出现)。strip
:如果设置为True
,则移除前导和尾随的空白。默认值为True
。
示例:
from unstructured.cleaners.extract import extract_text_after
text = "SPEAKER 1: Look at me, I'm flying!"
# 返回 "Look at me, I'm flying!"
extract_text_after(text, r"SPEAKER \d{1}:")
extract_text_before
功能:
- 提取指定模式之前的文本。
选项:
index
:如果设置了index
,则提取第(index + 1)
次出现的模式之前的文本。默认值为0
(第一次出现)。strip
:如果设置为True
,则移除前导和尾随的空白。默认值为True
。
示例:
from unstructured.cleaners.extract import extract_text_before
text = "Here I am! STOP Look at me! STOP I'm flying! STOP"
# 返回 "Here I am!"
extract_text_before(text, r"STOP")
extract_us_phone_number
功能:
- 从一段文本中提取美国电话号码。
示例:
from unstructured.cleaners.extract import extract_us_phone_number
# 返回 '215-867-5309'
extract_us_phone_number("Phone number: 215-867-5309")
group_broken_paragraphs
功能:
- 将因视觉或格式目的而使用换行符分隔的段落组合在一起。这在
.txt
文件中很常见。 - 默认情况下,
group_broken_paragraphs
会将通过\n
分隔的行组合在一起。您可以使用line_split
参数更改此行为。 - 该函数默认将
\n\n
视为段落分隔符。您可以使用paragraph_split
参数更改此行为。
示例:
from unstructured.cleaners.core import group_broken_paragraphs
text = """The big brown fox
was walking down the lane.
At the end of the lane, the
fox met a bear."""
group_broken_paragraphs(text)
import re
from unstructured.cleaners.core import group_broken_paragraphs
para_split_re = re.compile(r"(\s*\n\s*){3}")
text = """The big brown fox
was walking down the lane.
At the end of the lane, the
fox met a bear."""
group_broken_paragraphs(text, paragraph_split=para_split_re)
remove_punctuation
功能:
- 从字符串中移除 ASCII 和 Unicode 标点符号。
示例:
from unstructured.cleaners.core import remove_punctuation
# 返回 "A lovely quote"
remove_punctuation("“A lovely quote!”")
replace_unicode_quotes
功能:
- 替换字符串中的 Unicode 引号字符,例如
\x91
。
示例:
from unstructured.cleaners.core import replace_unicode_quotes
# 返回 "“A lovely quote!”"
replace_unicode_quotes("\x93A lovely quote!\x94")
# 返回 "‘A lovely quote!’"
replace_unicode_quotes("\x91A lovely quote!\x92")
translate_text
功能:
translate_text
函数用于在语言之间翻译文本。- 使用来自
transformers
的 Helsinki NLP MT 模型进行机器翻译。适用于俄语、中文、阿拉伯语和许多其他语言。
参数:
text
:要翻译的输入字符串。source_lang
:文本的源语言的两字母语言代码。如果未指定source_lang
,将使用langdetect
自动检测语言。target_lang
:目标翻译语言的两字母语言代码。默认值为"en"
。
示例:
from unstructured.cleaners.translate import translate_text
# 输出为 "I'm a Berliner!"
translate_text("Ich bin ein Berliner!")
# 输出为 "I can also translate Russian!"
translate_text("Я тоже могу переводить русский язык!", "ru", "en")
小结
Unstructured 库提供了丰富的提取函数,帮助用户从非结构化文本中提取有用的信息。这些函数涵盖了日期时间、电子邮件地址、IP 地址、MAPI ID、项目符号、文本片段、电话号码等多个方面。
通过使用这些提取工具,您可以从复杂的文本数据中获取结构化的信息,为下游的数据处理、分析和机器学习任务打下良好的基础。
Unstructured 库中的 Staging(预处理)功能
注意: Unstructured 开源库中的 Staging 函数正在被弃用,取而代之的是 Unstructured Ingest CLI 和 Unstructured Ingest Python 库中的目标连接器。
Unstructured 包中的 Staging 函数帮助您准备数据,以便将其导入到下游系统中。Staging 函数接受一个由文档元素(elements)组成的列表作为输入,并返回一个适当格式化的字典作为输出。在下面的示例中,我们使用 stage_for_label_studio
函数,将叙述文本(narrative text)示例准备好,以便导入到 LabelStudio 中。我们可以直接将这些数据上传到 LabelStudio,快速开始 NLP 标注任务。
示例:
import json
from unstructured.staging.label_studio import stage_for_label_studio
output = stage_for_label_studio(narrative_text)
print(json.dumps(output[:2], indent=4))
Staging 函数列表
convert_to_csv
功能:
将输出转换为初始结构化数据(ISD)格式,作为 CSV 字符串。
示例:
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.base import convert_to_csv
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
isd_csv = convert_to_csv(elements)
更多信息:
有关 convert_to_csv
函数的更多信息,请查看源代码。
convert_to_dataframe
功能:
将文档元素对象的列表转换为 Pandas DataFrame。DataFrame 将包含一个 text
列(元素的文本)和一个 type
列(元素的类型,如 NarrativeText
或 Title
)。
示例:
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.base import convert_to_dataframe
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
df = convert_to_dataframe(elements)
更多信息:
有关 convert_to_dataframe
函数的更多信息,请查看源代码。
convert_to_dict
功能:
将元素对象的列表转换为字典格式。这是 Unstructured 中表示文档的默认格式。
示例:
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.base import convert_to_dict
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
isd = convert_to_dict(elements)
更多信息:
有关 convert_to_dict
函数的更多信息,请查看源代码。
dict_to_elements
功能:
将由 convert_to_dict
生成的字典格式转换回元素对象的列表。
示例:
from unstructured.staging.base import dict_to_elements
isd = [
{"text": "My Title", "type": "Title"},
{"text": "My Narrative", "type": "NarrativeText"}
]
# elements 将是:
# [Title(text="My Title"), NarrativeText(text="My Narrative")]
elements = dict_to_elements(isd)
更多信息:
有关 dict_to_elements
函数的更多信息,请查看源代码。
stage_csv_for_prodigy
功能:
以 CSV 格式格式化输出,以供 Prodigy 使用。运行 stage_csv_for_prodigy
后,您可以将结果写入 CSV 文件,供 Prodigy 使用。
示例:
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.prodigy import stage_csv_for_prodigy
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
metadata = [{"type": "title"}, {"source": "news"}]
prodigy_csv_data = stage_csv_for_prodigy(elements, metadata)
# 生成的 CSV 文件可直接用于 Prodigy
with open("prodigy.csv", "w") as csv_file:
csv_file.write(prodigy_csv_data)
更多信息:
有关 stage_csv_for_prodigy
函数的更多信息,请查看源代码。
stage_for_argilla
功能:
将文本元素列表转换为 Argilla 数据集。可以使用 argilla_task
参数指定生成的数据集类型,有效值为 "text_classification"
、"token_classification"
和 "text2text"
。如果选择 "token_classification"
,且未在可选参数中包含 tokens
,则默认使用 NLTK 的词语分词器。
示例:
import json
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.argilla import stage_for_argilla
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
metadata = [{"type": "title"}, {"type": "text"}]
argilla_dataset = stage_for_argilla(elements, "text_classification", metadata=metadata)
更多信息:
有关 stage_for_argilla
函数的更多信息,请查看源代码。
stage_for_baseplate
功能:
stage_for_baseplate
函数将元素对象列表准备好,以便导入到 Baseplate(一种具有电子表格界面的 LLM 后端)。运行该函数后,您可以使用 Baseplate API 将文档上传到 Baseplate。以下示例演示了如何使用 stage_for_baseplate
函数。
示例:
from unstructured.documents.elements import ElementMetadata, NarrativeText, Title
from unstructured.staging.baseplate import stage_for_baseplate
metadata = ElementMetadata(filename="fox.epub")
elements = [
Title("A Wonderful Story About A Fox", metadata=metadata),
NarrativeText(
"A fox ran into the chicken coop and the chickens flew off!",
metadata=metadata,
),
]
rows = stage_for_baseplate(elements)
输出将如下:
{
"rows": [
{
"data": {
"element_id": "ad270eefd1cc68d15f4d3e51666d4dc8",
"text": "A Wonderful Story About A Fox",
"type": "Title",
},
"metadata": {"filename": "fox.epub"},
},
{
"data": {
"element_id": "8275769fdd1804f9f2b55ad3c9b0ef1b",
"text": "A fox ran into the chicken coop and the chickens flew off!",
"type": "NarrativeText",
},
"metadata": {"filename": "fox.epub"},
},
],
}
更多信息:
有关 stage_for_baseplate
函数的更多信息,请查看源代码。
stage_for_datasaur
功能:
将文本元素列表格式化为 Datasaur 中基于标记的任务的输入。
示例:
from unstructured.documents.elements import Text
from unstructured.staging.datasaur import stage_for_datasaur
elements = [Text("Text1"), Text("Text2")]
datasaur_data = stage_for_datasaur(elements)
输出:
生成的输出是一个字典列表,每个字典包含两个键:
text
:元素的文本内容。entities
:一个空列表。
您还可以在 stage_for_datasaur
函数中指定实体(entities)。这些实体将在输出的 entities
键中包含。实体列表是一个字典的列表,必须包含所有必要的键。实体列表的长度必须与元素列表的长度相同。对于没有实体的元素,使用空列表。
示例:
from unstructured.documents.elements import Text
from unstructured.staging.datasaur import stage_for_datasaur
elements = [Text("Hi my name is Matt.")]
entities = [[{"text": "Matt", "type": "PER", "start_idx": 11, "end_idx": 15}]]
datasaur_data = stage_for_datasaur(elements, entities)
更多信息:
有关 stage_for_datasaur
函数的更多信息,请查看源代码。
stage_for_label_box
功能:
格式化输出,以供 LabelBox 使用。LabelBox 接受云托管的数据,不支持直接导入文本。stage_for_label_box
函数执行以下操作:
- 在指定的
output_directory
中暂存数据文件,以便上传到云存储服务。 - 返回一个
List[Dict[str, Any]]
类型的配置,可写入 JSON 文件并导入到 LabelBox 中。
注意: stage_for_label_box
不会将数据上传到远程存储(如 S3)。运行此函数后,用户可以使用命令 aws s3 sync ${output_directory} ${url_prefix}
将数据上传到 S3。
示例:
以下示例展示了如何生成可用于 LabelBox 的 config.json
文件,并将暂存的数据文件上传到 S3 存储桶。
import os
import json
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.label_box import stage_for_label_box
# S3 存储桶名称
S3_BUCKET_NAME = "labelbox-staging-bucket"
# S3 存储桶中的键前缀(目录)
S3_BUCKET_KEY_PREFIX = "data/"
# 数据文件访问的 URL 前缀
S3_URL_PREFIX = f"https://{S3_BUCKET_NAME}.s3.amazonaws.com/{S3_BUCKET_KEY_PREFIX}"
# 本地输出目录,用于暂存数据文件
LOCAL_OUTPUT_DIRECTORY = "/tmp/labelbox-staging"
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
labelbox_config = stage_for_label_box(
elements,
output_directory=LOCAL_OUTPUT_DIRECTORY,
url_prefix=S3_URL_PREFIX,
external_ids=["id1", "id2"],
attachments=[[{"type": "RAW_TEXT", "value": "Title description"}], [{"type": "RAW_TEXT", "value": "Narrative Description"}]],
create_directory=True,
)
# 生成的配置文件可用于 LabelBox
with open("config.json", "w+") as labelbox_config_file:
json.dump(labelbox_config, labelbox_config_file, indent=4)
# 将暂存的数据文件上传到 S3
def upload_staged_files():
from s3fs import S3FileSystem
fs = S3FileSystem()
for filename in os.listdir(LOCAL_OUTPUT_DIRECTORY):
filepath = os.path.join(LOCAL_OUTPUT_DIRECTORY, filename)
upload_key = os.path.join(S3_BUCKET_KEY_PREFIX, filename)
fs.put_file(lpath=filepath, rpath=os.path.join(S3_BUCKET_NAME, upload_key))
upload_staged_files()
更多信息:
有关 stage_for_label_box
函数的更多信息,请查看源代码。
stage_for_label_studio
功能:
格式化输出,以便上传到 LabelStudio。在运行 stage_for_label_studio
后,您可以将结果写入 JSON 文件,以包含在新的 LabelStudio 项目中。
示例:
import json
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.label_studio import stage_for_label_studio
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
label_studio_data = stage_for_label_studio(elements, text_field="my_text", id_field="my_id")
# 生成的 JSON 文件可直接上传到 LabelStudio
with open("label_studio.json", "w") as f:
json.dump(label_studio_data, f, indent=4)
包含预注释和预测:
annotations
参数是一个列表的列表。如果指定了annotations
,则每个元素必须有一个注释列表。如果元素没有注释,则使用空列表。以下示例展示了如何为 LabelStudio 的“文本分类”任务上传注释:
import json
from unstructured.documents.elements import NarrativeText
from unstructured.staging.label_studio import (
stage_for_label_studio,
LabelStudioAnnotation,
LabelStudioResult,
)
elements = [NarrativeText(text="Narrative")]
annotations = [[
LabelStudioAnnotation(
result=[
LabelStudioResult(
type="choices",
value={"choices": ["Positive"]},
from_name="sentiment",
to_name="text",
)
]
)
]]
label_studio_data = stage_for_label_studio(
elements,
annotations=annotations,
text_field="my_text",
id_field="my_id"
)
with open("label_studio.json", "w") as f:
json.dump(label_studio_data, f, indent=4)
predictions
参数也是一个列表的列表。预测是带有score
值的注释。如果指定了predictions
,则每个元素必须有一个预测列表。如果元素没有预测,则使用空列表。以下示例展示了如何为 LabelStudio 的“文本分类”任务上传预测:
import json
from unstructured.documents.elements import NarrativeText
from unstructured.staging.label_studio import (
stage_for_label_studio,
LabelStudioPrediction,
LabelStudioResult,
)
elements = [NarrativeText(text="Narrative")]
predictions = [[
LabelStudioPrediction(
result=[
LabelStudioResult(
type="choices",
value={"choices": ["Positive"]},
from_name="sentiment",
to_name="text",
)
],
score=0.68
)
]]
label_studio_data = stage_for_label_studio(
elements,
predictions=predictions,
text_field="my_text",
id_field="my_id"
)
with open("label_studio.json", "w") as f:
json.dump(label_studio_data, f, indent=4)
- 以下示例展示了如何为 LabelStudio 的“命名实体识别”任务上传注释:
import json
from unstructured.documents.elements import NarrativeText
from unstructured.staging.label_studio import (
stage_for_label_studio,
LabelStudioAnnotation,
LabelStudioResult,
)
elements = [NarrativeText(text="Narrative")]
annotations = [[
LabelStudioAnnotation(
result=[
LabelStudioResult(
type="labels",
value={"start": 0, "end": 9, "text": "Narrative", "labels": ["MISC"]},
from_name="label",
to_name="text",
)
]
)
]]
label_studio_data = stage_for_label_studio(
elements,
annotations=annotations,
text_field="my_text",
id_field="my_id"
)
with open("label_studio.json", "w") as f:
json.dump(label_studio_data, f, indent=4)
参考:
有关标签和注释的完整选项列表,请参阅 LabelStudio 文档。
更多信息:
有关 stage_for_label_studio
函数的更多信息,请查看源代码。
stage_for_prodigy
功能:
以 JSON 格式格式化输出,以供 Prodigy 使用。运行 stage_for_prodigy
后,您可以将结果写入 JSON 文件,供 Prodigy 使用。
示例:
import json
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.prodigy import stage_for_prodigy
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
metadata = [{"type": "title"}, {"type": "text"}]
prodigy_data = stage_for_prodigy(elements, metadata)
# 生成的 JSON 文件可直接用于 Prodigy
with open("prodigy.json", "w") as f:
json.dump(prodigy_data, f, indent=4)
注意:
Prodigy 建议使用 .jsonl
格式来提供数据给 API 加载器。运行 stage_for_prodigy
后,您可以使用 save_as_jsonl
工具函数,将格式化的数据保存为 .jsonl
文件。
from unstructured.documents.elements import Title, NarrativeText
from unstructured.staging.prodigy import stage_for_prodigy
from unstructured.utils import save_as_jsonl
elements = [Title(text="Title"), NarrativeText(text="Narrative")]
metadata = [{"type": "title"}, {"type": "text"}]
prodigy_data = stage_for_prodigy(elements, metadata)
# 生成的 jsonl 文件可直接用于 Prodigy
save_as_jsonl(prodigy_data, "prodigy.jsonl")
更多信息:
有关 stage_for_prodigy
函数的更多信息,请查看源代码。
stage_for_transformers
功能:
通过将元素拆分为适合模型注意力窗口的块,准备文本元素以供 Transformers 管道处理。
示例:
from transformers import AutoTokenizer, AutoModelForTokenClassification, pipeline
from unstructured.documents.elements import NarrativeText
from unstructured.staging.huggingface import stage_for_transformers
model_name = "hf-internal-testing/tiny-bert-for-token-classification"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForTokenClassification.from_pretrained(model_name)
nlp = pipeline("ner", model=model, tokenizer=tokenizer)
text = """[长文本内容]"""
elements = stage_for_transformers([NarrativeText(text=text)], tokenizer)
可选参数:
buffer
:留作注意力窗口缓冲区的令牌数量,默认是模型需要的特殊令牌数量。max_input_size
:模型的最大输入大小,即注意力窗口大小。如果未指定,默认使用tokenizer
的model_max_length
属性。split_function
:用于将文本拆分为块的函数,默认按空格拆分。chunk_separator
:在重组文本时用于连接块的字符串,默认使用空格。
直接处理文本:
如果需要直接处理文本而不是元素对象,可以使用 chunk_by_attention_window
辅助函数。
from unstructured.staging.huggingface import chunk_by_attention_window
chunks = chunk_by_attention_window(text, tokenizer)
results = [nlp(chunk) for chunk in chunks]
更多信息:
有关 stage_for_transformers
函数的更多信息,请查看源代码。
stage_for_weaviate
功能:
stage_for_weaviate
函数将元素对象列表准备好,以便导入到 Weaviate 向量数据库。
创建 Weaviate 模式:
您可以使用以下步骤在 Weaviate 中为 Unstructured 输出创建模式:
from unstructured.staging.weaviate import create_unstructured_weaviate_class
import weaviate
# 如需更改 Weaviate 中的类名,可修改 `class_name`
unstructured_class = create_unstructured_weaviate_class(class_name="UnstructuredDocument")
schema = {"classes": [unstructured_class]}
client = weaviate.Client("http://localhost:8080")
client.schema.create(schema)
上传数据到 Weaviate:
创建模式后,您可以使用以下流程将文档批量上传到 Weaviate。有关上传和查询数据的更多选项,请参阅 Weaviate 文档。
from unstructured.partition.pdf import partition_pdf
from unstructured.staging.weaviate import stage_for_weaviate
import weaviate
from weaviate.util import generate_uuid5
filename = "example-docs/pdf/layout-parser-paper-fast.pdf"
elements = partition_pdf(filename=filename, strategy="fast")
data_objects = stage_for_weaviate(elements)
client = weaviate.Client("http://localhost:8080")
with client.batch(batch_size=10) as batch:
for data_object in data_objects:
batch.add_data_object(
data_object,
"UnstructuredDocument",
uuid=generate_uuid5(data_object),
)
更多信息:
有关 stage_for_weaviate
函数的更多信息,请查看源代码。
总结
虽然 Unstructured 开源库中的 Staging 函数正在被弃用,但了解它们的使用方式仍有助于您准备数据,以便将其导入到各种下游系统中。通过使用这些函数,您可以将处理后的文档元素格式化为适合不同工具和平台的数据格式,如 LabelStudio、Prodigy、Argilla、Weaviate 等。这有助于在机器学习和数据处理流程中实现更高效的数据集成。
Unstructured 库中的 Chunking(分块)功能
Unstructured 库中的 Chunking(分块)功能利用通过分区(partition)函数检测到的元数据和文档元素,对这些元素进行后处理,生成更有用的“块”(chunks),以适用于诸如检索增强生成(Retrieval Augmented Generation,RAG)等用例。
分块基础
Unstructured 中的分块与您可能熟悉的其他分块机制有所不同。传统方法从文档中提取的纯文本开始,根据纯文本特征(如表示段落边界或列表项边界的字符序列 \n\n
或 \n
)来形成块。
由于 Unstructured 使用了关于每种文档格式的特定知识,将文档划分为语义单元(文档元素),因此只有当单个元素超过所需的最大块大小时,我们才需要使用文本拆分(text-splitting)。除非出现这种情况,所有的块都包含一个或多个完整的元素,保留了在分区过程中建立的语义单元的连贯性。
在讨论细节之前,有几个关于分块的概念值得介绍:
-
分块是在文档元素上执行的。 这是在分区之后、对分区生成的元素执行的单独步骤(尽管它也可以与分区合并为一步完成)。
-
一般来说,分块将连续的元素组合在一起,形成尽可能大的块,但不超过最大块大小。
-
如果单个元素本身就超过了最大块大小,将使用文本拆分将其分为两个或多个块。
-
分块产生一系列
CompositeElement
、Table
或TableChunk
元素。每个“块”都是这三种类型之一的实例。
分块选项
以下选项可用于调整分块行为。这些是可在分区或分块函数调用中使用的关键字参数。所有这些选项都有默认值,只有在需要非默认设置时才需要指定。特定的分块策略(如 by_title
)可能有其他选项。
-
max_characters
:int
(默认值为500
)——块的硬最大大小。没有块会超过此字符数。如果单个元素本身就超过了此大小,将使用文本拆分将其分为两个或多个块。 -
new_after_n_chars
:int
(默认值为max_characters
)——块的“软”最大大小。已经超过此字符数的块将不会被扩展,即使下一个元素可以在不超过硬最大值的情况下适应。这可以与max_characters
结合使用,以设置“首选”大小,例如:“我更喜欢大约 1000 个字符的块,但我宁愿有一个 1500 字符(max_characters
)的块,也不愿使用文本拆分。”这可以通过指定max_characters=1500, new_after_n_chars=1000
来实现。 -
overlap
:int
(默认值为0
)——仅当使用文本拆分来拆分超大块时,包含来自前一个块末尾的此数量字符,作为下一个块的前缀。这可以减轻在任意位置根据文本长度拆分超大元素所带来的影响。 -
overlap_all
:bool
(默认值为False
)——是否在正常的块之间也应用重叠(overlap
),而不仅仅是在使用文本拆分来拆分超大元素时。因为正常的块是由具有清晰语义边界的完整元素组成的,因此此选项可能会“污染”正常的块。您需要根据您的用例来决定此选项是否适合您。
分块的执行
分块可以作为分区的一部分执行,也可以作为分区后单独的步骤执行:
在分区时指定分块策略
通过为 chunking_strategy
参数指定一个值,可以在分区时执行分块。当前的选项有 basic
和 by_title
(下面将详细介绍)。
示例:
from unstructured.partition.html import partition_html
chunks = partition_html(url=url, chunking_strategy="basic")
调用分块函数
分块也可以通过直接调用分块函数在分区后单独执行。例如,在调整分块参数时,这可能很方便。分块通常比分区更快,尤其是在使用 OCR 或推理时,通过分别执行这些步骤,可以实现更快的反馈循环。
示例:
from unstructured.chunking.basic import chunk_elements
from unstructured.partition.html import partition_html
url = "https://understandingwar.org/backgrounder/russian-offensive-campaign-assessment-august-27-2023-0"
elements = partition_html(url=url)
chunks = chunk_elements(elements)
# 或者使用 by_title 策略
from unstructured.chunking.title import chunk_by_title
chunks = chunk_by_title(elements)
for chunk in chunks:
print(chunk)
print("\n\n" + "-"*80)
input()
分块策略
目前有两种分块策略:basic
和 by_title
。by_title
策略与 basic
策略共享大部分行为,因此我们先介绍基础的 basic
策略。
“basic” 分块策略
basic
策略将顺序的元素组合起来,以最大限度地填充每个块,同时遵守指定的 max_characters
(硬最大值)和 new_after_n_chars
(软最大值)选项值。
-
超大元素处理:如果单个元素本身就超过了硬最大值,它将被隔离(不会与其他元素组合),然后使用文本拆分将其分为两个或多个块。
-
表格处理:
Table
元素始终被隔离,永远不会与其他元素组合。Table
也可能是超大的,此时将使用文本拆分将其分为两个或多个TableChunk
元素。 -
重叠处理:如果指定了
overlap
,则在通过拆分超大元素形成的块之间应用重叠;如果overlap_all=True
,则也在其他块之间应用重叠。
“by_title” 分块策略
by_title
分块策略保留了章节边界,甚至还可以选择保留页面边界。这里的“保留”意味着单个块永远不会包含来自两个不同章节的文本。当新章节开始时,现有的块将关闭,并开始一个新块,即使下一个元素可以适应之前的块。
除了具有基本策略的行为外,by_title
策略还有以下行为:
-
检测章节标题:
Title
元素被认为是新章节的开始。当遇到Title
元素时,之前的块将关闭,开始一个新块,即使Title
元素可以适应之前的块。 -
尊重页面边界:可以使用
multipage_sections
参数选择是否尊重页面边界。默认值为True
,表示分页符不会开始新块。将其设置为False
,则将不同页面上的元素分隔到不同的块中。 -
合并小章节:在某些文档中,分区可能会将列表项或其他短段落识别为
Title
元素,即使它们并未作为章节标题。这可能导致块的大小明显小于预期。可以使用combine_text_under_n_chars
参数来缓解此行为。默认值与max_characters
相同,表示将连续的小章节组合起来,以最大限度地填充分块窗口。将其设置为0
将禁用章节合并。
恢复块中的原始元素
通常,块会合并多个文档元素,最大限度地填充所需大小的块。在这种合并中,信息自然会丢失,例如文本的某部分来自哪个元素,以及某些无法始终合并为单个值的元数据(如页面编号和坐标)。
组合成块的原始元素可以通过块的 metadata.orig_elements
字段访问:
示例:
elements = [
Title("Lorem Ipsum"),
NarrativeText("Lorem ipsum dolor sit.")
]
chunk = chunk_elements(elements)[0]
print(chunk.text)
# 输出:'Lorem Ipsum\n\nLorem ipsum dolor sit.'
print(chunk.metadata.orig_elements)
# 输出:[Title("Lorem Ipsum"), NarrativeText("Lorem ipsum dolor sit.")]
这些元素将包含他们所有的原始元数据,因此可以用于访问无法可靠合并的元数据,例如:
{e.metadata.page_number for e in chunk.metadata.orig_elements}
# 可能输出:{2, 3}
[e.metadata.coordinates for e in chunk.metadata.orig_elements]
# 输出:[<CoordinatesMetadata ...>, <CoordinatesMetadata ...>, ...]
[
e.metadata.image_path
for e in chunk.metadata.orig_elements
if e.metadata.image_path is not None
]
# 可能输出:['/tmp/lorem.jpg', '/tmp/ipsum.png']
序列化和反序列化 orig_elements
在序列化过程中,metadata.orig_elements
被压缩为 Base64 的 gzip 格式。要反序列化 metadata.orig_elements
,可以使用 elements_from_base64_gzipped_json
函数。例如:
from unstructured.partition.auto import partition
from unstructured.staging.base import elements_from_base64_gzipped_json
elements = partition('local-ingest-source/fake-email.eml', chunking_strategy='basic', include_orig_elements=True)
print("Before:\n")
for element in elements:
metadata = element.metadata.to_dict()
print(f"Element ID: {element.id}")
print(f" Compressed orig_elements: {metadata['orig_elements']}")
print("\n")
# 输出:
# Before:
#
# Element ID: 083776ca703b1925e5fef69bb2635f1f
# Compressed orig_elements: eJztlM1uGyEUhV8Fzbq2GGbwDFZUZdNFpDaLyOomiix+Lg7tABbcaRtFfffCJFXS...
print("After:\n")
for element in elements:
metadata = element.metadata.to_dict()
print(f"Element ID: {element.id}")
orig_elements = elements_from_base64_gzipped_json(metadata["orig_elements"])
print(f" Uncompressed orig_elements:")
for orig_element in orig_elements:
print(f" {orig_element.category}: {orig_element.text}")
print("\n")
# 输出:
# After:
#
# Element ID: 083776ca703b1925e5fef69bb2635f1f
# Uncompressed orig_elements:
# NarrativeText: This is a test email to use for unit tests.
# Title: Important points:
# ListItem: Roses are red
# ListItem: Violets are blue
总结
Unstructured 库的分块功能利用分区生成的文档元素和元数据,对文档进行后处理,形成更实用的“块”,以适用于诸如 RAG 等用例。通过选择合适的分块策略(basic
或 by_title
)和调整参数,您可以控制块的大小和内容,以满足您的特定需求。此外,您还可以访问块中的原始元素,以获取无法在合并过程中可靠整合的元数据。这使得 Unstructured 库在处理复杂文档、保持语义一致性和满足下游应用需求方面具备强大的灵活性。
Unstructured 库中的 Embedding(嵌入)功能
重要提示: Unstructured 开源库本身不提供调用嵌入服务提供商以获取文本嵌入的内置支持。因此,如果您需要为文本生成嵌入,需要使用其他方法。
替代方案
1. 使用 Unstructured Ingest CLI 和 Unstructured Ingest Python 库
- Unstructured Ingest CLI 和 Unstructured Ingest Python 库在数据摄取(ingest)管道中内置了对嵌入服务提供商的支持。
- 这意味着您可以在数据摄取的过程中,直接调用嵌入服务,为文本生成嵌入向量。
- 您可以参考相关文档,了解如何使用这些工具。
2. 使用第三方工具和库
- 您可以利用 Unstructured 开源库生成的 JSON 文件,其中包含了文档元素的文本内容。
- 然后,使用常见的第三方工具和库(如 Hugging Face、OpenAI 等),为这些文本生成嵌入向量。
- 这种方法灵活性更高,您可以选择适合自己的嵌入模型和服务。
示例:使用 Hugging Face 为文本生成嵌入
下面是一个示例 Python 脚本,演示了如何为 JSON 文件中的每个文档元素生成嵌入向量。
功能概述:
- 输入:由 Unstructured 开源库生成的 JSON 文件(例如
myfile.json
)。 - 处理流程:
- 读取 JSON 文件的内容,将其解析为 JSON 对象。
- 使用 Hugging Face 的
sentence-transformers/all-MiniLM-L6-v2
模型,为每个文档元素的text
字段生成嵌入向量。 - 将生成的嵌入向量添加到对应的文档元素中,作为新的
embeddings
字段。
- 输出:更新后的 JSON 文件,其中每个文档元素都包含了对应的嵌入向量。
示例代码:
# 文件名:embeddings.py
# 安装所需的库:pip install langchain sentence_transformers
import sys
import json
from langchain.embeddings import HuggingFaceEmbeddings
if __name__ == "__main__":
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)
# 获取 JSON 文件的路径
if len(sys.argv) < 2:
print("错误:请指定输入 JSON 文件的路径。")
print("例如:'python embeddings.py myfile.json'")
sys.exit(1)
file_path = sys.argv[1]
try:
# 读取 JSON 文件的内容
with open(file_path, 'r') as file:
file_elements = json.load(file)
# 处理 JSON 文件中的每个元素
for element in file_elements:
# 获取元素的 "text" 字段
text = element["text"]
# 为 "text" 字段生成嵌入向量
query_result = embeddings.embed_query(text)
# 将嵌入向量添加到元素中,作为 "embeddings" 字段
element["embeddings"] = query_result
# 将更新后的 JSON 保存回原始文件
with open(file_path, 'w') as file:
json.dump(file_elements, file, indent=2)
print(f"完成!更新后的 JSON 已保存到 '{file_path}'。")
except FileNotFoundError:
print(f"错误:文件 '{file_path}' 未找到。")
except IOError:
print(f"错误:无法访问文件 '{file_path}'。")
使用步骤:
-
安装依赖库:
在终端或命令行中执行:
pip install langchain sentence_transformers
-
保存脚本:
将上述代码保存为
embeddings.py
。 -
准备 JSON 文件:
使用 Unstructured 开源库处理您的文档,并生成一个 JSON 文件,例如
myfile.json
。 -
运行脚本:
在终端或命令行中执行:
python embeddings.py myfile.json
该脚本将读取
myfile.json
,为每个文档元素的text
生成嵌入向量,并将结果保存回myfile.json
。
其他资源
如果您想了解更多关于如何使用 Python 脚本调用不同的嵌入服务提供商,可以参考以下资源:
- Amazon Bedrock
- Hugging Face
- OctoAI
- OpenAI
- together.ai
- Vertex AI
- Voyage AI
(注:以上列出了常见的嵌入服务提供商,您可以在其官方网站或文档中找到详细的使用方法。)
总结
虽然 Unstructured 开源库本身不支持直接获取文本的嵌入,但通过结合第三方工具和库,您仍然可以为由 Unstructured 库生成的文档元素获取嵌入向量。这对于进一步的自然语言处理任务(例如检索增强生成、文本聚类、语义搜索等)非常有用。
- 如果您希望在摄取管道中直接集成嵌入过程,建议使用 Unstructured Ingest CLI 或 Unstructured Ingest Python 库,它们内置了对嵌入服务提供商的支持。
- 对于需要更高定制化或特定嵌入模型的情况,使用 Python 脚本结合第三方嵌入库是一个灵活的解决方案。
希望以上解释能帮助您更好地理解如何在 Unstructured 库的基础上获取文本嵌入。如果您有更多问题,欢迎进一步咨询。