文档存储


Flowise的文档存储服务提供了一种灵活的数据管理方式,使您能够在单一位置上传、拆分和准备数据集,并进行更新操作。

这种集中式方法简化了数据处理,并能够高效管理各种数据格式,从而使得在Flowise应用中组织和访问数据变得更加容易。

设置

在本教程中,我们将构建一个检索增强生成(RAG)系统,用于检索有关“LibertyGuard Deluxe Homeowners Policy”的信息,而大型语言模型(LLM)并未对此主题进行过广泛训练。

通过使用Flowise文档存储,我们将准备并更新有关LibertyGuard及其家庭保险政策的数据。这将使我们的RAG系统能够准确回答用户关于LibertyGuard家庭保险产品的查询。

1. 添加文档库

首先,添加一个文档库并为其命名。在我们的示例中,将其命名为“LibertyGuard Deluxe Homeowners Policy”。

2. 选择文档加载器

进入您刚刚创建的文档库,并选择您想要使用的文档加载器。在我们的示例中,由于我们的数据集是PDF格式的,我们将使用PDF加载器

文档加载器是专门处理各种文档格式摄入的节点。

3. 准备数据

步骤1:文档加载器

  • 首先,我们从上传PDF文件开始。

  • 然后,我们添加一个唯一的元数据键。这是可选的,但这是一个好习惯,因为如果需要的话,它允许我们在后续操作中定位和筛选这个相同的数据集。

  • 每个加载器都带有预配置的元数据,在某些情况下,您可以使用“省略元数据键”来移除不必要的元数据。

步骤2:文本分割器

  • 选择您想要用来对数据进行分块的文本分割器。在我们的特定情况下,我们将使用递归字符文本分割器

  • 分词器用于将加载的文档分割成更小的片段、文档或块。这是一个至关重要的预处理步骤,主要有两个原因:

    检索速度与相关性:在向量数据库中将大型文档作为单个实体进行存储和查询,可能会导致检索速度较慢,且检索结果的相关性可能较低。将文档拆分为更小的块可以进行更有针对性的检索。通过对更小、更集中的信息单元进行查询,我们可以实现更快的响应速度,并提高检索结果的准确性。

    • 成本效益高:由于我们仅检索相关片段而非整个文档,因此大型语言模型(LLM)处理的标记数量显著减少。这种有针对性的检索方法直接降低了我们大型语言模型的使用成本,因为计费通常基于标记消耗。通过最大限度地减少发送给大型语言模型的不相关信息量,我们也实现了成本优化。

    文本切分策略有多种,包括:

    • 字符文本分割:将文本分割成固定字符数的大块。这种方法虽然直接,但可能会将单词或短语分割到不同的大块中,从而可能破坏上下文。

    • 词元文本分割:根据所选嵌入模型特定的词边界或词元化方案对文本进行分割。这种方法通常会得到语义上更为连贯的片段,因为它保留了词边界并考虑了文本的底层语言结构。

    • 递归式字符文本分割:该策略旨在将文本分割成保持语义连贯且大小在指定限制范围内的块。它特别适用于具有嵌套部分或标题的层级结构文档。与盲目地在字符限制处进行分割不同,该策略会递归分析文本以找到逻辑断点,如句子结尾或部分分隔。这种方法确保每个块都代表一个有意义的信息单元,即使它略微超出了目标大小。

    • Markdown文本分割器:该分割器专为Markdown格式的文档设计,可根据Markdown标题和结构元素对文本进行逻辑分割,生成与文档中逻辑部分相对应的区块。

    • 代码文本分割器:该策略专为分割代码文件而设计,它考虑了代码结构、函数定义以及其他特定于编程语言的元素,以创建有意义的块,这些块适用于代码搜索和文档编制等任务。

    • HTML到Markdown文本分割器:这款专用分割器首先将HTML内容转换为Markdown,然后应用Markdown文本分割器,从而实现对网页和其他HTML文档的结构化分割。

    您还可以自定义以下参数:

    • 块大小(Chunk Size):每个块所期望的最大大小,通常以字符或词元为单位。

    • 块重叠:连续块之间重叠的字符或标记的数量,有助于保持块间的上下文连贯性。

信息提示框 在本指南中,我们设置了较大的数据块重叠大小,以确保数据块之间不会遗漏任何相关数据。然而,最佳的重叠大小取决于数据的复杂性。您可能需要根据特定的数据集以及您想要提取的信息性质来调整此值。 {% 结束提示 %}

4. 预览数据

我们现在可以预览使用当前的文本分割器配置(chunk_size=1500chunk_overlap=750)将如何对数据进行分块。

尝试不同的文本分割器、分块大小和重叠值,以找到适合您特定数据集的最佳配置,这一点非常重要。此预览功能可让您优化分块过程,并确保生成的块适合您的检索增强生成(RAG)系统。

{% 提示 样式="信息" %}

请注意,我们的自定义元数据company: "liberty"已被插入到每个数据块中。即使我们对其他数据集使用相同的向量存储索引,这些元数据也能让我们在后续操作中轻松过滤和检索此特定数据集中的信息。

理解块重叠

在基于向量的检索和大型语言模型(LLM)查询的背景下,块重叠在保持上下文连续性提高响应准确性方面发挥着重要作用,尤其是在处理有限检索深度或top K(即根据查询从向量存储中检索到的最相似块的最大数量参数)时。

在查询处理过程中,大型语言模型(LLM)会对向量存储执行相似性搜索,以检索与给定查询语义最相关的数据块。如果检索深度(由top K参数表示)设置为较小的值(默认为4),则大型语言模型最初将仅使用这4个数据块中的信息来生成其响应。

这种情况给我们带来了一个问题,因为仅依赖数量有限且无重叠的块可能会导致答案不完整或不准确,尤其是在处理需要跨多个块的信息查询时。

块重叠有助于解决这个问题,因为它确保了连续块之间共享一部分文本上下文,从而增加了检索到的块中包含给定查询所有相关信息的可能性

换言之,这种重叠充当了块与块之间的桥梁,使大型语言模型(LLM)即使在仅限于检索到的一小部分块(前K个)时,也能访问更广泛的上下文窗口。如果查询涉及的概念或信息超出了一个单一的块,重叠区域增加了捕获所有必要上下文的可能性。

因此,在文本分割阶段引入语块重叠,我们增强了大型语言模型(LLM)的以下能力:

  1. 保持上下文连贯性:重叠的语块使得连续段落之间的信息过渡更为流畅,从而使模型对文本的理解更为连贯。

  2. 提高检索准确性:通过增加在目标前K个检索结果中捕获所有相关信息的概率,重叠有助于提供更准确且更符合上下文的响应。

准确性与成本

因此,为了进一步优化检索准确性与成本之间的权衡,可以采用两种主要策略:

  1. 增加/减少分块重叠率:在文本分割过程中调整重叠率,可以对分块之间的共享上下文数量进行精细控制。较高的重叠率通常能更好地保留上下文,但也可能增加成本,因为需要使用更多的分块来涵盖整个文档。相反,较低的重叠率可以降低成本,但可能会丢失分块之间的关键上下文信息,从而导致大型语言模型(LLM)的回答不够准确或不完整。

  2. 增加/减少Top K值:提高默认的Top K值(4)会扩大生成响应时考虑的块数范围。虽然这可以提高准确性,但也会增加成本。

提示:最佳重叠前K值的选择取决于诸多因素,如文档复杂性、嵌入模型特性以及准确性与成本之间的预期平衡。对这些值进行实验对于找到满足特定需求的理想配置至关重要。

  1. 处理您的数据

一旦你对分块过程感到满意,就该处理你的数据了。

处理完数据后,您仍然可以通过删除或添加内容来细化各个数据块。这种精细控制具有多个优势:

  • 提高准确性:识别并纠正原始数据中的不准确或不一致之处,确保应用程序中使用的信息可靠。

  • 提高相关性:优化内容块以突出关键信息,并删除无关部分,从而提高检索过程的精确度和有效性。

  • 查询优化:调整数据块以更好地匹配预期的用户查询,使其更具针对性,并提升整体用户体验。

  1. 配置更新插入流程

在通过文档加载器正确处理并加载数据,且对数据进行适当分块后,我们现在可以开始配置更新插入(upsert)流程。

更新插入(upsert)过程包括三个基本步骤:

  • 嵌入表示:我们首先选择合适的嵌入模型来对我们的数据集进行编码。该模型会将我们的数据转换为数值向量表示。

  • **向量存储(Vector Store):**接下来,我们要确定数据集将驻留的向量存储位置。

  • **记录管理器(可选):**最后,我们还可以选择实现一个记录管理器。该组件提供了在数据集存储到矢量存储中后对其进行管理的功能。

步骤1:选择嵌入

点击“选择嵌入”卡片,并选择您偏好的嵌入模型。在我们的示例中,我们将选择OpenAI作为嵌入提供者,并使用维度为“1536”的“text-embedding-ada-002”模型。

嵌入是将文本转换为能够捕捉其含义的数值表示的过程。这种数值表示,也称为嵌入向量,是一个多维数组,其中每一维都代表文本含义的一个特定方面。

这些向量使得大型语言模型(LLMs)能够在向量存储库中比较和搜索相似的文本片段,方法是在这个多维空间中测量它们之间的距离或相似度。

理解嵌入/向量存储维度

向量存储索引中的维度数量取决于我们更新数据时所使用的嵌入模型,反之亦然。每个维度代表数据中的一个特定特征或概念。例如,一个维度可能代表文本的特定主题、情感或其他方面

我们用来嵌入数据的维度越多,从文本中捕捉细微含义的可能性就越大。然而,这种增加是以每个查询更高的计算需求为代价的。

一般来说,维度数越多,所需的存储、处理和比较嵌入向量的资源就越多。因此,理论上,像谷歌的embedding-001(使用768个维度)这样的嵌入模型,相较于像OpenAI的text-embedding-3-large(使用3072个维度)等其他模型,成本更低。

值得注意的是,维度与意义捕捉之间的关系并非严格的线性关系;存在一个收益递减点,即增加更多维度所带来的额外成本收益甚微。

{% 提示 样式="警告" %}

为确保嵌入模型与Vector Store索引之间的兼容性,维度对齐至关重要。嵌入模型和Vector Store索引必须具有相同的维度数。维度不匹配会导致更新错误,因为Vector Store旨在处理由所选嵌入模型确定的特定大小的向量。

步骤2:选择向量存储

点击“选择向量存储”卡片,并选择您偏好的向量存储。在我们的场景中,由于我们需要一个可用于生产的选项,我们将选择Upstash。

向量存储是一种特殊类型的数据库,用于存储向量嵌入。我们可以微调像“top K”这样的参数,它决定了在响应查询时,从向量存储中检索到的最相似块的最大数量。

信息提示框 较低的top K值将返回更少但可能更相关的结果,而较高的值将返回更广泛的结果范围,可能涵盖更多信息。 {% 结束提示 %}

步骤 3:选择记录管理器

记录管理器是我们更新流中的一个可选但极其有用的附加功能。它使我们能够维护所有已更新到矢量存储中的数据块的记录,从而能够根据需要高效地添加或删除数据块。

换言之,在新的更新插入(upsert)过程中对文档所做的任何更改,都不会导致向量存储中存储重复的向量嵌入。

有关如何设置和使用此功能的详细说明,请参阅专门的指南

7. 将数据更新到向量存储中

要开始更新插入流程并将您的数据传输到Vector Store,请点击“更新插入”按钮。

如下图所示,我们的数据已成功更新到Upstash矢量数据库中。为了优化更新过程并确保高效的存储和检索,数据被分为85个块。

8. 测试你的数据集

无需离开文档库,即可快速测试数据集的功能,只需点击“检索查询”按钮即可。该操作将启动一个测试查询,使您能够验证数据检索过程的准确性和有效性。

在我们的案例中,当查询保险单中关于厨房地板覆盖范围的信息时,我们从指定的向量存储Upstash中检索到了4个相关数据块。根据定义的“top k”参数,检索结果限制在4个数据块内,以确保我们获得的是最相关的信息,而不会出现不必要的冗余。

9. 测试你的RAG

最后,我们的检索增强生成(RAG)系统已经投入使用。值得注意的是,大型语言模型(LLM)如何有效地解释查询,并成功利用分块数据中的相关信息来构建一个全面的响应。

Agentflow

使用Agent节点,您可以添加文档存储:

或直接连接到向量数据库和嵌入模式:

聊天流程

您可以使用之前配置的向量存储:

或者,使用文档存储(Vector):

10. API

还有用于创建、更新和删除文档存储的API支持。在本节中,我们将重点介绍其中两个最常用的API:

  • 更新插入(Upsert)

  • 刷新

如需了解详情,请参阅文档存储API参考

更新插入API

更新插入(upserting)过程有几种不同的场景,每种场景的结果都不同。

场景1:在同一个文档存储中,使用现有的文档加载器配置,作为新的文档加载器进行更新插入。

选项卡

python 导入requests库 导入json库

DOC_STORE_ID = "您的文档存储ID" DOC_LOADER_ID = "你的文档加载器ID" API_URL = f"http://localhost:3000/api/v1/document-store/upsert/{DOC_STORE_ID}" API_KEY = "请在此处输入您的API密钥"

表单数据 = { "files": ('my-another-file.pdf', open('my-another-file.pdf', 'rb')) }

body_data = { "docId": DOC_LOADER_ID }

headers = { "Authorization": f"持有者 {BEARER_TOKEN}" }

定义一个函数query,接收表单数据form_data作为参数: response = requests.post(API_URL, files=form_data, data=body_data, headers=headers) 打印(响应) 返回响应的JSON格式数据

输出 = 查询(表单数据) 打印输出

{% endtab %}

{% tab title="Javascript" %}
```javascript
const DOC_STORE_ID = "你的文档存储ID"
const DOC_LOADER_ID = "你的文档加载器ID"

let formData = new FormData();;
formData.append("files", input.files[0]);;
formData.append("docId", DOC_LOADER_ID)

异步函数 query(formData) {
    const response = await fetch(
        `http://localhost:3000/api/v1/document-store/upsert/${DOC_STORE_ID}`,
        {
            方法:"POST",
            头部:{
                “授权”:“持有者 <your_api_key_here>”
            },
            正文:表单数据
        }
    );
    const result = await response.json();;
    返回结果;
}

对表单数据进行查询后,若响应成功,则执行以下操作:
    控制台输出(console.log)响应内容;
});

{% endtab %} {% endtabs %}

场景2:在同一个文档存储中,用新文件替换现有的文档加载器。

{% hint style="success" %} 在此场景中,请求体中同时需要包含**docIdreplaceExisting**。 {% 结束提示 %}

选项卡 {% tab title="Python" %} python 导入requests库 导入json库

DOC_STORE_ID = "您的文档存储ID" DOC_LOADER_ID = "你的文档加载器ID" API_URL = f"http://localhost:3000/api/v1/document-store/upsert/{DOC_STORE_ID}" API_KEY = "请在此处输入您的API密钥"

表单数据 = { "files": ('my-another-file.pdf', open('my-another-file.pdf', 'rb')) }

body_data = { "docId": DOC_LOADER_ID,, "replaceExisting": 是的 }

headers = { "Authorization": f"持有者 {BEARER_TOKEN}" }

定义查询函数(根据表单数据): response = requests.post(API_URL, files=form_data, data=body_data, headers=headers) 打印响应内容 返回响应的JSON格式数据

输出 = 查询(表单数据) 打印输出


</div>

<div data-gb-custom-block data-tag="tab" data-title='Javascript'>

```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
const DOC_STORE_ID = "your_doc_store_id";;
const DOC_LOADER_ID = "your_doc_loader_id";;

让 formData 成为一个新的 FormData 对象;
formData.append("files", input.files[0]);;
formData.append("docId", DOC_LOADER_ID);;
formData.append("replaceExisting", true);;

异步函数 query(formData) {
    const response = await fetch(
        `http://localhost:3000/api/v1/document-store/upsert/${DOC_STORE_ID}`,
        {
            方法:"POST",
            头部:{
                “授权”:“持有者 <your_api_key_here>”
            },
            正文:表单数据
        }
    );
    const result = await response.json();;
    返回结果;
}

对表单数据进行查询,然后获取响应数据
    控制台输出(console.log)响应内容;
});

场景3:在同一个文档存储中,作为新文档加载器从头开始进行更新插入。

标签页

python 导入requests库 导入json库

DOC_STORE_ID = "您的文档存储ID" API_URL = f"http://localhost:3000/api/v1/document-store/upsert/{DOC_STORE_ID}" API_KEY = "请在此处输入您的API密钥"

表单数据 = { "files": ('my-another-file.pdf', open('my-another-file.pdf', 'rb')) }

加载器 = { "name": "pdf文件",, "config": {} # 可留空以使用默认配置 }

拆分器 = { "name": "recursiveCharacterTextSplitter",, "config": { "chunkSize": 1400,, "chunkOverlap": 100 } }

嵌入 = { "名称":"openAIEmbeddings", "config": { "modelName": "text-embedding-ada-002",, “凭证”:<your_credential_id> } }

vectorStore = { "name": "松果",, "config": { "pineconeIndex": "示例索引",, "pineconeNamespace": "examplenamespace",, "credential": <你的凭证信息> } }

body_data = { "docId": DOC_LOADER_ID,, "loader": json.dumps(loader),, "splitter": json.dumps(splitter),, "embedding": json.dumps(嵌入),, "vectorStore": json.dumps(vectorStore) }

headers = { "Authorization": f"持有者 {BEARER_TOKEN}" }

def query(form_data): response = requests.post(API_URL, files=form_data, data=body_data, headers=headers) 打印响应内容 返回响应的JSON格式数据

输出 = 查询(表单数据) 打印输出

{% endtab %}

{% tab title="Javascript" %}
```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
const DOC_STORE_ID = "你的文档存储ID";;
const API_URL = `http://localhost:3000/api/v1/document-store/upsert/${DOC_STORE_ID}`;;
const API_KEY = "your_api_key_here";;

const formData = new FormData();;
formData.append("files", new Blob([await (await fetch('my-another-file.pdf')) .blob()]), "my-another-file.pdf");;

const loader = {
    名称:"pdfFile",
    config: {} // 可留空以使用默认配置
};

const splitter = {
    名称:"recursiveCharacterTextSplitter",
    配置:{
        数据块大小:1400,
        块重叠:100
    }
};

const 嵌入 = {
    名称:"openAIEmbeddings",
    配置:{
        模型名称:"text-embedding-ada-002",
        凭证:"your_credential_id"
    }
};

const vectorStore = {
    名称:"pinecone",
    配置:{
        松果索引:"示例索引",
        pineconeNamespace: "examplenamespace",,
        凭证:"your_credential_id"
    }
};

const bodyData = {
    文档ID:"DOC_LOADER_ID",
    加载器:JSON.stringify(加载器),
    分割器:JSON.stringify(分割器),
    嵌入:JSON.stringify(嵌入),
    vectorStore: JSON.stringify(vectorStore)
};

const headers = {
    "授权":`持有者 BEARER_TOKEN`
};

异步函数 query() {
    尝试 {
        const response = await fetch(API_URL, {
            方法:"POST",
            headers: 头部信息,
            正文:表单数据
        });

        const result = await response.json();;
        console.log(result);;
        返回结果;
    } catch (error) {
        console.error("错误:", error);;
    }
}

查询();;

{% endtab %} {% endtabs %}

{% 提示 样式="危险" %} 不建议从零开始创建,因为这会暴露您的凭证ID。推荐的方式是创建一个占位符文档库,并在用户界面(UI)上配置参数。然后使用该占位符作为基础,添加新的文档加载器或创建新的文档库。 {% endhint %}

场景4:为每次更新插入创建新的文档存储

{% hint style="success" %} 在此场景中,请求体中同时需要包含**createNewDocStoredocStore**。 {% 结束提示 %}

标签页 {% tab title="Python" %} python 导入requests库 导入json库

DOC_STORE_ID = "您的文档存储ID" DOC_LOADER_ID = "你的文档加载器ID" API_URL = f"http://localhost:3000/api/v1/document-store/upsert/{DOC_STORE_ID}" API_KEY = "请在此处输入您的API密钥"

表单数据 = { "files": ('my-another-file.pdf', open('my-another-file.pdf', 'rb')) }

body_data = { "docId": DOC_LOADER_ID,, "createNewDocStore": 真, "docStore": json.dumps({"name": "我的新文档库"}) }

headers = { "授权": f"持有者 {BEARER_TOKEN}" }

定义查询函数(根据表单数据): response = requests.post(API_URL, files=form_data, data=body_data, headers=headers) 打印(响应) 返回响应的JSON格式数据

输出 = 查询(表单数据) 打印输出


</div>

<div data-gb-custom-block data-tag="tab" data-title='Javascript'>

```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
const DOC_STORE_ID = "你的文档存储ID";;
const DOC_LOADER_ID = "你的文档加载器ID";;

将formData设置为新的FormData对象;
formData.append("files", input.files[0]);;
formData.append("docId", DOC_LOADER_ID);;
formData.append("createNewDocStore", true);;
formData.append("docStore", JSON.stringify({ "name": "我的新文档库" }));;

异步函数 query(formData) {
    const response = await fetch(
        `http://localhost:3000/api/v1/document-store/upsert/${DOC_STORE_ID}`,
        {
            方法:"POST",
            headers: {
                “授权”:“持有者 <your_api_key_here>”
            },
            正文:表单数据
        }
    );
    const result = await response.json();;
    返回结果;
}

对表单数据进行查询后,若查询成功则返回响应数据
    控制台输出(console.log)响应内容;
});

问:在哪里可以找到文档存储ID和文档加载器ID?

A:你可以从网址中找到相应的ID。

问:我在哪里可以找到可覆盖的配置?

A:您可以在每个文档加载器上的“查看API”按钮中找到可用的配置:

对于每次更新插入操作,都涉及5个元素:

  • loader

  • splitter

  • embedding

  • vectorStore

  • recordManager

您可以使用元素的config属性覆盖现有配置。例如,使用上图所示,您可以使用新的url创建一个新的文档加载器:

标签页

python 导入requests库

API_URL = "http://localhost:3000/api/v1/document-store/upsert/"

定义查询函数(payload): response = requests.post(API_URL, json=payload) 返回响应的JSON格式数据

输出 = 查询({ "docId": , # 覆盖现有配置 "loader": { "config": { "url": "https://new-url.com" } } }) 打印(输出)

{% endtab %}

{% tab title="Javascript" %}
```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
你是个专业的翻译,负责把英语内容翻译成中文内容,请帮我翻译一下原文内容
异步函数 query(data) {
    const response = await fetch(
        "http://localhost:3000/api/v1/document-store/upsert/<storeId>",
        {
            方法:"POST",
            headers: {
                "Content-Type": "application/json"
            },
            正文:JSON.stringify(数据)
        }
    );
    const result = await response.json();;
    返回结果;
}

查询({
    "docId": <docLoaderId>,
    // 覆盖现有配置
    "loader": {
        "config": {
            "url": "https://new-url.com"
        }
    }
}).then((response) => {
    控制台输出(console.log)响应内容;
});

{% endtab %} {% endtabs %}

如果加载器支持文件上传呢?是的,你猜对了,我们必须使用表单数据作为请求体!

以下图为例,我们可以这样覆盖PDF文件加载器的**usage**参数:

选项卡 {% tab title="Python" %} python 导入requests库 导入json库

API_URL = "http://localhost:3000/api/v1/document-store/upsert/" API_KEY = "请在此处输入您的API密钥"

表单数据 = { "files": ('my-another-file.pdf', open('my-another-file.pdf', 'rb')) }

override_loader_config = { "config": { “用法”:“每页” } }

body_data = { "docId": , "loader": json.dumps(override_loader_config) # 覆盖现有配置 }

headers = { "Authorization": f"持有者 {BEARER_TOKEN}" }

定义查询函数(form_data): response = requests.post(API_URL, files=form_data, data=body_data, headers=headers) 打印响应内容 返回响应的JSON格式数据

输出 = 查询(表单数据) 打印输出


</div>

<div data-gb-custom-block data-tag="tab" data-title='Javascript'>

```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
你是个专业的翻译,负责把英语内容翻译成中文内容,请帮我翻译一下原文内容
const DOC_STORE_ID = "你的文档存储ID";;
const DOC_LOADER_ID = "你的文档加载器ID";;

const overrideLoaderConfig = {
    "config": {
        “用法”:“每页”
    }
}

将formData设置为新的FormData对象;
formData.append("files", input.files[0]);;
formData.append("docId", DOC_LOADER_ID);;
formData.append("loader", JSON.stringify(overrideLoaderConfig));;

异步函数 query(formData) {
    const response = await fetch(
        `http://localhost:3000/api/v1/document-store/upsert/${DOC_STORE_ID}`,
        {
            方法:"POST",
            headers: {
                “授权”:“持有者 <your_api_key_here>”
            },
            正文:表单数据
        }
    )
    const result = await response.json();;
    返回结果;
}

对表单数据进行查询后,若查询成功,则返回响应数据
    控制台输出(console.log)响应内容;
e

Q:何时使用表单数据(Form Data)与JSON作为API请求的正文?

A:对于具有文件上传功能(如PDF、DOCX、TXT等)的文档加载器,正文必须以表单数据的形式发送。

{% 提示 样式="警告" %}

确保发送的文件类型与文档加载器预期的文件类型兼容。

例如,如果正在使用PDF文件加载器,则应仅发送**.pdf**文件。

为了避免为不同的文件类型使用单独的加载器,我们建议使用文件加载器

选项卡

python 导入requests库 导入json库

API_URL = "http://localhost:3000/api/v1/document-store/upsert/"

使用表单数据上传文件

表单数据 = { "files": ('my-another-file.pdf', open('my-another-file.pdf', 'rb')) }

body_data = { "docId": }

定义一个查询函数,接受表单数据作为参数: response = requests.post(API_URL, files=form_data, data=body_data) 打印响应 返回响应的JSON格式数据

输出 = 查询(表单数据) 打印(输出)

{% endtab %}

{% tab title="Javascript API" %}
```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
你是个专业的翻译,负责把英语内容翻译成中文内容,请帮我翻译一下原文内容
// 使用FormData来上传文件
let formData = new FormData();;
formData.append("files", input.files[0]);;
formData.append("docId", <docId>);;

异步函数 query(formData) {
    const response = await fetch(
        "http://localhost:3000/api/v1/document-store/upsert/<storeId>",
        {
            方法:"POST",
            正文:表单数据
        }
    );
    const result = await response.json();;
    返回结果;
}

对表单数据进行查询后,若响应成功,则执行以下操作:
    控制台输出(console.log)响应内容;
});

{% endtab %} {% endtabs %}

对于其他不具有上传文件功能的文档加载器节点,API主体采用JSON格式:

选项卡 {% tab title="Python API" %} python 导入requests库

API_URL = "http://localhost:3000/api/v1/document-store/upsert/"

定义查询函数(payload): response = requests.post(API_URL, json=payload) 返回响应的JSON格式数据

输出 = 查询({ "docId": }) 打印输出


</div>

<div data-gb-custom-block data-tag="tab" data-title='Javascript API'>

```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
异步函数 query(data) {
    const response = await fetch(
        "http://localhost:3000/api/v1/document-store/upsert/<storeId>",
        {
            方法:"POST",
            headers: {
                "Content-Type": "application/json"
            },
            正文:JSON.stringify(数据)
        }
    );
    const result = await response.json();;
    返回结果;
}

查询({
    "docId":<docId>
}).then((response) => {
    控制台输出响应内容;
});

问:我可以添加新的元数据吗?

A:您可以通过在请求正文中传递metadata来提供新的元数据:


/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
{
    "docId": <文档ID>,
    "metadata": {
        “来源:”abc“
    }
}

刷新API

很多时候,你可能希望重新处理文档存储中的每个文档加载器,以获取最新数据,并将其更新到向量存储中,从而保持所有内容的同步。这可以通过刷新API来实现:

标签页

python 导入requests库

API_URL = "http://localhost:3000/api/v1/document-store/refresh/"

定义查询函数: response = requests.post(API_URL) 返回响应的JSON格式数据

输出 = 查询() 打印输出

{% endtab %}

{% tab title="Javascript API" %}
```javascript
异步函数 query(data) {
    const response = await fetch(
        "http://localhost:3000/api/v1/document-store/refresh/<storeId>",
        {
            方法:"POST",
            头部:{
                "Content-Type": "application/json"
            }
        }
    );
    const result = await response.json();;
    返回结果;
}

query().then((response) => {
    控制台输出响应内容;
});

{% endtab %} {% endtabs %}

您还可以覆盖特定文档加载器的现有配置:

标签页 {% tab title="Python API" %} python 导入requests库

API_URL = "http://localhost:3000/api/v1/document-store/refresh/"

定义查询函数(query function):


python
def query(payload):
response = requests.post(API_URL, json=payload)
返回响应的JSON格式数据

输出 = 查询( { "items": [ { "docId": , "splitter": { "name": "recursiveCharacterTextSplitter",, "config": { "chunkSize": 2000,, “chunkOverlap”:100 } } } ] } ) 打印输出


</div>

<div data-gb-custom-block data-tag="tab" data-title='Javascript API'>

```javascript

/// 译文内容:
---
根据上面的信息,执行如下指令:
你是个专业的翻译,负责把英语内容翻译成中文内容,请帮我翻译一下原文内容
异步函数 query(data) {
    const response = await fetch(
        "http://localhost:3000/api/v1/document-store/refresh/<storeId>",
        {
            方法:"POST",
            headers: {
                "Content-Type": "application/json"
            },
            正文:JSON.stringify(数据)
        }
    );
    const result = await response.json();;
    返回结果;
}

查询({
    "items": [
        {
            "docId": <docId>,
            "splitter": {
                "name": "recursiveCharacterTextSplitter",,
                "config": {
                    "chunkSize": 2000,,
                    “chunkOverlap”:100
                }
            }
        }
    ]
}).then((response) => {
    控制台输出(console.log)响应内容;
});

11. 总结

我们首先创建了一个文档库来整理LibertyGuard Deluxe Homeowners Policy的数据。然后,我们通过上传、分块、处理和更新这些数据,使其为我们的RAG系统做好准备。

文档存储的优势:

文档库为检索增强生成(RAG)系统的数据管理和准备提供了多项优势:

  • 组织与管理:它们为数据的存储、管理和准备提供了一个中心位置。

  • 数据质量:分块处理有助于构建数据结构,以便进行准确的检索和分析。

  • 灵活性:文档存储允许根据需要优化和调整数据,从而提高RAG系统的准确性和相关性。

12. 视频教程

RAG Like a Boss - Flowise文档存储教程

在本视频中,Leon 提供了一个循序渐进的教程,指导如何在 FlowiseAI 中使用文档存储来轻松管理您的 RAG 知识库。

Last updated