🚀使用Readability.js清洗HTML内容,打造RAG高质量数据
原文链接:Clean up HTML Content for Retrieval-Augmented Generation with Readability.js
作者:Phil Nash
译者:倔强青铜三
前言
大家好,我是倔强青铜三 。是一名热情的软件工程师,我热衷于分享和传播IT技术,致力于通过我的知识和技能推动技术交流与创新,欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!
从网页抓取内容是为您的 检索增强生成 (RAG) 应用程序获取内容的一种方法。但解析网页内容可能会很麻烦。
Mozilla 的开源库 Readability.js 是提取网页重要部分的有用工具。让我们看看如何将其用作 RAG 应用程序数据摄取管道的一部分。
从网页检索非结构化数据
网页是我们可以在基于 RAG 的应用程序中使用的非结构化数据来源。但网页通常包含许多无关内容,例如页眉、侧边栏和页脚。这些内容对于浏览网站的人来说是有用的上下文,但会分散页面主要内容的注意力。
为了为 RAG 获取最佳数据,我们需要删除无关内容。当您在一个网站内工作时,可以使用像 cheerio 这样的工具根据您对网站结构的了解自行解析 HTML。但如果您要抓取不同布局和设计的页面,则需要一种好的方法来返回相关内容并避免其余部分。
重新利用阅读视图
大多数网络浏览器都带有阅读视图,可以剥离除文章标题和内容之外的所有内容。以下是应用于 DataStax 网站博客文章时浏览器和阅读模式的区别。
Mozilla 将 Firefox 阅读模式的底层库作为独立的开源模块提供:Readability.js。因此,我们可以在数据管道中使用 Readability.js 来剥离无关内容,并从抓取的网页中返回高质量的结果。
如何使用 Node.js 和 Readability.js 抓取数据
让我们看看一个从我之前关于 在 Node.js 中创建向量嵌入 的博客文章中抓取文章内容的示例。以下是您可以用来检索页面 HTML 的一些 JavaScript 代码:
JavaScript
const html = await fetch("https://www.datastax.com/blog/how-to-create-vector-embeddings-in-node-js")
.then((res) => res.text());
console.log(html);
这包括所有 HTML 标签以及导航、页脚、分享链接、行动号召以及大多数网站上的其他内容。
为了改进这一点,您可以安装像 cheerio 这样的模块并仅选择重要部分:
bash
npm install cheerio
JavaScript
import * as cheerio from "cheerio";
const html = await fetch("https://www.datastax.com/blog/how-to-create-vector-embeddings-in-node-js")
.then((res) => res.text());
const $ = cheerio.load(html);
console.log($("h1").text(), "\n");
console.log($("section#blog-content > div:first-child").text());
使用此代码,您可以获得文章的标题和文本。正如我之前所说,如果您了解 HTML 的结构,这非常有用,但情况并不总是如此。
相反,安装 Readability.js 和 jsdom:
bash
npm install @mozilla/readability jsdom
Readability.js 通常在浏览器环境中运行并使用实时文档,而不是 HTML 字符串,因此我们需要在 Node.js 中包含 jsdom 以提供该功能。现在,我们可以将已经加载的 HTML 转换为文档,并将其传递给 Readability.js 以解析内容。
JavaScript
import { Readability } from "@mozilla/readability";
import { JSDOM } from "jsdom";
const url = "https://www.datastax.com/blog/how-to-create-vector-embeddings-in-node-js";
const html = await fetch(url).then((res) => res.text());
const doc = new JSDOM(html, { url });
const reader = new Readability(doc.window.document);
const article = reader.parse();
console.log(article);
当您检查文章时,可以看到它从 HTML 中解析了许多内容。
有标题、作者、摘要、发布时间以及内容和 textContent。textContent 属性是文章的纯文本内容,已准备好让您 将其拆分为块、创建向量嵌入 并 摄取到 Astra DB。content 属性是原始 HTML,包括链接和图像。如果您想提取链接或以某种方式处理图像,这可能会有用。
您可能还希望查看文档是否可能返回良好的结果。阅读视图在文章上效果很好,但对其他类型的内容用处不大。您可以使用 isProbablyReaderable
函数快速检查 HTML 是否适合使用 Readability.js 进行处理。如果该函数返回 false,您可能需要以不同的方式解析 HTML,甚至检查 URL 是否包含对您有用的内容。
JavaScript
const doc = new JSDOM(html, { url });
const reader = new Readability(doc.window.document);
if (reader.isProbablyReaderable(doc.window.document)) {
const article = reader.parse();
console.log(article);
} else {
// 做其他事情
}
如果页面未通过此检查,您可能希望标记 URL 以查看它是否包含对您的 RAG 应用程序有用的信息,或者是否应将其排除。
使用 Readability 与 LangChain.js
如果您的应用程序使用LangChain.js,您也可以使用 Readability.js 返回 HTML 页面的内容。它非常适合您的数据摄取管道,并与其他 LangChain 组件一起使用,例如 文本分块器 和 向量存储。
以下示例使用 LangChain.js 加载上述相同页面,使用 MozillaReadabilityTransformer 返回页面的相关内容,使用 RecursiveCharacterTextSplitter 将文本拆分为块,使用 OpenAI 创建向量嵌入,并将数据存储在 Astra DB 中。
您需要安装以下依赖项:
bash
npm install @langchain/core @langchain/community @langchain/openai @datastax/astra-db-ts @mozilla/readability jsdom
要运行示例,您需要创建一个 Astra DB 数据库,并将数据库的端点和应用程序令牌存储在您的环境中,分别为 ASTRA_DB_APPLICATION_TOKEN
和 ASTRA_DB_API_ENDPOINT
。您还需要一个存储在环境中的 OpenAI API 密钥,名为 OPENAI_API_KEY
。
导入依赖项:
JavaScript
import { HTMLWebBaseLoader } from "@langchain/community/document_loaders/web/html";
import { MozillaReadabilityTransformer } from "@langchain/community/document_transformers/mozilla_readability";
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { OpenAIEmbeddings } from "@langchain/openai";
import { AstraDBVectorStore } from "@langchain/community/vectorstores/astradb";
我们使用 HTMLWebBaseLoader
从我们提供的 URL 加载原始 HTML。HTML 然后通过 MozillaReadabilityTransformer
提取文本,随后由 RecursiveCharacterTextSplitter
将其拆分为块。最后,我们创建一个嵌入提供程序和一个 Astra DB 向量存储,用于将文本块转换为向量嵌入并存储在向量数据库中。
JavaScript
const loader = new HTMLWebBaseLoader("https://www.datastax.com/blog/how-to-create-vector-embeddings-in-node-js");
const transformer = new MozillaReadabilityTransformer();
const splitter = new RecursiveCharacterTextSplitter({
maxCharacterCount: 1000,
chunkOverlap: 200,
});
const embeddings = new OpenAIEmbeddings({
model: "text-embedding-3-small",
});
const vectorStore = new AstraDBVectorStore(embeddings, {
token: process.env.ASTRA_DB_APPLICATION_TOKEN,
endpoint: process.env.ASTRA_DB_API_ENDPOINT,
collection: "content",
collectionOptions: {
vector: {
dimension: 1536,
metric: "cosine",
},
},
});
await vectorStore.initialize();
所有组件的初始化构成了大部分工作。一旦一切设置完成,您可以像这样加载、转换、拆分、嵌入和存储文档:
JavaScript
const docs = await loader.load();
const sequence = transformer.pipe(splitter);
const vectorizedDocs = await sequence.invoke(docs);
await vectorStore.addDocuments(vectorizedDocs);
使用 Readability.js 更准确地抓取网页数据
Readability.js 是一个经过实战考验的库,为 Firefox 的阅读模式提供支持,我们可以使用它仅从网页中抓取相关数据。这清理了网页内容,使其对 RAG 更加有用。
正如我们所见,您可以直接使用该库,或者使用 LangChain.js 和 MozillaReadabilityTransformer
。
从网页获取数据只是您摄取管道的第一步。从这里,您需要将文本拆分为块,创建向量嵌入,并将所有内容存储在 Astra DB 中。然后,您就可以构建您的 RAG 驱动应用程序了。
最后感谢阅读!欢迎关注我,微信公众号 :
倔强青铜三
。欢迎点赞
、收藏
、关注
,一键三连!!!