|
@@ -0,0 +1,114 @@
|
|
|
+package com.qmth.ops.biz.ai.client.aliyun.qwen_ocr;
|
|
|
+
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.qmth.boot.core.ai.model.llm.ChatRole;
|
|
|
+import com.qmth.boot.core.ai.model.ocr.OcrType;
|
|
|
+import com.qmth.boot.tools.codec.CodecUtils;
|
|
|
+import com.qmth.boot.tools.models.ByteArray;
|
|
|
+import com.qmth.ops.biz.ai.client.OcrApiClient;
|
|
|
+import com.qmth.ops.biz.ai.client.OcrApiConfig;
|
|
|
+import com.qmth.ops.biz.ai.exception.ChatRequestError;
|
|
|
+import okhttp3.MediaType;
|
|
|
+import okhttp3.Request;
|
|
|
+import okhttp3.RequestBody;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+public class QwenOcrClient extends OcrApiClient {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(QwenOcrClient.class);
|
|
|
+
|
|
|
+ public QwenOcrClient(OcrApiConfig config) {
|
|
|
+ super(config);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected Request buildRequest(OcrType type, byte[] image) throws Exception {
|
|
|
+ Map<String, Object> request = new HashMap<>();
|
|
|
+ request.put("model", "qwen-vl-ocr");
|
|
|
+ List<Map<String, Object>> messages = new ArrayList<>();
|
|
|
+ Map<String, Object> message = new HashMap<>();
|
|
|
+ message.put("role", "user");
|
|
|
+ List<Map<String, Object>> contents = new ArrayList<>();
|
|
|
+ Map<String, Object> content1 = new HashMap<>();
|
|
|
+ content1.put("type", "image_url");
|
|
|
+ Map<String, String> urlBase64 = new HashMap<>();
|
|
|
+ String base64 = CodecUtils.toBase64(image);
|
|
|
+ urlBase64.put("url", "data:image/jpeg;base64," + base64);
|
|
|
+ content1.put("image_url", urlBase64);
|
|
|
+ // content1.put("min_pixels", 1000);
|
|
|
+ // content1.put("max_pixels", 1280000);
|
|
|
+ Map<String, Object> content2 = new HashMap<>();
|
|
|
+ content2.put("type", "text");
|
|
|
+ content2.put("text", "Read all the text in the image.");
|
|
|
+ contents.add(content1);
|
|
|
+ contents.add(content2);
|
|
|
+ messages.add(message);
|
|
|
+ message.put("content", contents);
|
|
|
+ request.put("messages", messages);
|
|
|
+
|
|
|
+ String json = new ObjectMapper().writeValueAsString(request);
|
|
|
+ log.info("request:{}", json);
|
|
|
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), json);
|
|
|
+ return new Request.Builder().url(getConfig().getUrl())
|
|
|
+ .addHeader("Authorization", "Bearer " + getConfig().getSecret())
|
|
|
+ .post(requestBody)
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected String buildResult(byte[] data, ObjectMapper mapper) throws IOException {
|
|
|
+ String json = data != null ? new String(data, StandardCharsets.UTF_8) : null;
|
|
|
+ log.info("response:{}", json);
|
|
|
+
|
|
|
+ QwenOcrResult result = mapper.readValue(json, QwenOcrResult.class);
|
|
|
+ return result.getChoices().stream().filter(choice -> choice.getMessage().getRole() == ChatRole.assistant)
|
|
|
+ .map(choice -> choice.getMessage().getContent()).findFirst().orElse("");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected String handleError(byte[] data, int statusCode, ObjectMapper mapper) {
|
|
|
+ String error = data != null ? new String(data, StandardCharsets.UTF_8) : null;
|
|
|
+ log.info("responseError:{}", error);
|
|
|
+
|
|
|
+ if (data != null) {
|
|
|
+ try {
|
|
|
+ QwenOcrResponse response = mapper.readValue(data, QwenOcrResponse.class);
|
|
|
+ if (response != null && response.getError() != null) {
|
|
|
+ error = response.getError().getMessage();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("handleError failed! {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (statusCode) {
|
|
|
+ case 400:
|
|
|
+ throw new ChatRequestError(Optional.ofNullable(error).orElse("chat request error"));
|
|
|
+ case 429:
|
|
|
+ throw new ChatRequestError(Optional.ofNullable(error).orElse("chat model rate limit exceeded"));
|
|
|
+ default:
|
|
|
+ throw new ChatRequestError(Optional.ofNullable(error).orElse("chat model error"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) throws Exception {
|
|
|
+ OcrApiConfig config = new OcrApiConfig();
|
|
|
+ config.setUrl("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions");
|
|
|
+ // config.setUrl("https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation");
|
|
|
+ config.setSecret("sk-xxx");
|
|
|
+ config.setQps(10);
|
|
|
+
|
|
|
+ File file = new File("D:\\home\\test.png");
|
|
|
+ byte[] image = ByteArray.fromFile(file).value();
|
|
|
+ QwenOcrClient client = new QwenOcrClient(config);
|
|
|
+ String value = client.forImage(OcrType.HANDWRITING, image);
|
|
|
+ System.out.println(value);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|