|
@@ -0,0 +1,235 @@
|
|
|
+package com.ruoyi.common.utils.moonshot;
|
|
|
+
|
|
|
+import com.ruoyi.common.utils.moonshot.vo.*;
|
|
|
+import com.google.gson.Gson;
|
|
|
+import io.reactivex.BackpressureStrategy;
|
|
|
+import io.reactivex.Flowable;
|
|
|
+import okhttp3.*;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.context.annotation.Configuration;
|
|
|
+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<ChatCompletionStreamResponse> 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);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|