文档管理

创建完文档库之后,您可以按照本文操作上传文档。

上传文档

本文以通过异步方式上传本地文档为例,示例代码如下:

import time
import io
from typing import Dict, List, Any
from alibabacloud_tea_util import models as util_models


def upload_document_async(
        namespace,
        namespace_password,
        collection,
        file_name,
        file_path,
        metadata: Dict[str, Any] = None,
        chunk_overlap: int = None,
        chunk_size: int = None,
        document_loader_name: str = None,
        text_splitter_name: str = None,
        dry_run: bool = None,
        zh_title_enhance: bool = None,
        separators: List[str] = None):
    with open(file_path, 'rb') as f:
        file_content_bytes = f.read()
    request = gpdb_20160503_models.UploadDocumentAsyncAdvanceRequest(
        region_id=ADBPG_INSTANCE_REGION,
        dbinstance_id=ADBPG_INSTANCE_ID,
        namespace=namespace,
        namespace_password=namespace_password,
        collection=collection,
        file_name=file_name,
        metadata=metadata,
        chunk_overlap=chunk_overlap,
        chunk_size=chunk_size,
        document_loader_name=document_loader_name,
        file_url_object=io.BytesIO(file_content_bytes),
        text_splitter_name=text_splitter_name,
        dry_run=dry_run,
        zh_title_enhance=zh_title_enhance,
        separators=separators,
    )
    response = get_client().upload_document_async_advance(request, util_models.RuntimeOptions())
    print(f"upload_document_async response code: {response.status_code}, body:{response.body}")
    return response.body.job_id


def wait_upload_document_job(namespace, namespace_password, collection, job_id):
    def job_ready():
        request = gpdb_20160503_models.GetUploadDocumentJobRequest(
            region_id=ADBPG_INSTANCE_REGION,
            dbinstance_id=ADBPG_INSTANCE_ID,
            namespace=namespace,
            namespace_password=namespace_password,
            collection=collection,
            job_id=job_id,
        )
        response = get_client().get_upload_document_job(request)
        print(f"get_upload_document_job response code: {response.status_code}, body:{response.body}")
        return response.body.job.completed
    while True:
        if job_ready():
            print("successfully load document")
            break
        time.sleep(2)


if __name__ == '__main__':
    job_id = upload_document_async("ns1", "Ns1password", "dc1",
                                   "test.pdf", "/root/test.pdf")
    wait_upload_document_job("ns1", "Ns1password", "dc1", job_id)


# upload_document_async output:
# {
#    "JobId":"95de2856-0cd4-44bb-b216-ea2f0ebcc57b",
#    "Message":"Successfully create job",
#    "RequestId":"9F870770-C402-19EC-9E26-ED7E4F539C3E",
#    "Status":"success"
# }

# get_upload_document_job output:
# {
#    "ChunkResult":{
#        "ChunkFileUrl":"http://knowledge-base-gp-xx.oss-cn-beijing.aliyuncs.com/ns1/dc1/produce-files/test.pdf/chunks.jsonl?Expires=1706530707&OSSAccessKeyId=ak&Signature=6qUSwBtuthr0L9OxKoTh7kEohxQ%3D",
#        "PlainChunkFileUrl":"http://knowledge-base-gp-xx.oss-cn-beijing.aliyuncs.com/ns1/dc1/produce-files/test.pdf/plain_chunks.txt?Expires=1706530707&OSSAccessKeyId=ak&Signature=sxc5iiGUDE2M%2FV0JikFvQE7FdBM%3D"
#    },
#    "Job":{
#        "Completed":true,
#        "CreateTime":"2024-01-29 18:15:27.364484",
#        "Id":"95de2856-0cd4-44bb-b216-ea2f0ebcc57b",
#        "Progress":100,
#        "Status":"Success",
#        "UpdateTime":"2024-01-29 18:15:53.78808"
#    },
#    "Message":"Success get job info",
#    "RequestId":"64487F02-5A02-1CD9-BA5C-B59E9D3A68CC",
#    "Status":"success"
# }

其中upload_document_async的参数说明如下:

  • namespace:文档库所在的Namespace名称。

  • namespace_password:Namespace的密码。

  • collection:文档要存入的文档库名称。

  • file_name:文档名称,带有类型后缀。

  • file_path:本地的文档路径,文件最大200 MB。

  • metadata:文档的元数据,需要和创建文档库时指定的元数据一致。

  • chunk_overlap:处理大型数据的切分策略。在分块处理时,连续的块之间重叠的数据量,最大值不能超过chunk_size。

  • chunk_size:处理大型数据的切分策略,数据拆分成较小的部分时每个块的大小,最大值为2048。

  • document_loader_name:建议无需指定,会按照文件扩展名自动匹配加载器。自动匹配加载器的详情,请参见文档理解

  • text_splitter_name:切分器名称。文档切分详情,请参见文档切分

  • dry_run:是否只进行文档理解和切分,不进行向量化和入库。取值说明:

    • true:只进行文档理解和切分。

    • false(默认):先进行文档理解和切分,然后进行向量化和入库。

  • zh_title_enhance:是否开启中文标题加强。取值说明:

    • true:开启中文标题加强。

    • false:关闭中文标题加强。

  • separators:处理大型数据切分策略的分隔符,一般无需指定。

文档理解

document_loader_name会根据文档名后缀来自动决定使用哪个loader:

  • UnstructuredHTMLLoader:.html

  • UnstructuredMarkdownLoader:.md

  • PyMuPDFLoader:.pdf

  • PyPDFLoader:.pdf

  • RapidOCRPDFLoader:.pdf

  • JSONLoader:.json

  • CSVLoader:.csv

  • RapidOCRLoader:.png.jpg.jpeg.bmp

  • UnstructuredFileLoader:.eml.msg.rst.txt.xml.docx.epub.odt.pptx.tsv

当一个文档类型有多个loader时,如pdf,可以指定其中任一个。若需要识别图片里的文本,建议使用RapidOCRPDFLoader。

文档切分

文档切分的效果由chunk_overlap、chunk_size、text_splitter_name几部分决定,其中text_splitter_name取值说明如下:

  • ChineseRecursiveTextSplitter:继承于RecursiveCharacterTextSplitter,默认以["\n\n","\n", "。|!|?","\.\s|\!\s|\?\s", ";|;\s", ",|,\s"]作为分隔符,使用正则匹配,中文比 RecursiveCharacterTextSplitter效果更好一些。

  • SpacyTextSplitter:默认以["\n\n", "\n", " ", ""]作为分隔符。可以支持c++gojavajsphpprotopythonrstrubyrustscalaswiftmarkdownlatexhtmlsolcsharp等多种代码语言的切分。

  • RecursiveCharacterTextSplitter:默认分隔符为\n\n,使用Spacy库的en_core_web_sm模型来分隔,对全英文文档支持较好。

  • MarkdownHeaderTextSplitter:针对markdown类型,使用[ ("#", "head1"), ("##", "head2"), ("###", "head3"), ("####", "head4") ]来切分。

查看文档列表

def list_documents(namespace, namespace_password, collection):
    request = gpdb_20160503_models.ListDocumentsRequest(
        region_id=ADBPG_INSTANCE_REGION,
        dbinstance_id=ADBPG_INSTANCE_ID,
        namespace=namespace,
        namespace_password=namespace_password,
        collection=collection,
    )
    response = get_client().list_documents(request)
    print(f"list_documents response code: {response.status_code}, body:{response.body}")


if __name__ == '__main__':
    list_documents("ns1", "Ns1password", "dc1")


# output: body:
# {
#    "Items":{
#        "DocumentList":[
#            {
#                "FileName":"test.pdf",
#                "Source":"OSS"
#            }
#        ]
#    },
#    "RequestId":"08D5E2D6-81E1-1D8A-B864-830538B04991",
#    "Status":"success"
# }

其中list_documents的参数说明如下:

  • namespace:文档库所在的Namespace名称。

  • namespace_password:Namespace的密码。

  • collection: 文档库名称。

查看文档详情

def describe_document(namespace, namespace_password, collection, file_name):
    request = gpdb_20160503_models.DescribeDocumentRequest(
        region_id=ADBPG_INSTANCE_REGION,
        dbinstance_id=ADBPG_INSTANCE_ID,
        namespace=namespace,
        namespace_password=namespace_password,
        collection=collection,
        file_name=file_name
    )
    response = get_client().describe_document(request)
    print(f"describe_document response code: {response.status_code}, body:{response.body}")


if __name__ == '__main__':
    describe_document("ns1", "Ns1password", "dc1", "test.pdf")


# output: body:
# {
#    "DocsCount":24,
#    "DocumentLoader":"PyMuPDFLoader",
#    "FileExt":"pdf",
#    "FileMd5":"ce16fa68025ebf41649810f0335caf49",
#    "FileMtime":"2024-01-29 11:37:27.270611",
#    "FileName":"test.pdf",
#    "FileSize":8332620,
#    "FileVersion":1,
#    "RequestId":"D05B4CF1-64F0-1D77-AD9C-C54CAB065571",
#    "Source":"OSS",
#    "Status":"success",
#    "TextSplitter":"ChineseRecursiveTextSplitter"
# }

其中describe_document的参数说明如下:

  • namespace:文档库所在的Namespace名称。

  • namespace_password:Namespace的密码。

  • collection: 文档库名称。

  • file_name: 文档名称。

返回文档的详细信息如下:

  • DocsCount:文档被切分的块数量。

  • TextSplitter:文档切分器名称。

  • DocumentLoader:文档Loader名称。

  • FileExt:文档扩展名。

  • FileMd5:文档MD5 HASH值。

  • FileMtime:文档最新上传时间。

  • FileSize:文件大小,单位为字节。

  • FileVersion:文档版本,INT类型,代表此文档被上传更新了多少次。

删除文档

def delete_document(namespace, namespace_password, collection, file_name):
    request = gpdb_20160503_models.DeleteDocumentRequest(
        region_id=ADBPG_INSTANCE_REGION,
        dbinstance_id=ADBPG_INSTANCE_ID,
        namespace=namespace,
        namespace_password=namespace_password,
        collection=collection,
        file_name=file_name
    )
    response = get_client().delete_document(request)
    print(f"delete_document response code: {response.status_code}, body:{response.body}")


if __name__ == '__main__':
    delete_document("ns1", "Ns1password", "dc1", "test.pdf")


# output: body:
# {
#    "Message":"success",
#    "RequestId":"DC735368-02DD-48A4-8A26-C8DEB53C5B56",
#    "Status":"success"
# }

其中delete_document的参数说明如下:

  • namespace:文档库所在的Namespace名称。

  • namespace_password:Namespace的密码。

  • collection: 文档库名称。

  • file_name: 文档名称。