通过API上传文档

您可以将私有领域的文档从本地或对象存储OSS上传至百炼知识库,使大模型应用可以回答私有领域的问题。百炼支持通过控制台或API上传文档。本文介绍如何使用API将文档上传至百炼。

重要
  • RAM用户(子账号)调用:RAM用户需要首先获取百炼OpenAPI的管理权限,然后才能调用本文中的接口。阿里云账号(主账号)可直接调用无须授权。

  • API不支持创建结构化数据表:您只能在控制台数据管理中创建结构化数据表并上传数据。您可以将知识库与云数据库RDS关联,以实现结构化知识库的自动更新,详见创建知识库

  • 最大上传限制:每个业务空间最多可上传10万个文档。

操作步骤

建议您使用最新版百炼SDK来调用本文中的接口。

通过API将非结构化文档上传至百炼,只需四步:

image

1. 申请文档上传租约

使用百炼SDK调用ApplyFileUploadLease接口,获取用于上传文档的 URL 链接(租约)以及上传所需的相关参数。

  • 关于在线调试与示例代码

    您可以在线调试ApplyFileUploadLease接口,并实时生成多语言(例如Java、Node.js等)代码示例

  • 此接口请求参数中的FileName字段的值须与即将上传的文档名一致

    ApplyFileUploadLease接口请求参数中的FileName字段表示您即将上传的文档的名称(包括后缀),该字段的值必须与实际文档名一致,否则接口会报错。例如,您准备上传一个名为百炼系列手机产品介绍.docx的文档:

    image

    相应的FileName传入示例如下:

    百炼系列手机产品介绍.docx
  • 关于此接口请求参数中的MD5字段的值

    ApplyFileUploadLease接口请求参数中的Md5字段表示您即将上传的文档的MD5值(用于验证文档是否完整),您可以使用Pythonhashlib模块或JavaMessageDigest类获取该值。

    您可以展开下方折叠面板查看PythonJava的示例代码(其他语言需要您参照示例代码自行编写)。

    生成MD5示例代码

    Python

    # 示例代码仅供参考,请勿在生产环境中直接使用
    import hashlib
    def calculate_md5(file_path):
        """计算文档的 MD5 值。
    
        Args:
            file_path (str): 文档的路径。
    
        Returns:
            str: 文档的 MD5 值。
        """
        md5_hash = hashlib.md5()
    
        # 以二进制形式读取文件
        with open(file_path, "rb") as f:
            # 按块读取文件,避免大文件占用过多内存
            for chunk in iter(lambda: f.read(4096), b""):
                md5_hash.update(chunk)
    
        return md5_hash.hexdigest()
    
    # 使用示例
    file_path = "请替换为您需要上传文档的实际本地路径,例如/Users/Bailian/Desktop/百炼系列手机产品介绍.docx"
    md5_value = calculate_md5(file_path)
    print(f"文档的MD5值为: {md5_value}")
    

    Java

    示例代码

    // 示例代码仅供参考,请勿在生产环境中直接使用
    import java.io.InputStream;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.security.MessageDigest;
    
    public class Md5Utils {
    
        private static String getFileMd5(String filePath) throws Exception {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            try (InputStream is = Files.newInputStream(Paths.get(filePath))) {
                byte[] buffer = new byte[1024];
                int read;
                while ((read = is.read(buffer)) > 0) {
                    digest.update(buffer, 0, read);
                }
            }
            byte[] md5Bytes = digest.digest();
    
            StringBuilder md5String = new StringBuilder();
            for (byte b : md5Bytes) {
                md5String.append(String.format("%02x", b));
            }
    
            return md5String.toString();
        }
    
        public static void main(String[] args) throws Exception {
    
            String filePath = "请替换为您需要上传文档的实际本地路径,例如/Users/Bailian/Desktop/百炼系列手机产品介绍.docx";
            String md5 = getFileMd5(filePath);
    
            System.out.println("文档的MD5值为: " + md5);
        }
    }

    运行上述示例代码,您即可得到目标文档的MD5值(以下示例值仅供参考):

    文档的MD5值为: c0c07fb456057128540a91ea9b06666c
  • 成功调用ApplyFileUploadLease接口的响应示例

    • 此接口响应中的Data.FileUploadLeaseIdData.Param.MethodData.Param.UrlData.Param.HeadersX-bailian-extraContent-Type字段的值请妥善保存,它们将用于后续的上传步骤。

    • 此接口响应中的Data.Param.Url字段的值(即租约)有效期为分钟级,请尽快上传文档,以免租约过期导致无法上传。

    {
      "RequestId": "778C0B3B-59C2-5FC1-A947-36EDD1xxxxxx",
      "Success": true,
      "Message": "",
      "Code": "success",
      "Status": "200",
      "Data": {
        "FileUploadLeaseId": "1e6a159107384782be5e45ac4759b247.1719325231035",
        "Type": "HTTP",
        "Param": {
          "Method": "PUT",
          "Url": "https://bailian-datahub-data-origin-prod.oss-cn-hangzhou.aliyuncs.com/1005426495169178/10024405/68abd1dea7b6404d8f7d7b9f7fbd332d.1716698936847.pdf?Expires=1716699536&OSSAccessKeyId=TestID&Signature=HfwPUZo4pR6DatSDym0zFKVh9Wg%3D",
          "Headers": "        \"X-bailian-extra\": \"MTAwNTQyNjQ5NTE2OTE3OA==\",\n        \"Content-Type\": \"application/pdf\""
        }
      }
    }

2. 上传文档至百炼的临时存储

使用上一步(申请文档上传租约)返回的Data.Param.UrlData.Param.MethodData.Param.HeadersX-bailian-extraContent-Type等参数,将您在本地或OSS中的文档上传至百炼的临时存储暂存。示例代码如下。

  • 不支持在线调试

    由于本步骤的代码目前并未包含在SDK中,因此不支持在线调试和多语言示例代码的自动生成(需要您参照下方的示例代码自行手动编写)。

  • 关于示例代码中的pre_signed_url参数

    下方示例代码中的pre_signed_url是您在上一步(申请文档上传租约)中调用ApplyFileUploadLease接口实际返回的Data.ParamUrl字段的值。

Python

示例代码

# 示例代码仅供参考,请勿在生产环境中直接使用
import requests
from urllib.parse import urlparse

def upload_file(pre_signed_url, file_path):
    try:
        # 设置请求头
        headers = {
            "X-bailian-extra": "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中X-bailian-extra字段的值",
            "Content-Type": "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中Content-Type字段的值"
        }

        # 读取文档并上传
        with open(file_path, 'rb') as file:
            # 下方设置请求方法用于文档上传,需与您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param中Method字段的值一致
            response = requests.put(pre_signed_url, data=file, headers=headers)

        # 检查响应状态码
        if response.status_code == 200:
            print("File uploaded successfully.")
        else:
            print(f"Failed to upload the file. ResponseCode: {response.status_code}")

    except Exception as e:
        print(f"An error occurred: {str(e)}")

def upload_file_link(pre_signed_url, source_url_string):
    try:
        # 设置请求头
        headers = {
            "X-bailian-extra": "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中X-bailian-extra字段的值",
            "Content-Type": "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中Content-Type字段的值"
        }

        # 设置访问OSS的请求方法为GET
        source_response = requests.get(source_url_string)
        if source_response.status_code != 200:
            raise RuntimeError("Failed to get source file.")

        # 下方设置请求方法用于文档上传,需与您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param中Method字段的值一致
        response = requests.put(pre_signed_url, data=source_response.content, headers=headers)

        # 检查响应状态码
        if response.status_code == 200:
            print("File uploaded successfully.")
        else:
            print(f"Failed to upload the file. ResponseCode: {response.status_code}")

    except Exception as e:
        print(f"An error occurred: {str(e)}")

if __name__ == "__main__":

    pre_signed_url_or_http_url = "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param中Url字段的值"

    # 文档来源可以是本地,上传本地文档至百炼临时存储
    file_path = "请替换为您需要上传文档的实际本地路径"
    upload_file(pre_signed_url_or_http_url, file_path)

    # 文档来源还可以是OSS
    # file_path = "请替换为您需要上传文档的实际OSS可公网访问地址"
    # upload_file_link(pre_signed_url_or_http_url, file_path)

Java

示例代码

// 示例代码仅供参考,请勿在生产环境中直接使用
import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class UploadFile{

    public static void uploadFile(String preSignedUrl, String filePath) {
        HttpURLConnection connection = null;
        try {
            // 创建URL对象
            URL url = new URL(preSignedUrl);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法用于文档上传,需与您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param中Method字段的值一致
            connection.setRequestMethod("PUT");

            // 允许向connection输出,因为这个连接是用于上传文档的
            connection.setDoOutput(true);

            connection.setRequestProperty("X-bailian-extra", "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中X-bailian-extra字段的值");
            connection.setRequestProperty("Content-Type", "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中Content-Type字段的值");

            // 读取文档并通过连接上传
            try (DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());
                 FileInputStream fileInputStream = new FileInputStream(filePath)) {
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                    outStream.write(buffer, 0, bytesRead);
                }

                outStream.flush();
            }

            // 检查响应
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 文档上传成功处理
                System.out.println("File uploaded successfully.");
            } else {
                // 文档上传失败处理
                System.out.println("Failed to upload the file. ResponseCode: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    public static void uploadFileLink(String preSignedUrl, String sourceUrlString) {
        HttpURLConnection connection = null;
        try {
            // 创建URL对象
            URL url = new URL(preSignedUrl);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法用于文档上传,需与您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param中Method字段的值一致
            connection.setRequestMethod("PUT");

            // 允许向connection输出,因为这个连接是用于上传文档的
            connection.setDoOutput(true);

            connection.setRequestProperty("X-bailian-extra", "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中X-bailian-extra字段的值");
            connection.setRequestProperty("Content-Type", "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param.Headers中Content-Type字段的值");

            URL sourceUrl = new URL(sourceUrlString);
            HttpURLConnection sourceConnection = (HttpURLConnection) sourceUrl.openConnection();

            // 设置访问OSS的请求方法为GET
            sourceConnection.setRequestMethod("GET");
            // 获取响应码,200表示请求成功
            int sourceFileResponseCode = sourceConnection.getResponseCode();

            // 从OSS读取文档并通过连接上传
            if (sourceFileResponseCode != HttpURLConnection.HTTP_OK){
                throw new RuntimeException("Failed to get source file.");
            }
            try (DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());
                 InputStream in = new BufferedInputStream(sourceConnection.getInputStream())) {
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = in.read(buffer)) != -1) {
                    outStream.write(buffer, 0, bytesRead);
                }

                outStream.flush();
            }

            // 检查响应
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 文档上传成功
                System.out.println("File uploaded successfully.");
            } else {
                // 文档上传失败
                System.out.println("Failed to upload the file. ResponseCode: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    public static void main(String[] args) {

        String preSignedUrlOrHttpUrl = "请替换为您在上一步中调用ApplyFileUploadLease接口实际返回的Data.Param中Url字段的值";

        // 文档来源可以是本地,上传本地文档至百炼临时存储
        String filePath = "请替换为您需要上传文档的实际本地路径";
        uploadFile(preSignedUrlOrHttpUrl, filePath);

        // 文档来源还可以是OSS
        // String filePath = "请替换为您需要上传文档的实际OSS可公网访问地址";
        // uploadFileLink(preSignedUrlOrHttpUrl, filePath);
    }
}

3. 将文档添加至百炼的数据管理

上一步(上传文档至百炼的临时存储)操作成功后,文档将暂存于百炼的临时存储空间内 12 小时,请及时使用百炼SDK调用AddFile接口将文档上传至百炼的数据管理

  • 关于在线调试与示例代码

    您可以在线调试AddFile接口,并实时生成多语言代码示例

  • 关于此接口请求参数中的LeaseId字段

    AddFile接口请求参数中的LeaseId字段的值为之前步骤(申请文档上传租约)中调用ApplyFileUploadLease接口返回的Data.FileUploadLeaseId字段的值。

  • 请勿重复提交

    AddFile接口调用成功后,LeaseId(租约 ID)随即失效,请勿使用相同的租约 ID 重复提交。

4. 查看文档解析状态

上一步AddFile接口调用成功后,百炼将开始上传并解析文档。整个过程需一定时间,请耐心等待。期间您可以访问百炼的数据管理,或使用百炼SDK调用DescribeFile接口查询文档最新状态。上传完成后,DescribeFile接口响应参数中的Data.Status字段的值为PARSE_SUCCESS

  • 关于在线调试与示例代码

    您可以在线调试DescribeFile接口,并实时生成多语言代码示例

  • 存储期限

    导入数据管理的文档仅用于最终导入知识库前的临时存储,有效期为90天,不支持长期保存,请自行妥善保存原文档。

下一步

相关文档

除了使用API上传文档,您还可以通过控制台上传文档,详见知识库

常见问题

调用AddFile接口将文档添加至百炼的数据管理时,遇到Access your uploaded file failed. Please check if your upload action was successful报错,如何处理?

一般是由于没有执行或未能成功执行上文第2步(上传文档至百炼的临时存储)导致。请在确认该步骤成功执行后,再调用AddFile接口。