dify实现原理分析-上传文件创建知识库
概述
本文介绍上传文件到知识库的处理逻辑。本文主要介绍文件上传的主要实现流程。
知识库文件上传API介绍
文件上传API
/datasets/{
dataset_id}/document/create-by-text
API的处理类设置
api.add_resource(
DocumentAddByTextApi,
"/datasets/<uuid:dataset_id>/document/create_by_text",
"/datasets/<uuid:dataset_id>/document/create-by-text",
)
文本上传的处理实现:DocumentAddByTextApi.post
class DocumentAddByTextApi(DatasetApiResource):
"""Resource for documents."""
@cloud_edition_billing_resource_check("vector_space", "dataset")
@cloud_edition_billing_resource_check("documents", "dataset")
def post(self, tenant_id, dataset_id):
# 获取用户请求参数,解析参数,验证参数的合法性
# 进一步检查参数的合法性
DocumentService.document_create_args_validate(args)
# 启动文档分割任务,(1)分割文档构建嵌入向量并保存到向量库中;(2)提取关键词,并保存到数据库中。
DocumentService.save_document_with_dataset_id(...)
# ...
post函数的主要实现逻辑
- 参数验证:
- 使用
reqparse.RequestParser()
定义并验证请求中的参数,如name
,text
,process_rule
, 等等。 - 检查必要的参数是否为非空,并进行必要的数据类型转换。
- 在数据库中验证数据集是否存在
- 查询指定的
dataset
对象,确保该数据集存在。如果不存在则抛出错误。
注:在上传文档时,需要先创建一个数据集。上传文件后,首先要检查数据集是否存在。
- 索引技术类型验证:
- 确保提供的或默认的索引技术类型是有效的。如果不有效则抛出错误。
- 上传文件并添加数据源信息:
- 将传入的文本内容通过
FileService.upload_text()
方法上传到文件系统,dify支持多种文件存储系统,比如:aliyun_oss,local等,并在配置数据库中添加一条文件上传信息的记录。 - 创建一个数据源字典,指定文件类型及其信息列表。这里的数据源类型被设置为:“upload_file”。
- 参数验证和保存文档:
- 调用
DocumentService.document_create_args_validate(args)
验证所有传入参数的有效性。 - 调用
DocumentService.save_document_with_dataset_id()
方法将文档保存到数据库中,并启动索引构建任务,构建文档索引。该函数是文档上传过程并对文档进行处理的核心。
- 异常处理:
- 捕获并处理可能的
ProviderTokenNotInitError
异常,抛出自定义的ProviderNotInitializeError
。
- 返回结果:
- 将成功创建的文档和相关的批处理信息以 JSON 格式返回,并附带 HTTP 状态码 200。
post函数功能小结
- 提供一个 REST API 接口,允许通过上传文件的文本内容创建新的知识库(Dataset)。文件保存到存储库(可设置,比如:S3等)中。
- 通过Celery任务队列,启动异步索引构建任务,来把文档切分成小块(chunk),并把分块构建成嵌入向量,保存到向量数据库中。
- 把文档和分块信息(元数据信息)保存到数据库中,抽取文本的关键词,并把关键词保存到数据库中。
- 确保输入数据的有效性和一致性,防止错误输入导致的数据损坏或业务逻辑混乱。
- 实现与数据库的交互,对新创建的文档进行持久化存储。
save_document_with_dataset_id函数
总体实现逻辑分析
从以上过程可以看出,其主要功能是在save_document_with_dataset_id函数中完成。现在,我们来看一下该函数的实现逻辑。