Dify 知识库操作源码解析
知识库操作
数据表
接口
接口 |
名字 |
功能描述 |
请求示例 |
源码位置 |
请求参数 |
---|---|---|---|---|---|
POST /datasets |
创建空知识库 |
创建空知识库 |
curl --location --request POST 'http://127.0.0.1:5001/v1/datasets' \--header 'Authorization: Bearer {api_key}' \--header 'Content-Type: application/json' \--data-raw '{"name": "name"}' |
api/controllers/console/datasets/datasets.py |
详情 |
GET /datasets |
知识库列表 |
知识库列表 |
curl --location --request GET 'http://127.0.0.1:5001/v1/datasets?page=1&limit=20' \--header 'Authorization: Bearer {api_key}' |
api/controllers/console/datasets/datasets.py |
|
DELETE /datasets/{dataset_id} |
删除知识库 |
删除知识库 |
curl --location --request DELETE 'http://127.0.0.1:5001/console/api/datasets/{dataset_id}--header 'Authorization: Bearer {api_key}' |
位置 |
|
POST /datasets/init |
上传文件创建知识库 |
上传文件创建知识库 |
位置 |
创建
方式一:先创建空知识库,再上传文件
创建空知识库
代码流程
[!TIP]
主要流程就是收集参数 insert 数据表(dataset)中
DatasetListApi-post:处理参数,保存至数据库
create_empty_dataset:保存将创建的知识库方法
请求参数
# 知识库的详细信息
knowledge_base = {
# 知识库的唯一ID
"id": "cbd8a746-a9ab-4d79-8337-99d4ac989691",
# 知识库的名称
"name": "测试知识库",
# 描述,这里没有提供
"description": None,
# 知识库的提供商
"provider": "vendor",
# 权限设置,只对我可见
"permission": "only_me",
# 数据源类型,未指定
"data_source_type": None,
# 索引技术,未指定
"indexing_technique": None,
# 关联的应用数量
"app_count": 0,
# 文档数量
"document_count": 0,
# 文档总词数
"word_count": 0,
# 创建者的唯一ID
"created_by": "c17d706d-6418-4ca0-9ba5-34b43bb7e32c",
# 创建时间的时间戳
"created_at": 1719337063,
# 最后更新者的唯一ID
"updated_by": "c17d706d-6418-4ca0-9ba5-34b43bb7e32c",
# 最后更新时间的时间戳
"updated_at": 1719337063,
# 嵌入模型信息,未指定
"embedding_model": None,
# 嵌入模型提供商,未指定
"embedding_model_provider": None,
# 是否有可用的嵌入模型,未指定
"embedding_available": None,
# 检索模型配置
"retrieval_model_dict": {
# 搜索方法,语义搜索
"search_method": "semantic_search",
# 是否启用重排序
"reranking_enable": False,
# 重排序模型信息
"reranking_model": {
# 重排序提供商名称
"reranking_provider_name": "",
# 重排序模型名称
"reranking_model_name": ""
},
# 返回的顶部结果数量
"top_k": 2,
# 是否启用分数阈值
"score_threshold_enabled": False,
# 分数阈值,未指定
"score_threshold": None
},
# 标签列表,目前为空
"tags": []
}
方法二:上传文件直接创建默认知识库
逻辑流程图
上传文件接口
位置:api/controllers/console/datasets/file.py
upload_file 代码逻辑:校验文件类型最终保存在/api/storage/upload_files 文件夹中
def upload_file(file: FileStorage, user: Union[Account, EndUser], only_image: bool = False) -> UploadFile:
# 获取文件名和扩展名
filename = file.filename
extension = file.filename.split('.')[-1]
# 如果文件名过长,截断并保留扩展名
if len(filename) > 200:
filename = filename.split('.')[0][:200] + '.' + extension
# 根据配置获取允许的文件类型
etl_type = dify_config.ETL_TYPE
allowed_extensions = UNSTRUCTURED_ALLOWED_EXTENSIONS + IMAGE_EXTENSIONS if etl_type == 'Unstructured' \
else ALLOWED_EXTENSIONS + IMAGE_EXTENSIONS
# 检查文件类型是否在允许的范围内
if extension.lower() not in allowed_extensions:
raise UnsupportedFileTypeError()
elif only_image and extension.lower() not in IMAGE_EXTENSIONS:
raise UnsupportedFileTypeError()
# # 读取文件内容
file_content = file.read()
# 获取文件大小
file_size = len(file_content)
# 设置文件大小限制,图片文件和非图片文件有不同的限制
if extension.lower() in IMAGE_EXTENSIONS:
file_size_limit = dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT * 1024 * 1024
else:
file_size_limit = dify_config.UPLOAD_FILE_SIZE_LIMIT * 1024 * 1024
# 检查文件大小是否超过限制
if file_size > file_size_limit:
message = f'File size exceeded. {
file_size} > {
file_size_limit}'
raise FileTooLargeError(message)
# 生成文件的唯一UUID
file_uuid = str(uuid.uuid4())
# 确定当前租户ID
if isinstance(user, Account):
current_tenant_id = user.current_tenant_id
else:
# end_user
current_tenant_id = user.tenant_id
# 构建文件在存储系统中的路径
file_key = 'upload_files/' + current_tenant_id + '/' + file_uuid + '.' + extension
# # 保存文件到存储系统
storage.save(file_key, file_content)
# # 创建UploadFile模型实例,并填充必要的字段
upload_file = UploadFile(
tenant_id=current_tenant_id,
storage_type=dify_config.STORAGE_TYPE,
key=file_key,
name=filename,
size=file_size,
extension=extension,
mime_type=file.mimetype