| @ -0,0 +1,15 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class ApiResponse { | |||||
| private String code; | |||||
| private String message; | |||||
| private Object data; | |||||
| public ApiResponse(String code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,14 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import com.fasterxml.jackson.annotation.JsonInclude; | |||||
| import lombok.Data; | |||||
| import java.util.List; | |||||
| @Data | |||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | |||||
| public class ChatCompletionRequest { | |||||
| private String model; | |||||
| private List<Message> messages; | |||||
| private int maxTokens; | |||||
| } | |||||
| @ -0,0 +1,33 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||||
| import com.fasterxml.jackson.annotation.JsonProperty; | |||||
| import lombok.AllArgsConstructor; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| import java.util.List; | |||||
| @Data | |||||
| @AllArgsConstructor | |||||
| @NoArgsConstructor | |||||
| @JsonIgnoreProperties(ignoreUnknown = true) | |||||
| public class ChatCompletionResponse { | |||||
| private String id; | |||||
| private String object; | |||||
| private long created; | |||||
| private List<Choice> choices; | |||||
| private String info; | |||||
| private Usage usage; | |||||
| @JsonProperty("model") | |||||
| private String model; | |||||
| //存数据库 | |||||
| private String content; | |||||
| private String picPath; | |||||
| } | |||||
| @ -0,0 +1,13 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| @JsonIgnoreProperties(ignoreUnknown = true) // 忽略所有未定义的字段 | |||||
| public class Choice { | |||||
| private int index; | |||||
| private Message message; | |||||
| private String finish_reason; | |||||
| } | |||||
| @ -0,0 +1,17 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import com.fasterxml.jackson.annotation.JsonInclude; | |||||
| import com.fasterxml.jackson.annotation.JsonProperty; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class Content { | |||||
| private String type; // text/image_url | |||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | |||||
| private String text; // type=text时使用 | |||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | |||||
| @JsonProperty("image_url") | |||||
| private ImageUrl imageUrl; // type=image_url时使用 | |||||
| } | |||||
| @ -0,0 +1,15 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import com.fasterxml.jackson.annotation.JsonProperty; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class ContentItem { | |||||
| private String type; // text/image_url/image_base64 | |||||
| private String text; // type=text时使用 | |||||
| @JsonProperty("image_url") | |||||
| private ImageUrl imageUrl; // type=image_url时使用 | |||||
| private String image; // type=image_base64时使用 | |||||
| } | |||||
| @ -0,0 +1,9 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class ImageUrl { | |||||
| private String url; | |||||
| } | |||||
| @ -0,0 +1,23 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import com.fasterxml.jackson.annotation.JsonSetter; | |||||
| import lombok.Data; | |||||
| import java.util.List; | |||||
| @Data | |||||
| public class Message { | |||||
| private String role; | |||||
| // private List<Content> content; | |||||
| private Object content; // 可以是 String 或 List<Content> | |||||
| @JsonSetter("content") | |||||
| public void setContent(Object content) { | |||||
| if (content instanceof String) { | |||||
| this.content = (String) content; | |||||
| } else if (content instanceof List) { | |||||
| this.content = (List<ContentItem>) content; | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,20 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import lombok.AllArgsConstructor; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @AllArgsConstructor | |||||
| public class Multimodal { | |||||
| private String role; | |||||
| private String imageType; | |||||
| private String imageData; | |||||
| private String model; | |||||
| private String text; | |||||
| private String imageName; | |||||
| private int maxTokens; | |||||
| } | |||||
| @ -0,0 +1,10 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class Usage { | |||||
| private int prompt_tokens; | |||||
| private int completion_tokens; | |||||
| private int total_tokens; | |||||
| } | |||||
| @ -0,0 +1,26 @@ | |||||
| package com.inspect.simulator.domain.bigmodelr; | |||||
| import lombok.AllArgsConstructor; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @AllArgsConstructor | |||||
| public class VisualModel { | |||||
| //照片类型(url ,base64) | |||||
| private String image_type; | |||||
| //照片名称 | |||||
| private String image_name; | |||||
| //照片地址(http,https无鉴权) | |||||
| private String image_url; | |||||
| //照片base64 | |||||
| private String image_base64; | |||||
| private String stringData; | |||||
| } | |||||
| @ -0,0 +1,16 @@ | |||||
| package com.inspect.simulator.service; | |||||
| import com.inspect.simulator.domain.bigmodelr.Multimodal; | |||||
| import com.inspect.simulator.domain.bigmodelr.VisualModel; | |||||
| import java.util.List; | |||||
| public interface ModelService { | |||||
| //语义大模型 | |||||
| public String semanticsModel(Multimodal multimodal); | |||||
| } | |||||
| @ -0,0 +1,142 @@ | |||||
| package com.inspect.simulator.service.impl; | |||||
| import com.fasterxml.jackson.annotation.JsonInclude; | |||||
| import com.fasterxml.jackson.core.JsonProcessingException; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import com.google.gson.Gson; | |||||
| import com.inspect.simulator.domain.bigmodelr.*; | |||||
| import com.inspect.simulator.service.ModelService; | |||||
| import okhttp3.*; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.stereotype.Service; | |||||
| import javax.annotation.Resource; | |||||
| import java.io.IOException; | |||||
| import java.net.SocketTimeoutException; | |||||
| import java.nio.file.Files; | |||||
| import java.nio.file.Path; | |||||
| import java.nio.file.Paths; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.*; | |||||
| import java.util.concurrent.TimeUnit; | |||||
| import java.util.stream.Collectors; | |||||
| import java.util.stream.Stream; | |||||
| @Service | |||||
| public class ModelServiceImpl implements ModelService { | |||||
| // 设置支持的图片文件扩展名 | |||||
| private static final List<String> IMAGE_EXTENSIONS = Arrays.asList(".jpg", ".jpeg", ".png"); | |||||
| private final ObjectMapper objectMapper = new ObjectMapper(); | |||||
| private final OkHttpClient httpClient = new OkHttpClient.Builder() | |||||
| .connectTimeout(40, TimeUnit.SECONDS) // 连接超时 | |||||
| .readTimeout(60, TimeUnit.SECONDS) // 读取超时 | |||||
| .writeTimeout(30, TimeUnit.SECONDS) // 写入超时 | |||||
| .build(); | |||||
| public ModelServiceImpl() { | |||||
| // 设置JSON序列化时忽略null值 | |||||
| objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); | |||||
| } | |||||
| //调用语义大模型接口 | |||||
| public String semanticsModel(Multimodal multimodal){ | |||||
| // 重试次数 | |||||
| int maxRetries = 3; | |||||
| int attempt = 0; | |||||
| while (attempt < maxRetries) { | |||||
| try { | |||||
| // 构建请求JSON | |||||
| ChatCompletionRequest request = buildRequestBody(multimodal); | |||||
| System.out.println("创建json" + request.getClass()); | |||||
| // 发送请求并获取响应 | |||||
| ChatCompletionResponse response = semanticsModelResponse(request); | |||||
| String content = String.valueOf(response.getChoices().get(0).getMessage().getContent()); | |||||
| System.out.println("语义大模型返回结果:"+content); | |||||
| return content; | |||||
| } catch (IOException e) { | |||||
| if (attempt == maxRetries) { | |||||
| return "请求超时,请稍后重试"; | |||||
| } | |||||
| System.out.println("第" + attempt + "次尝试超时,准备重试..."); | |||||
| try { | |||||
| Thread.sleep(1000 * attempt); // 指数退避 | |||||
| } catch (InterruptedException ie) { | |||||
| Thread.currentThread().interrupt(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return "请求处理失败"; | |||||
| } | |||||
| private ChatCompletionRequest buildRequestBody(Multimodal multimodal) { | |||||
| ChatCompletionRequest request = new ChatCompletionRequest(); | |||||
| // 设置模型名称,默认"SGGM-VL-74B-V1.2" | |||||
| request.setModel(multimodal.getModel() != null ? multimodal.getModel() : "SGGM-VL-74B-V1.2"); | |||||
| // 构建消息 | |||||
| Message message = new Message(); | |||||
| message.setRole(StringUtils.isNotBlank(multimodal.getRole()) ? multimodal.getRole() : "user"); | |||||
| message.setContent(multimodal.getText()); | |||||
| request.setMessages(Collections.singletonList(message)); | |||||
| return request; | |||||
| } | |||||
| private ChatCompletionResponse semanticsModelResponse(ChatCompletionRequest request) throws IOException { | |||||
| String requestBody; | |||||
| try { | |||||
| requestBody = objectMapper.writeValueAsString(request); | |||||
| } catch (JsonProcessingException e) { | |||||
| throw new IOException("请求体序列化失败", e); | |||||
| } | |||||
| Request httpRequest = new Request.Builder() | |||||
| .url("http://25.80.45.92:18063/lmp-cloud-ias-server/api/llm/chat/completions") | |||||
| .post(RequestBody.create(MediaType.parse("application/json"), requestBody)) | |||||
| .addHeader("Authorization", "Bearer 54c1ae2c5fd54afe85e74d6fe9161f7f") | |||||
| .addHeader("Content-Type", "application/json") | |||||
| .build(); | |||||
| try (Response response = httpClient.newCall(httpRequest).execute()) { | |||||
| if (!response.isSuccessful()) { | |||||
| String errorBody = response.body() != null ? response.body().string() : "无响应体"; | |||||
| throw new IOException(String.format("请求失败,状态码: %d,错误信息: %s", response.code(), errorBody)); | |||||
| } | |||||
| String responseBody = response.body().string(); | |||||
| System.out.println("语义大模型API响应内容: " + responseBody); | |||||
| return objectMapper.readValue(responseBody, ChatCompletionResponse.class); | |||||
| } catch (SocketTimeoutException e) { | |||||
| throw new IOException("请求超时,请检查网络连接或增加超时时间", e); | |||||
| } | |||||
| } | |||||
| } | |||||