LangChain4j 提供了一套丰富的 API,用于构建从简单到高级的检索增强生成(RAG)系统。这些 API 覆盖了从文档加载、预处理、嵌入到检索的全过程,使得开发者可以灵活地构建智能问答系统。以下是 Core RAG APIs 的核心组件及其功能的总结
这篇文章内容比较多,请分章节阅读,对做RAG非常有用
Core RAG APIs
LangChain4j 提供了一系列丰富的 API,帮助你构建从简单到高级的自定义 RAG 管道。以下是主要的领域类和 API。
1 Document(文档)
Document 类表示一个完整的文档,如单个 PDF 文件或网页。目前,Document 仅支持文本信息,但未来将支持图像和表格。
Metadata.from(Map):从一个 Map 创建 Metadata。
Metadata.put(String key, String value) / put(String, int) / 等等:向 Metadata 中添加一个条目。
Metadata.getString(String key) / getInteger(String key) / 等等:返回 Metadata 条目的值,并将其转换为所需的类型。
Metadata.containsKey(String key):检查 Metadata 是否包含指定键的条目。
Metadata.remove(String key):通过键从 Metadata 中移除一个条目。
Metadata.copy():返回 Metadata 的一个副本。
Metadata.toMap():将 Metadata 转换为一个 Map。
2 Metadata(元数据)
Metadata的概念
每个 Document 都包含 Metadata。它存储了关于文档的元信息,例如文档的名称、来源、最后更新日期、所有者,或其他任何相关的细节。
Metadata 以键值对的形式存储,其中键是 String
类型,值可以是以下类型之一:String、Integer、Long、Float、Double。
Metadata 是一种键值对存储结构,用于描述文档的元信息。这些元信息可以包括但不限于:
- 文档的名称(name)
- 文档的来源(source)
- 文档的最后更新日期(lastUpdateDate)
- 文档的所有者(owner)
- 其他任何相关的细节
Metadata 的用途有多个方面:
-
增强 LLM 的理解:
当将文档内容传递给语言模型时,Metadata 中的信息(如文档名称和来源)可以被包含在提示中,帮助语言模型更好地理解文档的上下文。
例如,如果文档的来源是一个特定的网站或作者,这些信息可以帮助语言模型生成更准确的回答。 -
过滤和搜索:
在检索相关文档时,可以通过 Metadata 条目进行过滤。例如,你可以通过 owner 字段将搜索范围限制为特定用户的所有文档。
这种过滤机制可以提高检索的效率和准确性。 -
同步更新:
当文档的来源(如网页或文件)被更新时,可以通过 Metadata 中的标识符(如 id 或 source)快速定位到对应的文档,并在嵌入存储(EmbeddingStore)中进行更新,以保持数据的一致性。
有用的元数据方法:
- Metadata.from(Map):从一个 Map 创建 Metadata。
- Metadata.put(String key, String value) / put(String, int) / 等等:向 Metadata 中添加一个条目。
- Metadata.getString(String key) / getInteger(String key) / 等等:返回 Metadata 条目的值,并将其转换为所需的类型。
- Metadata.containsKey(String key):检查 Metadata 是否包含指定键的条目。
- Metadata.remove(String key):通过键从 Metadata 中移除一个条目。
- Metadata.copy():返回 Metadata 的一个副本。
- Metadata.toMap():将 Metadata 转换为一个 Map。
Metadata 是 LangChain4j 中的一个重要组件,用于存储和管理文档的元信息。它通过提供丰富的操作方法,使得开发者可以灵活地处理文档的上下文信息,从而提高语言模型的理解能力和检索效率。通过合理使用 Metadata,开发者可以构建更加智能和高效的问答系统。
3 Document Loader(文档加载器)
LangChain4j 提供的多种文档加载器(DocumentLoader),这些加载器用于从不同的数据源加载文档。文档加载器是构建智能问答系统时非常重要的组件,因为它们负责将文档数据导入到系统中,以便后续进行处理和检索。以下是每个加载器的详细解析:
1. FileSystemDocumentLoader
从本地文件系统加载文档。它支持从指定路径加载单个文件或整个目录中的文件。
- 用途:适用于本地存储的文档,例如 PDF、TXT、HTML 等。
- 示例:
// 加载单个文件
Document document = FileSystemDocumentLoader.loadDocument("/path/to/file.txt");
// 加载整个目录中的所有文件
List<Document> documents = FileSystemDocumentLoader.loadDocuments("/path/to/directory");
2. ClassPathDocumentLoader
从类路径(classpath)加载文档。它允许你加载存储在项目资源文件夹中的文档。
- 用途:适用于开发和测试阶段,尤其是当文档存储在项目的资源文件夹中时。
- 示例:
// 加载类路径中的文件
Document document = ClassPathDocumentLoader.loadDocument("resources/file.txt");
3. UrlDocumentLoader
从 URL 加载文档。它支持从网络地址加载文档,例如网页或在线文件。
- 用途:适用于从互联网加载文档,例如从博客、新闻网站或在线文档库加载内容。
- 示例:
// 加载网页内容
Document document = UrlDocumentLoader.loadDocument("https://example.com/page.html");
4. AmazonS3DocumentLoader
从 Amazon S3 存储桶加载文档。它支持从 AWS S3 存储桶加载文件。
- 用途:适用于使用 AWS S3 存储文档的场景。
- 示例:
// 加载 S3 存储桶中的文件
Document document = AmazonS3DocumentLoader.loadDocument("s3://bucket-name/path/to/file.txt");
5. AzureBlobStorageDocumentLoader
从 Azure Blob Storage 加载文档。它支持从 Azure Blob 存储加载文件。
- 用途:适用于使用 Azure Blob Storage 存储文档的场景。-
- 示例:
// 加载 Azure Blob 存储中的文件
Document document = AzureBlobStorageDocumentLoader
.loadDocument("azure://container-name/path/to/file.txt");
6. GitHubDocumentLoader
从 GitHub 仓库加载文档。它支持从 GitHub 仓库加载文件或整个目录。
- 用途:适用于从 GitHub 仓库加载文档,例如开源项目文档或代码注释。
- 示例:
// 加载 GitHub 仓库中的文件
Document document = GitHubDocumentLoader
.loadDocument("https://github.com/user/repo/path/to/file.txt");
7. GoogleCloudStorageDocumentLoader
从 Google Cloud Storage 加载文档。它支持从 Google Cloud Storage 存储桶加载文件。
- 用途:适用于使用 Google Cloud Storage 存储文档的场景。
- 示例:
// 加载 Google Cloud Storage 存储桶中的文件
Document document = GoogleCloudStorageDocumentLoader.loadDocument("gs://bucket-name/path/to/file.txt");
8. SeleniumDocumentLoader
使用 Selenium 从网页加载文档。它支持从动态生成的网页加载内容,例如需要 JavaScript 渲染的页面。
- 用途:适用于加载需要动态渲染的网页内容。
- 示例:
// 加载动态网页内容
Document document = SeleniumDocumentLoader.loadDocument("https://example.com/dynamic-page");
9. TencentCosDocumentLoader
从腾讯云 COS(Cloud Object Storage)加载文档。它支持从腾讯云 COS 存储桶加载文件。
- 用途:适用于使用腾讯云 COS 存储文档的场景。
- 示例:
// 加载腾讯云 COS 存储桶中的文件
Document document = TencentCosDocumentLoader
.loadDocument("cos://bucket-name/path/to/file.txt");
4 Document Parser(文档解析器)
LangChain4j 中的 DocumentParser 接口及其多种实现。DocumentParser 的作用是从各种文件格式中提取文本内容,以便后续处理和分析
DocumentParser 接口用于解析不同格式的文件,如 PDF、DOC、TXT 等。LangChain4j 提供了多种实现,例如 ApacheTikaDocumentParser 可以自动检测和解析几乎所有文件格式。
LangChain4j 提供了多种 DocumentParser 实现,支持从不同格式的文件中提取文本内容。这些解析器包括:
- TextDocumentParser:适用于纯文本文件。
- ApachePdfBoxDocumentParser:适用于 PDF 文件。
- ApachePoiDocumentParser:适用于 Microsoft Office 文件。
- ApacheTikaDocumentParser:适用于多种文件格式。
通过合理选择和使用这些解析器,开发者可以灵活地处理各种文档格式,从而为后续的文档处理和检索提供支持。此外,LangChain4j 还支持通过 SPI 自动加载默认解析器,简化了开发流程
1. TextDocumentParser
TextDocumentParser 是一个简单的解析器,用于解析纯文本格式的文件,例如 TXT、HTML 和 Markdown(MD)文件。
- 用途:适用于简单文本文件,尤其是那些不需要复杂解析的文件。
- 示例:
Document document = FileSystemDocumentLoader
.loadDocument("/path/to/file.txt", new TextDocumentParser());
2. ApachePdfBoxDocumentParser
ApachePdfBoxDocumentParser 使用 Apache PDFBox 库来解析 PDF 文件。
- 用途:适用于 PDF 文件,能够提取文本内容。
- 示例:
Document document = FileSystemDocumentLoader
.loadDocument("/path/to/file.pdf", new ApachePdfBoxDocumentParser());
3. ApachePoiDocumentParser
ApachePoiDocumentParser 使用 Apache POI 库来解析 Microsoft Office 文件格式,例如 DOC、DOCX、PPT、PPTX、XLS 和 XLSX。
- 用途:适用于 Microsoft Office 文件,能够提取文本内容。
- 示例:
Document document = FileSystemDocumentLoader.loadDocument("/path/to/file.docx", new ApachePoiDocumentParser());
4. ApacheTikaDocumentParser
ApacheTikaDocumentParser 使用 Apache Tika 库来自动检测并解析几乎所有现有的文件格式。
- 用途:适用于多种文件格式,尤其是当不确定文件类型时。
- 示例:
Document document = FileSystemDocumentLoader
.loadDocument("/path/to/file.unknown", new ApacheTikaDocumentParser());
5 Document Transformer(文档转换器)
DocumentTransformer 的实现可以执行多种文档转换操作,包括:
- 清理(Cleaning):从文档的文本中移除不必要的噪声,这可以节省令牌(tokens)并减少干扰。
- 过滤(Filtering):从搜索中完全排除特定的文档。
- 丰富(Enriching):向文档中添加额外信息,以潜在地增强搜索结果。
- 总结(Summarizing):对文档进行总结,并将其简短的总结存储在元数据中。稍后,这些总结可以被包含在每个 TextSegment 中(我们将在下面讨论),以潜在地改善搜索效果。
- 等等。
在这个阶段,也可以添加、修改或删除元数据条目。
目前,LangChain4j 提供的现成实现只有 langchain4j-document-transformer-jsoup 模块中的 HtmlToTextDocumentTransformer,它可以从未加工的 HTML 中提取所需的文本内容和元数据条目。
由于没有一种放之四海而皆准的解决方案,我们建议根据你的独特数据实现自己的 DocumentTransformer。
1. 清理(Cleaning)
功能:从文档的文本中移除不必要的噪声,例如多余的空格、HTML 标签、特殊字符等。
目的:
- 节省令牌:减少文档的大小,从而节省在语言模型中使用的令牌数量。
- 减少干扰:提高文档的可读性和语言模型的理解能力。
示例:
Document document = new Document("This is a sample document with unnecessary noise. \n\n");
document = new CleaningDocumentTransformer().transform(document);
2. 过滤(Filtering)
功能:从搜索结果中完全排除特定的文档。
目的:
- 提高相关性:确保搜索结果只包含与查询相关的文档。
- 节省资源:避免处理无关的文档,节省计算资源。
示例:
List<Document> documents = ...; // 从某个来源加载的文档列表
documents = new FilteringDocumentTransformer()
.transform(documents);
3. 丰富(Enriching)
功能:向文档中添加额外信息,例如关键词、摘要、来源等。
目的:
- 增强搜索结果:通过添加更多上下文信息,提高文档在搜索中的相关性。
- 提供更多信息:为语言模型提供更多背景信息,帮助其生成更准确的回答。
示例:
Document document = new Document("This is a sample document.");
document = new EnrichingDocumentTransformer()
.transform(document);
4. 总结(Summarizing)
功能:对文档进行总结,并将总结存储在元数据中。
目的:
- 提高效率:通过总结,语言模型可以更快地理解文档的核心内容。
- 改善搜索:总结可以被包含在每个 TextSegment 中,从而提高搜索的准确性。
示例:
Document document = new Document("This is a long document with detailed information.");
document = new SummarizingDocumentTransformer().transform(document);
String summary = document.getMetadata()