Эх сурвалжийг харах

修改core-ai,增加AiService,整合Api接口逻辑合并为简化后的服务方法

Signed-off-by: luoshi <luoshi@qmth.com.cn>
luoshi 1 жил өмнө
parent
commit
c8338a9267

+ 1 - 3
core-ai/src/main/java/com/qmth/boot/core/ai/client/LlmApiClient.java

@@ -10,8 +10,6 @@ import retrofit2.http.Header;
 import retrofit2.http.POST;
 import retrofit2.http.Tag;
 
-import java.util.Map;
-
 /**
  * 大模型应用服务接口
  */
@@ -40,7 +38,7 @@ public interface LlmApiClient {
      */
     @POST(AiConstants.LLM_CHAT_TEMPLATE_PATH)
     ChatResult chatTemplate(@Tag SignatureInfo signature, @Header(AiConstants.LLM_APP_TYPE_HEADER) LlmAppType type,
-            @Body Map<String, Object> param);
+            @Body Object param);
 
     /**
      * 大模型接口余额查询

+ 60 - 0
core-ai/src/main/java/com/qmth/boot/core/ai/model/llm/AutoScoreRequest.java

@@ -0,0 +1,60 @@
+package com.qmth.boot.core.ai.model.llm;
+
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * 自动判分请求参数
+ */
+@Validated
+public class AutoScoreRequest {
+
+    private String subjectName;
+
+    private String questionType;
+
+    private String questionBody;
+
+    private String standardAnswer;
+
+    private String studentAnswer;
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getQuestionType() {
+        return questionType;
+    }
+
+    public void setQuestionType(String questionType) {
+        this.questionType = questionType;
+    }
+
+    public String getQuestionBody() {
+        return questionBody;
+    }
+
+    public void setQuestionBody(String questionBody) {
+        this.questionBody = questionBody;
+    }
+
+    public String getStandardAnswer() {
+        return standardAnswer;
+    }
+
+    public void setStandardAnswer(String standardAnswer) {
+        this.standardAnswer = standardAnswer;
+    }
+
+    public String getStudentAnswer() {
+        return studentAnswer;
+    }
+
+    public void setStudentAnswer(String studentAnswer) {
+        this.studentAnswer = studentAnswer;
+    }
+}

+ 105 - 0
core-ai/src/main/java/com/qmth/boot/core/ai/service/AiService.java

@@ -0,0 +1,105 @@
+package com.qmth.boot.core.ai.service;
+
+import com.qmth.boot.core.ai.client.LlmApiClient;
+import com.qmth.boot.core.ai.client.OcrApiClient;
+import com.qmth.boot.core.ai.model.llm.*;
+import com.qmth.boot.core.ai.model.ocr.OcrType;
+import com.qmth.boot.core.retrofit.utils.SignatureInfo;
+import com.qmth.boot.core.retrofit.utils.UploadFile;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * AI相关功能服务
+ */
+@Service
+public class AiService {
+
+    private static final Pattern score_pattern = Pattern.compile("[^\\d]*(\\d+)[^\\d]*");
+
+    @Resource
+    private LlmApiClient llmApiClient;
+
+    @Resource
+    private OcrApiClient ocrApiClient;
+
+    /**
+     * 获取当前机构大模型接口调用次数余额
+     *
+     * @param appType   大模型接口应用类型
+     * @param signature 使用当前机构AK作为鉴权信息
+     * @return 调用次数余额
+     */
+    public LlmAppBalance getLlmBalance(@NotNull LlmAppType appType, @NotNull SignatureInfo signature) {
+        return llmApiClient.getBalance(signature, appType);
+    }
+
+    /**
+     * 使用自定义提示词进行自动命题
+     *
+     * @param request   大模型通用Chat请求
+     * @param signature 使用当前机构AK作为鉴权信息
+     * @return 大模型返回的文本集合
+     */
+    public List<String> autoGenerateQuestion(@NotNull ChatRequest request, @NotNull SignatureInfo signature) {
+        ChatResult result = llmApiClient.chat(signature, LlmAppType.AUTO_GENERATE_QUESTION, request);
+        return result.getChoices().stream().filter(choice -> choice.getMessage().getRole() == ChatRole.assistant)
+                .map(choice -> choice.getMessage().getContent()).collect(Collectors.toList());
+    }
+
+    /**
+     * 使用预设模版进行自动命题
+     *
+     * @param param     基于预设模版的参数对象,可以使用Map或自定义Object
+     * @param signature 使用当前机构AK作为鉴权信息
+     * @return 大模型返回的文本集合
+     */
+    public List<String> autoGenerateQuestion(@NotNull Object param, @NotNull SignatureInfo signature) {
+        ChatResult result = llmApiClient.chatTemplate(signature, LlmAppType.AUTO_GENERATE_QUESTION, param);
+        return result.getChoices().stream().filter(choice -> choice.getMessage().getRole() == ChatRole.assistant)
+                .map(choice -> choice.getMessage().getContent()).collect(Collectors.toList());
+    }
+
+    /**
+     * 使用预设模版进行自动判分,考生作答为文本
+     *
+     * @param request   自动判分请求参数
+     * @param signature 使用当前机构AK作为鉴权信息
+     * @return 得分率,保留最多三位小数;null表示无法获取判分结果
+     */
+    public Double autoScore(@NotNull AutoScoreRequest request, @NotNull SignatureInfo signature) {
+        ChatResult result = llmApiClient.chatTemplate(signature, LlmAppType.AUTO_SCORE, request);
+        String text = result.getChoices().stream().filter(choice -> choice.getMessage().getRole() == ChatRole.assistant)
+                .map(choice -> choice.getMessage().getContent()).findFirst().orElse("");
+        Matcher m = score_pattern.matcher(text);
+        if (m.find()) {
+            return new BigDecimal(Integer.parseInt(m.group(1))).divide(BigDecimal.valueOf(100), 3, RoundingMode.HALF_UP)
+                    .doubleValue();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 使用预设模版进行自动判分,考生作答为图片
+     *
+     * @param request   自动判分请求参数
+     * @param image     图片内容
+     * @param signature 使用当前机构AK作为鉴权信息
+     * @return 得分率,保留最多三位小数;null表示无法获取判分结果
+     */
+    public Double autoScore(@NotNull AutoScoreRequest request, @NotNull byte[] image,
+            @NotNull SignatureInfo signature) {
+        request.setStudentAnswer(
+                ocrApiClient.forImage(signature, OcrType.HANDWRITING, UploadFile.build("image", "", image)));
+        return autoScore(request, signature);
+    }
+}