package com.ruoyi.common.utils.moonshot; import com.google.gson.Gson; import com.ruoyi.common.utils.moonshot.vo.*; import io.reactivex.BackpressureStrategy; import io.reactivex.Flowable; import okhttp3.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.Objects; import java.util.concurrent.TimeUnit; public class Client { private static final String DEFAULT_BASE_URL = "https://api.moonshot.cn/v1"; private static final String CHAT_COMPLETION_SUFFIX = "/chat/completions"; private static final String MODELS_SUFFIX = "/models"; private static final String FILES_SUFFIX = "/files"; private String baseUrl; private String apiKey; public Client(String apiKey) { this(apiKey, DEFAULT_BASE_URL); } public Client(String apiKey, String baseUrl) { this.apiKey = apiKey; if (baseUrl.endsWith("/")) { baseUrl = baseUrl.substring(0, baseUrl.length() - 1); } this.baseUrl = baseUrl; } public String getChatCompletionUrl() { return baseUrl + CHAT_COMPLETION_SUFFIX; } public String getModelsUrl() { return baseUrl + MODELS_SUFFIX; } public String getFilesUrl() { return baseUrl + FILES_SUFFIX; } public String getApiKey() { return apiKey; } /** * * @return * @throws IOException */ public ModelsList ListModels() throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(getModelsUrl()) .addHeader("Authorization", "Bearer " + getApiKey()) .build(); try { Response response = client.newCall(request).execute(); String body = response.body().string(); Gson gson = new Gson(); return gson.fromJson(body, ModelsList.class); } catch (IOException e) { e.printStackTrace(); throw e; } } public String uploadFiles(File file) throws IOException { OkHttpClient client = new OkHttpClient(); // 假设你有一个文件对象 "file" 需要上传 // 这里还需要知道文件的MIME类型,这里以"application/octet-stream"为例,表示任意二进制数据 MediaType MEDIA_TYPE_OCTET_STREAM = MediaType.parse("application/octet-stream"); // 创建一个RequestBody来包装你的文件 RequestBody fileBody = RequestBody.create(MEDIA_TYPE_OCTET_STREAM, file); // 使用MultipartBody.Builder来构建请求体 MultipartBody.Builder multipartBuilder = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", file.getName(), fileBody); // "file" 是表单的键,通常与服务端约定 // 如果还有其他表单字段,可以这样添加 // .addFormDataPart("key", "value"); MultipartBody multipartBody = multipartBuilder.build(); // 使用multipartBody作为POST请求的请求体 Request request = new Request.Builder() .url(getFilesUrl()) .addHeader("Authorization", "Bearer " + getApiKey()) .post(multipartBody) .build(); try { Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } // 假设服务器返回的是JSON格式的响应 return response.body().string(); } catch (IOException e) { e.printStackTrace(); throw e; } } public ChatCompletionResponse ChatCompletion(ChatCompletionRequest request) throws IOException { request.stream = false; OkHttpClient client = new OkHttpClient(); MediaType mediaType = MediaType.parse("application/json"); RequestBody body = RequestBody.create(mediaType, new Gson().toJson(request)); Request httpRequest = new Request.Builder() .url(getChatCompletionUrl()) .addHeader("Authorization", "Bearer " + getApiKey()) .addHeader("Content-Type", "application/json") .post(body) .build(); try { Response response = client.newCall(httpRequest).execute(); String responseBody = response.body().string(); Gson gson = new Gson(); return gson.fromJson(responseBody, ChatCompletionResponse.class); } catch (IOException e) { e.printStackTrace(); throw e; } } // return a stream of ChatCompletionStreamResponse public Flowable ChatCompletionStream(ChatCompletionRequest request) throws IOException { request.stream = true; OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(30000, TimeUnit.SECONDS) .build(); MediaType mediaType = MediaType.parse("application/json"); RequestBody body = RequestBody.create(mediaType, new Gson().toJson(request)); Request httpRequest = new Request.Builder() .url(getChatCompletionUrl()) .addHeader("Authorization", "Bearer " + getApiKey()) .addHeader("Content-Type", "application/json") .post(body) .build(); Response response = client.newCall(httpRequest).execute(); if (response.code() != 200) { throw new RuntimeException("Failed to start stream: " + response.body().string()); } // get response body line by line return Flowable.create(emitter -> { ResponseBody responseBody = response.body(); if (responseBody == null) { emitter.onError(new RuntimeException("Response body is null")); return; } String line; while ((line = responseBody.source().readUtf8Line()) != null) { if (line.startsWith("data:")) { line = line.substring(5); line = line.trim(); } if (Objects.equals(line, "[DONE]")) { emitter.onComplete(); return; } line = line.trim(); if (line.isEmpty()) { continue; } Gson gson = new Gson(); ChatCompletionStreamResponse streamResponse = gson.fromJson(line, ChatCompletionStreamResponse.class); emitter.onNext(streamResponse); } emitter.onComplete(); }, BackpressureStrategy.BUFFER); } public FileUploadResult uploadFile(File file) throws IOException { OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(30000, TimeUnit.SECONDS) .build(); RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("file",file.getPath(), RequestBody.create(MediaType.parse("application/octet-stream"), file)) .addFormDataPart("purpose", "file-extract") .build(); Request request = new Request.Builder() .url(getFilesUrl()) .method("POST", body) .addHeader("Authorization", "Bearer " + getApiKey()) .build(); Response response = client.newCall(request).execute(); String responseBody = response.body().string(); Gson gson = new Gson(); return gson.fromJson(responseBody, FileUploadResult.class); } public FileUploadResult uploadFile(MultipartFile file) throws IOException { OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(30000, TimeUnit.SECONDS) .build(); RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("file",file.getOriginalFilename(), RequestBody.create(MediaType.parse("application/octet-stream"), file.getBytes())) .addFormDataPart("purpose", "file-extract") .build(); Request request = new Request.Builder() .url(getFilesUrl()) .method("POST", body) .addHeader("Authorization", "Bearer " + getApiKey()) .build(); Response response = client.newCall(request).execute(); String responseBody = response.body().string(); Gson gson = new Gson(); return gson.fromJson(responseBody, FileUploadResult.class); } }