257-LangChain框架的TextSplitter - HTMLHeaderTextSplitter

案例目标

本案例旨在介绍和演示 HTMLHeaderTextSplitter 的使用方法,这是一种"结构感知"的文本分块生成器,它在元素级别分割文本,并为每个标题添加元数据,类似于 MarkdownHeaderTextSplitter。通过本案例,您将学习如何:

  • 使用 HTMLHeaderTextSplitter 按 HTML 标题分割文本
  • 为分割后的文本块添加相关的元数据
  • 将 HTMLHeaderTextSplitter 与其他分割器结合使用
  • 从网页 URL 加载 HTML 内容并进行分割处理
  • 了解 HTMLHeaderTextSplitter 的局限性

技术栈与核心依赖

  • LangChain: 核心框架,提供文本分割功能
  • langchain_text_splitters: 提供各种文本分割器实现
  • langchain_opentutorial: 环境设置和实用工具
  • HTML 解析: 用于解析 HTML 结构和标题标签

环境配置

在开始之前,需要安装必要的依赖包:

# 安装 langchain-opentutorial 包
%pip install langchain langchain-opentutorial

# 安装所需的其他依赖包
from langchain_opentutorial import package

package.install(
    [
        "langsmith",
        "langchain",
        "langchain_core",
        "langchain_community",
        "langchain_text_splitters",
        "langchain_openai",
    ]
)

设置环境变量:

from langchain_opentutorial import set_env

set_env(
    {
        "OPENAI_API_KEY": "",
        "LANGCHAIN_API_KEY": "",
        "LANGCHAIN_TRACING_V2": "true",
        "LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com",
        "LANGCHAIN_PROJECT": "RecursiveJsonSplitter",
    }
)

案例实现

1. 使用 HTML 字符串

首先,我们演示如何使用 HTML 字符串创建 HTMLHeaderTextSplitter 并分割文本:

from langchain_text_splitters import HTMLHeaderTextSplitter

html_string = """
<!DOCTYPE html>
<html>
<body>
    <div>
        <h1>Header 1</h1>
        <p>Text included in Header 1</p>
        <div>
            <h2>Header 2-1 Title</h2>
            <p>Text included in Header 2-1</p>
            <h3>Header 3-1 Title</h3>
            <p>Text included in Header 3-1</p>
            <h3>Header 3-2 Title</h3>
            <p>Text included in Header 3-2</p>
        </div>
        <div>
            <h2>Header 2-2 Title</h2>
            <p>Text included in Header 2-2</p>
        </div>
        <br>
        <p>Last content</p>
    </div>
</body>
</html>
"""

headers_to_split_on = [
    ("h1", "Header 1"),  # 指定要分割的标题标签及其名称
    ("h2", "Header 2"),
    ("h3", "Header 3"),
]

# 创建 HTMLHeaderTextSplitter 对象,根据指定的标题分割 HTML 文本
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# 分割 HTML 字符串并将结果存储在 html_header_splits 变量中
html_header_splits = html_splitter.split_text(html_string)
# 打印分割结果
for header in html_header_splits:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

输出结果:

Header 1
{'Header 1': 'Header 1'}
=====================
Text included in Header 1
{'Header 1': 'Header 1'}
=====================
Header 2-1 Title
{'Header 1': 'Header 1', 'Header 2': 'Header 2-1 Title'}
=====================
Text included in Header 2-1
{'Header 1': 'Header 1', 'Header 2': 'Header 2-1 Title'}
=====================
Header 3-1 Title
{'Header 1': 'Header 1', 'Header 2': 'Header 2-1 Title', 'Header 3': 'Header 3-1 Title'}
=====================
Text included in Header 3-1
{'Header 1': 'Header 1', 'Header 2': 'Header 2-1 Title', 'Header 3': 'Header 3-1 Title'}
=====================
Header 3-2 Title
{'Header 1': 'Header 1', 'Header 2': 'Header 2-1 Title', 'Header 3': 'Header 3-2 Title'}
=====================
Text included in Header 3-2
{'Header 1': 'Header 1', 'Header 2': 'Header 2-1 Title', 'Header 3': 'Header 3-2 Title'}
=====================
Header 2-2 Title
{'Header 1': 'Header 1', 'Header 2': 'Header 2-2 Title'}
=====================
Text included in Header 2-2  
Last content
{'Header 1': 'Header 1'}
=====================

2. 与其他分割器结合使用并从网页 URL 加载 HTML

接下来,我们演示如何从网页 URL 加载 HTML 内容,然后通过管道将其与其他分割器连接处理:

from langchain_text_splitters import RecursiveCharacterTextSplitter

url = "https://plato.stanford.edu/entries/goedel/"  # 指定要分割的文本的 URL

headers_to_split_on = [  # 指定要分割的 HTML 标题标签及其名称
    ("h1", "Header 1"),
    ("h2", "Header 2"),
    ("h3", "Header 3"),
    ("h4", "Header 4"),
]

# 创建 HTMLHeaderTextSplitter 对象,根据指定的 HTML 标题分割文本
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

# 从 URL 获取文本并根据 HTML 标题进行分割
html_header_splits = html_splitter.split_text_from_url(url)

chunk_size = 500  # 指定将文本分割成的块的大小
chunk_overlap = 30  # 指定块之间的重叠字符数
text_splitter = RecursiveCharacterTextSplitter(  # 创建 RecursiveCharacterTextSplitter 对象以递归分割文本
    chunk_size=chunk_size, chunk_overlap=chunk_overlap
)

# 将按 HTML 标题分割的文本分割为指定大小的块
splits = text_splitter.split_documents(html_header_splits)

# 打印分割文本的第 80 到 85 块
for header in splits[80:85]:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

3. HTMLHeaderTextSplitter 的局限性

HTMLHeaderTextSplitter 尝试处理 HTML 文档之间的结构差异,但有时可能会遗漏特定的标题。

例如,该算法假设标题总是在相关文本"上方"的节点中,即在前一个兄弟节点、祖先节点及其组合中。

在以下新闻文章中(截至撰写时),头条文本被标记为"h1",但它位于与我们期望的文本元素不同的子树中。

因此,与"h1"元素相关的文本不会出现在块元数据中,但如果适用,与"h2"相关的文本会出现。

# 指定要分割的 HTML 页面的 URL
url = "https://www.cnn.com/2023/09/25/weather/el-nino-winter-us-climate/index.html"

headers_to_split_on = [
    ("h1", "Header 1"),  # 指定要分割的标题标签及其名称
    ("h2", "Header 2"),  # 指定要分割的标题标签及其名称
]

# 创建 HTMLHeaderTextSplitter 对象,根据指定的标题分割 HTML 文本
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

# 从指定的 URL 分割 HTML 页面并将结果存储在 html_header_splits 变量中
html_header_splits = html_splitter.split_text_from_url(url)

# 打印分割结果
for header in html_header_splits:
    print(f"{header.page_content[:100]}")
    print(f"{header.metadata}", end="\n=====================\n")

输出结果:

CNN values your feedback  
1. How relevant is this ad to you?  
2. Did you encounter any technical i
{}
=====================
An El Niño winter is coming. Here's what that could mean for the US
{'Header 1': 'An El Niño winter is coming. Here's what that could mean for the US'}
=====================
By  , CNN Meteorologist  
Mary Gilbert  
3 minute read  
Published
        4:44 AM EDT, Mon Septembe
{'Header 1': 'An El Niño winter is coming. Here's what that could mean for the US'}
=====================
What could this winter look like?
{'Header 1': 'An El Niño winter is coming. Here's what that could mean for the US', 'Header 2': 'What could this winter look like?'}
=====================
No two El Niño winters are the same, but many have temperature and precipitation trends in common.  
{}
=====================

案例效果

通过使用 HTMLHeaderTextSplitter,我们实现了以下效果:

  • 成功将 HTML 文档按标题结构分割成多个文本块
  • 为每个文本块添加了包含标题层次结构的元数据
  • 能够处理嵌套的 HTML 结构,保留标题层次关系
  • 可以与其他分割器(如 RecursiveCharacterTextSplitter)结合使用,进一步细化文本块
  • 能够直接从网页 URL 加载 HTML 内容并进行处理

注意: HTMLHeaderTextSplitter 可能无法处理所有 HTML 结构,特别是当标题不在相关文本的上方节点时,可能会导致元数据不完整。

案例实现思路

本案例的实现基于以下思路:

  1. 结构感知分割: HTMLHeaderTextSplitter 不是简单地按字符或行数分割文本,而是基于 HTML 文档的结构(标题层次)进行分割,这样可以保留文档的语义结构。
  2. 元数据丰富: 为每个分割的文本块添加元数据,记录该块所属的标题层次结构,这样可以在后续处理中保留上下文信息。
  3. 灵活性: 允许用户指定要分割的标题标签(h1, h2, h3 等)及其在元数据中的名称,提供了灵活性。
  4. 组合使用: 可以与其他分割器结合使用,先按结构分割,再按大小分割,实现更精细的文本处理。
  5. 直接网页处理: 提供直接从 URL 加载 HTML 内容的功能,方便处理在线文档。

扩展建议

基于本案例,可以考虑以下扩展方向:

  • 自定义元数据处理: 开发自定义的元数据处理逻辑,例如提取更多 HTML 属性或添加自定义标签。
  • 多语言支持: 扩展对非英语 HTML 文档的支持,处理不同语言的标题结构。
  • 性能优化: 对于大型 HTML 文档,优化分割性能,例如使用流式处理或并行处理。
  • 与其他数据源集成: 将 HTMLHeaderTextSplitter 与其他数据源(如数据库、API)集成,实现更复杂的数据处理流程。
  • 可视化工具: 开发可视化工具,展示 HTML 文档的结构和分割结果,帮助用户更好地理解分割过程。
  • 错误处理增强: 增强对不规范 HTML 文档的错误处理能力,提高分割的鲁棒性。

总结

HTMLHeaderTextSplitter 是 LangChain 中一个强大的文本分割工具,它能够基于 HTML 文档的结构进行智能分割,并为每个文本块添加丰富的元数据。通过本案例,我们学习了如何使用 HTMLHeaderTextSplitter 处理 HTML 字符串和网页内容,以及如何与其他分割器结合使用。

这种结构感知的分割方法特别适用于处理具有明确层次结构的文档,如技术文档、学术论文和新闻文章等。通过保留文档的结构信息,HTMLHeaderTextSplitter 可以帮助我们在后续的自然语言处理任务中更好地理解和利用文本的上下文关系。

尽管 HTMLHeaderTextSplitter 有一些局限性,特别是在处理非标准 HTML 结构时,但它仍然是处理 HTML 文档的有用工具,可以大大提高文本分割的质量和效率。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值