@PostMapping(value = "/validate", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public List<ValidationResult> validateDocument(@RequestPart("file") MultipartFile file, @RequestPart("expectedConfig") String expectedConfig) throws Exception { JsonNode jsonNode = parseJson(expectedConfig); return param.validateImagePrecisely(file, jsonNode); } public JsonNode parseJson(String jsonContent) throws Exception { return objectMapper.readTree(jsonContent); } private final ObjectMapper objectMapper = new ObjectMapper(); private static final String BASE_URL = "http://10.191.39.243:8000/v1"; private static final String API_KEY = "Luxsan20250701"; private static final String MODEL_NAME = "/models/Qwen2.5-VL-72B-Instruct"; // 主验证方法 public List<ValidationResult> validateImagePrecisely(MultipartFile file, JsonNode expectedConfig) { try { String imageUrl = convertToBase64(file); //调用大模型OCR结果 String modelResponse =recognizeTextFromImage(imageUrl); //解析API响应 JsonNode responseNode = objectMapper.readTree(modelResponse); if (!responseNode.path("success").asBoolean()) { String errorMsg = responseNode.path("message").asText(); log.error("OCR API调用失败: {}", errorMsg); return Collections.singletonList( new ValidationResult("SYSTEM", "API_ERROR", "API调用成功", "API调用失败: " + errorMsg, false) ); } //提取OCR结果 JsonNode actualData = responseNode.path("data").path("ocr_result"); log.info("OCR识别结果: {}", actualData.toPrettyString()); //比较 return preciseCompare(actualData, expectedConfig); } catch (Exception e) { log.error("验证过程异常: {}", e.getMessage(), e); return Collections.singletonList( new ValidationResult("SYSTEM", "EXCEPTION", "正常处理", "系统错误: " + e.getMessage(), false) ); } } private String convertToBase64(MultipartFile file) throws IOException { String contentType = Optional.ofNullable(file.getContentType()) .orElse("image/jpeg"); try (InputStream is = file.getInputStream()) { byte[] bytes = IOUtils.toByteArray(is); return "data:" + contentType + ";base64," + Base64.getEncoder().encodeToString(bytes); } } // 精准字段比较 private List<ValidationResult> preciseCompare(JsonNode actualData, JsonNode expectedConfig) { List<ValidationResult> results = new ArrayList<>(); // 遍历所有预期字段 expectedConfig.fields().forEachRemaining(entry -> { String field = entry.getKey(); String expectedValue = entry.getValue().asText(); JsonNode actualNode = actualData.path(field); if (actualNode.isMissingNode()) { results.add(new ValidationResult("FIELD", field, expectedValue, "字段不存在", false)); return; } String actualValue = actualNode.asText(); boolean found = actualValue.equals(expectedValue); results.add(new ValidationResult( "FIELD", field, String.join("", expectedValue), found ? "Found" : "Not Found", found )); }); return results; } //大模型 public String recognizeTextFromImage(String imageUrl) throws IOException { URL url = new URL(BASE_URL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Authorization", "Bearer " + API_KEY); connection.setRequestProperty("Content-Type", "application/json"); connection.setDoOutput(true); // 2. 构建请求体 JSONObject requestBody = new JSONObject(); requestBody.put("model", MODEL_NAME); JSONArray messages = new JSONArray(); JSONObject message = new JSONObject(); message.put("role", "user"); JSONArray content = new JSONArray(); // 文本指令 JSONObject textContent = new JSONObject(); textContent.put("type", "text"); textContent.put("text", "提取图片中的所有文本内容,并按照json格式输出"); content.put(textContent); // 图像URL JSONObject imageContent = new JSONObject(); imageContent.put("type", "image_url"); JSONObject imageUrlObj = new JSONObject(); imageUrlObj.put("url", imageUrl); imageContent.put("image_url", imageUrlObj); content.put(imageContent); message.put("content", content); messages.put(message); requestBody.put("messages", messages); // 3. 发送请求 try (OutputStream os = connection.getOutputStream()) { byte[] input = requestBody.toString().getBytes(StandardCharsets.UTF_8); os.write(input, 0, input.length); } // 4. 获取响应 int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { try (BufferedReader br = new BufferedReader( new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { StringBuilder response = new StringBuilder(); String responseLine; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } // 解析响应,提取模型返回的内容 JSONObject jsonResponse = new JSONObject(response.toString()); JSONArray choices = jsonResponse.getJSONArray("choices"); if (choices.length() > 0) { JSONObject firstChoice = choices.getJSONObject(0); JSONObject messageObj = firstChoice.getJSONObject("message"); return messageObj.getString("content"); } else { throw new IOException("未获取到有效响应"); } } } else { // 读取错误流 try (BufferedReader br = new BufferedReader( new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) { StringBuilder errorResponse = new StringBuilder(); String line; while ((line = br.readLine()) != null) { errorResponse.append(line); } throw new IOException("HTTP请求失败: " + responseCode + ", 错误信息: " + errorResponse.toString()); } } }org.springframework.web.multipart.MultipartException: Current request is not a multipart request我在后端测试的时候报错
最新发布