Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions core/src/main/java/ai/z/openapi/AbstractAiClient.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ai.z.openapi;

import ai.z.openapi.service.AbstractClientBaseService;
import ai.z.openapi.service.fileparsing.FileParsingService;
import ai.z.openapi.service.fileparsing.FileParsingServiceImpl;
import ai.z.openapi.service.model.ChatError;
import ai.z.openapi.service.model.ZAiHttpException;
import ai.z.openapi.service.chat.ChatService;
Expand Down Expand Up @@ -106,6 +108,9 @@ public abstract class AbstractAiClient extends AbstractClientBaseService {
/** Voice clone service for voice cloning operations */
private VoiceCloneService voiceCloneService;

/** FileParsing service for fileParsing operations */
private FileParsingService fileParsingService;

/** Moderation service for content safety detection */
private ModerationService moderationService;

Expand Down Expand Up @@ -261,6 +266,18 @@ public synchronized VoiceCloneService voiceClone() {
return voiceCloneService;
}

/**
* Returns the file service for file operations. This service handles file uploads,
* downloads, and management.
* @return the FileParsingService instance (lazily initialized)
*/
public synchronized FileParsingService fileParsing() {
if (fileParsingService == null) {
this.fileParsingService = new FileParsingServiceImpl(this);
}
return fileParsingService;
}

/**
* Returns the moderation service for content safety detection. This service handles
* content moderation for text, image, video, and audio inputs.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ai.z.openapi.api.fileparsing;

import ai.z.openapi.service.fileparsing.FileParsingUploadResp;
import ai.z.openapi.service.fileparsing.FileParsingDownloadResp;
import io.reactivex.rxjava3.core.Single;
import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.Streaming;
import retrofit2.http.Part;
import retrofit2.http.Multipart;
import retrofit2.http.Header;

import java.io.File;

/**
* File Parsing API Provides functionality for uploading files for parsing, and retrieving
* the parsing results.
*/
public interface FileParsingApi {

/**
* Create a file parsing task. Uploads a file and creates a document parsing job using
* specific tool type and file type.
* @param multipartBody File data with metadata including tool_type and file_type
* @return Information and status of the parsing job
*/
// @Multipart
@POST("files/parser/create")
Single<FileParsingUploadResp> createParseTask(@Body MultipartBody multipartBody);

/**
* Get a file parsing result. Retrieves the parsing result by taskId and format type.
* @param taskId The unique task ID for the parsing job
* @param formatType The format type of the parsing result
* @return Parsing result content (JSON or raw format)
*/
@Streaming
@GET("files/parser/result/{taskId}/{formatType}")
Call<ResponseBody> downloadParseResult(@Path("taskId") String taskId, @Path("formatType") String formatType);

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import ai.z.openapi.service.batches.BatchRequest;
import ai.z.openapi.service.model.ChatError;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
Expand All @@ -16,7 +15,6 @@
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class FileDelRequest implements ClientRequest<FileDelRequest> {

private String fileId;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ai.z.openapi.service.fileparsing;

import ai.z.openapi.core.model.ClientRequest;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
* File parsing result download request parameters
*/
@EqualsAndHashCode(callSuper = false)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class FileParsingDownloadReq implements ClientRequest<FileParsingDownloadReq> {

/**
* Parsing task ID (required)
*/
private String taskId;

/**
* Returned content format type (e.g., "download_link", "txt", required)
*/
private String formatType;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ai.z.openapi.service.fileparsing;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
* File parsing result response DTO
*/
@EqualsAndHashCode(callSuper = false)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class FileParsingDownloadResp {

/**
* Parsing task ID
*/
@JsonProperty("task_id")
private String taskId;

/**
* Result status (e.g., succeeded, failed, etc.)
*/
@JsonProperty("status")
private String status;

/**
* Response message
*/
@JsonProperty("message")
private String message;

/**
* Parsed result content
*/
@JsonProperty("content")
private String content;

/**
* Parsing result download link (if available)
*/
@JsonProperty("parsing_result_url")
private String parsingResultUrl;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ai.z.openapi.service.fileparsing;

import ai.z.openapi.core.model.ClientResponse;
import ai.z.openapi.service.model.ChatError;
import lombok.Data;

@Data
public class FileParsingDownloadResponse implements ClientResponse<FileParsingDownloadResp> {

/**
* Response status code.
*/
private int code;

/**
* Response message.
*/
private String msg;

/**
* Indicates whether the request was successful.
*/
private boolean success;

/**
* The FileParsing result data.
*/
private FileParsingDownloadResp data;

/**
* Error information if the request failed.
*/
private ChatError error;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ai.z.openapi.service.fileparsing;

import ai.z.openapi.core.model.ClientResponse;
import ai.z.openapi.service.model.ChatError;
import lombok.Data;

@Data
public class FileParsingResponse implements ClientResponse<FileParsingUploadResp> {

/**
* Response status code.
*/
private int code;

/**
* Response message.
*/
private String msg;

/**
* Indicates whether the request was successful.
*/
private boolean success;

/**
* The FileParsing result data.
*/
private FileParsingUploadResp data;

/**
* Error information if the request failed.
*/
private ChatError error;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ai.z.openapi.service.fileparsing;

/**
* File parsing service interface
*/
public interface FileParsingService {

/**
* Submits a file parsing task to the server.
* @param request The file parsing upload request
* @return FileParsingUploadResp containing the parsing task info
*/
FileParsingResponse createParseTask(FileParsingUploadReq request);

/**
* Retrieves the result of a parsing task.
* @param request The parsing result query request (can include taskId, formatType
* etc)
* @return FileParsingDownloadResp containing the result content
*/
FileParsingDownloadResponse getParseResult(FileParsingDownloadReq request);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package ai.z.openapi.service.fileparsing;

import ai.z.openapi.AbstractAiClient;
import ai.z.openapi.api.fileparsing.FileParsingApi;
import ai.z.openapi.core.response.HttpxBinaryResponseContent;
import ai.z.openapi.utils.RequestSupplier;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.reactivex.rxjava3.core.Single;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Response;

import java.io.File;
import java.io.IOException;

/**
* File parsing service implementation
*/
public class FileParsingServiceImpl implements FileParsingService {

private final AbstractAiClient zAiClient;

private final FileParsingApi fileParsingApi;

public FileParsingServiceImpl(AbstractAiClient zAiClient) {
this.zAiClient = zAiClient;
this.fileParsingApi = zAiClient.retrofit().create(FileParsingApi.class);
}

@Override
public FileParsingResponse createParseTask(FileParsingUploadReq request) {
if (request == null) {
throw new IllegalArgumentException("request cannot be null");
}
if (request.getFilePath() == null) {
throw new IllegalArgumentException("file path cannot be null");
}
if (request.getToolType() == null) {
throw new IllegalArgumentException("toolType cannot be null");
}
// 构建 multipart/form-data
RequestSupplier<FileParsingUploadReq, FileParsingUploadResp> supplier = params -> {
try {
File file = new File(params.getFilePath());
if (!file.exists()) {
throw new RuntimeException("file not found");
}

String toolType = params.getToolType();
String fileType = params.getFileType() == null ? "" : params.getFileType();

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();

return fileParsingApi.createParseTask(multipartBody);
}
catch (Exception e) {
throw new RuntimeException(e);
}
};
return this.zAiClient.executeRequest(request, supplier, FileParsingResponse.class);
}

@Override
public FileParsingDownloadResponse getParseResult(FileParsingDownloadReq request) {
if (request == null) {
throw new IllegalArgumentException("request cannot be null");
}
if (request.getTaskId() == null) {
throw new IllegalArgumentException("taskId cannot be null");
}
if (request.getFormatType() == null) {
throw new IllegalArgumentException("formatType cannot be null");
}

RequestSupplier<FileParsingDownloadReq, FileParsingDownloadResp> supplier = params -> {
try {
retrofit2.Call<ResponseBody> call = fileParsingApi.downloadParseResult(request.getTaskId(),
request.getFormatType());
Response<ResponseBody> execute = call.execute();
if (!execute.isSuccessful() || execute.body() == null) {
throw new IOException("Failed to download parse result");
}

HttpxBinaryResponseContent httpxBinaryResponseContent = new HttpxBinaryResponseContent(execute);
String result = httpxBinaryResponseContent.getText();

ObjectMapper mapper = new ObjectMapper();
FileParsingDownloadResp fileParsingDownloadResp = mapper.readValue(result,
FileParsingDownloadResp.class);

return Single.just(fileParsingDownloadResp);
}
catch (Exception e) {
throw new RuntimeException(e);
}
};

return this.zAiClient.executeRequest(request, supplier, FileParsingDownloadResponse.class);
}

}
Loading
Loading