feat: support file parsing sync (#60)

Co-authored-by: mengqian <cherish_a_meng@163.com>
This commit is contained in:
code-c-light 2025-10-30 17:31:50 +08:00 committed by GitHub
parent 67bd9910e1
commit ef5f55982e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 177 additions and 42 deletions

View file

@ -44,4 +44,14 @@ public interface FileParsingApi {
@GET("files/parser/result/{taskId}/{formatType}") @GET("files/parser/result/{taskId}/{formatType}")
Call<ResponseBody> downloadParseResult(@Path("taskId") String taskId, @Path("formatType") String formatType); Call<ResponseBody> downloadParseResult(@Path("taskId") String taskId, @Path("formatType") String formatType);
/**
* Executes a synchronous file parsing operation. Uploads a file and returns the
* parsing result with specified tool and file type.
* @param multipartBody The multipart request body containing the file and related
* metadata (tool type, file type)
* @return Parsing result content as a FileParsingDownloadResp object
*/
@POST("files/parser/sync")
Call<FileParsingDownloadResp> syncParse(@Body MultipartBody multipartBody);
} }

View file

@ -3,10 +3,9 @@ package ai.z.openapi.core;
/** /**
* Constants class containing all the configuration values and model identifiers used * Constants class containing all the configuration values and model identifiers used
* throughout the Z.AI OpenAPI SDK. * throughout the Z.AI OpenAPI SDK.
* * <p>
* This class provides centralized access to: - API base URLs - Model identifiers for * This class provides centralized access to: - API base URLs - Model identifiers for
* different AI capabilities - Invocation method constants * different AI capabilities - Invocation method constants
*
*/ */
public final class Constants { public final class Constants {

View file

@ -20,4 +20,13 @@ public interface FileParsingService {
*/ */
FileParsingDownloadResponse getParseResult(FileParsingDownloadReq request); FileParsingDownloadResponse getParseResult(FileParsingDownloadReq request);
/**
* Executes a synchronous file parsing operation. Uploads a file and immediately
* returns the parsing result, using the specified tool and file type.
* @param request The file parsing upload request (contains file path, tool type, file
* type, etc.)
* @return FileParsingDownloadResponse containing the parsed content and status
*/
FileParsingDownloadResponse syncParse(FileParsingUploadReq request);
} }

View file

@ -40,7 +40,7 @@ public class FileParsingServiceImpl implements FileParsingService {
if (request.getToolType() == null) { if (request.getToolType() == null) {
throw new IllegalArgumentException("toolType cannot be null"); throw new IllegalArgumentException("toolType cannot be null");
} }
// 构建 multipart/form-data // Construct multipart/form-data
RequestSupplier<FileParsingUploadReq, FileParsingUploadResp> supplier = params -> { RequestSupplier<FileParsingUploadReq, FileParsingUploadResp> supplier = params -> {
try { try {
File file = new File(params.getFilePath()); File file = new File(params.getFilePath());
@ -107,4 +107,55 @@ public class FileParsingServiceImpl implements FileParsingService {
return this.zAiClient.executeRequest(request, supplier, FileParsingDownloadResponse.class); return this.zAiClient.executeRequest(request, supplier, FileParsingDownloadResponse.class);
} }
@Override
public FileParsingDownloadResponse syncParse(FileParsingUploadReq request) {
if (request == null) {
throw new IllegalArgumentException("request cannot be null");
}
if (request.getFilePath() == null) {
throw new IllegalArgumentException("filePath cannot be null");
}
if (request.getToolType() == null) {
throw new IllegalArgumentException("toolType cannot be null");
}
RequestSupplier<FileParsingUploadReq, FileParsingDownloadResp> supplier = params -> {
try {
File file = new File(params.getFilePath());
if (!file.exists()) {
throw new RuntimeException("file not found at " + params.getFilePath());
}
String toolType = params.getToolType();
String fileType = params.getFileType();
// Construct multipart/form-data
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"), file));
MultipartBody.Builder formBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
formBodyBuilder.addPart(filePart);
formBodyBuilder.addFormDataPart("tool_type", toolType);
formBodyBuilder.addFormDataPart("file_type", fileType);
MultipartBody multipartBody = formBodyBuilder.build();
// Send a POST request
retrofit2.Call<FileParsingDownloadResp> call = fileParsingApi.syncParse(multipartBody);
Response<FileParsingDownloadResp> response = call.execute();
if (!response.isSuccessful() || response.body() == null) {
throw new IOException(
"Failed to sync parse, code: " + response.code() + ", msg: " + response.message());
}
return Single.just(response.body());
}
catch (Exception e) {
throw new RuntimeException(e);
}
};
return this.zAiClient.executeRequest(request, supplier, FileParsingDownloadResponse.class);
}
} }

View file

@ -218,11 +218,11 @@ public class FileParsingServiceTest {
byte[] bytes = Files.readAllBytes(new File(file).toPath()); byte[] bytes = Files.readAllBytes(new File(file).toPath());
Base64.Encoder encoder = Base64.getEncoder(); Base64.Encoder encoder = Base64.getEncoder();
String imageBase64 = encoder.encodeToString(bytes); String imageBase64 = encoder.encodeToString(bytes);
// 假设解析接口支持 imageBase64 字段 // Assuming the parsing interface supports the imageBase64 field
FileParsingUploadReq request = FileParsingUploadReq.builder() FileParsingUploadReq request = FileParsingUploadReq.builder()
.toolType("image") .toolType("image")
.fileType("png") .fileType("png")
.filePath(file) // 或文件路径 .filePath(file) // file path
.build(); .build();
FileParsingResponse response = fileParsingService.createParseTask(request); FileParsingResponse response = fileParsingService.createParseTask(request);

View file

@ -45,7 +45,7 @@
</scm> </scm>
<properties> <properties>
<revision>0.0.6.1</revision> <revision>0.0.6.2</revision>
<java.version>8</java.version> <java.version>8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

View file

@ -10,84 +10,86 @@ import ai.z.openapi.utils.StringUtils;
public class FileParsingExample { public class FileParsingExample {
public static void main(String[] args) { public static void main(String[] args) {
// 建议通过环境变量设置 API Key // It's recommended to set the API Key via environment variable
// export ZAI_API_KEY=your.api_key // export ZAI_API_KEY=your.api_key
// ZaiClient client = ZaiClient.builder().build(); // ZaiClient client = ZaiClient.builder().build();
// You can also specify the API Key directly in code
// 也可在代码中直接指定 API Key
ZaiClient client = ZaiClient.builder() ZaiClient client = ZaiClient.builder()
.apiKey("API Key") .apiKey("API Key")
.build(); .build();
try { try {
// 示例1: 创建解析任务 // Example 1: Create a file parsing task
System.out.println("=== 文件解析任务创建示例 ==="); System.out.println("=== Example: Create file parsing task ===");
String filePath = "your file path"; String filePath = "your file path";
String taskId = createFileParsingTaskExample(client, filePath, "pdf", "lite"); String taskId = createFileParsingTaskExample(client, filePath, "pdf", "lite");
// 示例2: 获取解析结果 // Example 2: Get parsing result
System.out.println("\n=== 获取解析结果示例 ==="); System.out.println("\n=== Example: Get parsing result ===");
getFileParsingResultExample(client, taskId); getFileParsingResultExample(client, taskId);
} catch (Exception e) { } catch (Exception e) {
System.err.println("发生异常: " + e.getMessage()); System.err.println("Exception occurred: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* 示例创建解析任务上传文件并解析 * Example: Create parsing task (upload file and parse)
* *
* @param client ZaiClient 实例 * @param client ZaiClient instance
* @return 解析任务的 taskId * @return TaskId of the parsing task
*/ */
private static String createFileParsingTaskExample(ZaiClient client, String filePath, String fileType, String toolType) { private static String createFileParsingTaskExample(ZaiClient client, String filePath, String fileType, String toolType) {
if (StringUtils.isEmpty(filePath)) { if (StringUtils.isEmpty(filePath)) {
System.err.println("无效的文件路径。"); System.err.println("Invalid file path.");
return null; return null;
} }
try { try {
FileParsingUploadReq uploadReq = FileParsingUploadReq.builder() FileParsingUploadReq uploadReq = FileParsingUploadReq.builder()
.filePath(filePath) .filePath(filePath)
.fileType(fileType) // 支持: pdf, docx .fileType(fileType) // support: pdf, docx etc.
.toolType(toolType) // 解析工具类型: lite, prime, expert .toolType(toolType) // tool type: lite, prime, expert
.build(); .build();
System.out.println("正在上传并创建解析任务..."); System.out.println("Uploading file and creating parsing task...");
FileParsingResponse response = client.fileParsing().createParseTask(uploadReq); FileParsingResponse response = client.fileParsing().createParseTask(uploadReq);
if (response.isSuccess()) { if (response.isSuccess()) {
if (null != response.getData().getTaskId()) { if (null != response.getData().getTaskId()) {
String taskId = response.getData().getTaskId(); String taskId = response.getData().getTaskId();
System.out.println("解析任务创建成功,TaskId: " + taskId); System.out.println("Parsing task created successfully, TaskId: " + taskId);
return taskId; return taskId;
} else { } else {
System.err.println("解析任务创建失败: " + response.getData().getMessage()); System.err.println("Failed to create parsing task: " + response.getData().getMessage());
} }
} else { } else {
System.err.println("解析任务创建失败: " + response.getMsg()); System.err.println("Failed to create parsing task: " + response.getMsg());
} }
} catch (Exception e) { } catch (Exception e) {
System.err.println("文件解析任务错误: " + e.getMessage()); System.err.println("File parsing task error: " + e.getMessage());
} }
// 返回 null 表示创建失败 // Return null indicates task creation failed
return null; return null;
} }
/** /**
* 示例获取解析结果 * Example: Get parsing result
* *
* @param client ZaiClient 实例 * @param client ZaiClient instance
* @param taskId 解析任务ID * @param taskId ID of the parsing task
*/ */
private static void getFileParsingResultExample(ZaiClient client, String taskId) { private static void getFileParsingResultExample(ZaiClient client, String taskId) {
if (taskId == null || taskId.isEmpty()) { if (taskId == null || taskId.isEmpty()) {
System.err.println("无效的任务ID无法获取解析结果。"); System.err.println("Invalid task ID. Cannot get parsing result.");
return; return;
} }
try { try {
int maxRetry = 100; // 最多轮询100次 int maxRetry = 100; // Maximum 100 polling attempts
int intervalMs = 3000; // 每次间隔3秒 int intervalMs = 3000; // 3 seconds interval between each polling
for (int i = 0; i < maxRetry; i++) { for (int i = 0; i < maxRetry; i++) {
FileParsingDownloadReq downloadReq = FileParsingDownloadReq.builder() FileParsingDownloadReq downloadReq = FileParsingDownloadReq.builder()
.taskId(taskId) .taskId(taskId)
@ -98,28 +100,28 @@ public class FileParsingExample {
if (response.isSuccess()) { if (response.isSuccess()) {
String status = response.getData().getStatus(); String status = response.getData().getStatus();
System.out.println("当前任务状态: " + status); System.out.println("Current task status: " + status);
if ("succeeded".equalsIgnoreCase(status)) { if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("解析结果获取成功!"); System.out.println("Parsing result obtained successfully!");
System.out.println("解析内容: " + response.getData().getContent()); System.out.println("Parsed content: " + response.getData().getContent());
System.out.println("内容下载链接: " + response.getData().getParsingResultUrl()); System.out.println("Download link: " + response.getData().getParsingResultUrl());
return; return;
} else if ("processing".equalsIgnoreCase(status)) { } else if ("processing".equalsIgnoreCase(status)) {
System.out.println("解析进行中,请稍候..."); System.out.println("Parsing in progress, please wait...");
Thread.sleep(intervalMs); Thread.sleep(intervalMs);
} else { } else {
System.out.println("解析任务异常,状态: " + status + ",消息: " + response.getData().getMessage()); System.out.println("Parsing task exception, status: " + status + ", message: " + response.getData().getMessage());
return; return;
} }
} else { } else {
System.err.println("解析结果获取失败: " + response.getMsg()); System.err.println("Failed to get parsing result: " + response.getMsg());
return; return;
} }
} }
System.out.println("等待超时,请稍后自行查询解析结果。"); System.out.println("Wait timeout, please check the parsing result later.");
} catch (Exception e) { } catch (Exception e) {
System.err.println("获取解析结果时异常: " + e.getMessage()); System.err.println("Exception occurred while getting parsing result: " + e.getMessage());
} }
} }
} }

View file

@ -0,0 +1,64 @@
package ai.z.openapi.samples;
import ai.z.openapi.ZaiClient;
import ai.z.openapi.service.fileparsing.FileParsingDownloadResponse;
import ai.z.openapi.service.fileparsing.FileParsingUploadReq;
import ai.z.openapi.utils.StringUtils;
public class FileParsingSyncExample {
public static void main(String[] args) {
// It is recommended to set the API Key using an environment variable
// export ZAI_API_KEY=your.api_key
// ZaiClient client = ZaiClient.builder().build();
// Alternatively, the API Key can be specified directly in the code
ZaiClient client = ZaiClient.builder()
.apiKey("API Key")
.build();
try {
System.out.println("=== Example: Creating file parsing task ===");
String filePath = "your file path";
FileParsingDownloadResponse result = syncFileParsingTaskExample(client, filePath, "pdf", "prime-sync");
System.out.println("Parsing task created successfully, TaskId: " + result.getData().getTaskId());
System.out.println("File content: " + result.getData().getContent());
System.out.println("Download link: " + result.getData().getParsingResultUrl());
} catch (Exception e) {
System.err.println("Exception occurred: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Example: Create parsing task (upload file and parse)
*
* @param client ZaiClient instance
* @return Parsing task's taskId
*/
private static FileParsingDownloadResponse syncFileParsingTaskExample(ZaiClient client, String filePath, String fileType, String toolType) {
if (StringUtils.isEmpty(filePath)) {
System.err.println("Invalid file path.");
return null;
}
try {
FileParsingUploadReq uploadReq = FileParsingUploadReq.builder()
.filePath(filePath)
.fileType(fileType) // Supported types: pdf, docx, etc.
.toolType(toolType) // Parsing tool type: lite, prime, expert
.build();
System.out.println("Uploading file and creating parsing task...");
return client.fileParsing().syncParse(uploadReq);
} catch (Exception e) {
System.err.println("File parsing task error: " + e.getMessage());
}
// Returning null means task creation failed
return null;
}
}