From 76858d26a9ddb6a298e57be41b2b04aa9ed94e79 Mon Sep 17 00:00:00 2001 From: cst61 Date: Fri, 15 May 2026 11:23:17 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=84=E4=BC=B0=E7=94=B3=E8=AF=B7=E8=B0=83?= =?UTF-8?q?=E7=A0=94=E5=A4=A7=E6=A8=A1=E5=9E=8B=E8=A7=A3=E6=9E=90=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LbAssessmentApplyController.java | 36 ++++- .../controller/LbPurchaseApplyController.java | 3 +- .../java/com/rj/entity/LbAssessmentApply.java | 12 ++ .../rj/service/ILbAssessmentApplyService.java | 10 +- .../impl/LbAssessmentApplyServiceImpl.java | 142 +++++++++++++++++- 5 files changed, 197 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/rj/controller/LbAssessmentApplyController.java b/src/main/java/com/rj/controller/LbAssessmentApplyController.java index c9e9fc0..9cef0eb 100644 --- a/src/main/java/com/rj/controller/LbAssessmentApplyController.java +++ b/src/main/java/com/rj/controller/LbAssessmentApplyController.java @@ -4,7 +4,11 @@ import com.rj.entity.LbAssessmentApply; import com.rj.service.ILbAssessmentApplyService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,6 +23,30 @@ public class LbAssessmentApplyController { @Autowired private ILbAssessmentApplyService lbAssessmentApplyService; + @Data + @Schema(description = "大模型解析申请评估信息请求体") + public static class ParseAssessmentTextRequest { + @Schema(description = "申请评估原文", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "申请评估文本不能为空") + private String assessmentText; + + @Schema(description = "当前登录人租户ID") + private String tenantId; + } + + @PostMapping("/parseAssessmentApplyFromText") + @Operation(summary = "大模型解析申请评估文本为实体", description = "根据自然语言申请评估信息调用大模型抽取字段,返回 LbAssessmentApply(不落库)") + public ResponseEntity> parseAssessmentApplyFromText( + @Parameter(description = "申请评估文本与租户ID", required = true) @Valid @RequestBody ParseAssessmentTextRequest body) { + Map result = lbAssessmentApplyService.parseFromAssessmentTextByLlm( + body.getAssessmentText(), body.getTenantId()); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + return ResponseEntity.badRequest().body(result); + } + @PostMapping("/add") @Operation(summary = "新增") public ResponseEntity> add( @@ -64,9 +92,13 @@ public class LbAssessmentApplyController { @RequestParam(required = false) String applicantName, @RequestParam(required = false) String applicantPhone, @RequestParam(required = false) String colleagueName, - @RequestParam(required = false) String teamLeaderName) { + @RequestParam(required = false) String teamLeaderName, + @RequestParam(required = false) String assessmentTeacherName, + @RequestParam(required = false) String moderatorName, + @RequestParam(required = false) String meetingNumber) { Map result = lbAssessmentApplyService.pageQuery( - current, size, tenantId, applicantName, applicantPhone, colleagueName, teamLeaderName + current, size, tenantId, applicantName, applicantPhone, colleagueName, teamLeaderName, + assessmentTeacherName, moderatorName, meetingNumber ); Boolean success = (Boolean) result.get("success"); if (success != null && success) { diff --git a/src/main/java/com/rj/controller/LbPurchaseApplyController.java b/src/main/java/com/rj/controller/LbPurchaseApplyController.java index ada55a6..3533fa8 100644 --- a/src/main/java/com/rj/controller/LbPurchaseApplyController.java +++ b/src/main/java/com/rj/controller/LbPurchaseApplyController.java @@ -32,8 +32,7 @@ public class LbPurchaseApplyController { @NotBlank(message = "订货信息不能为空") private String orderInfo; - @Schema(description = "当前登录人租户ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "tenantId不能为空") + @Schema(description = "当前登录人租户ID") private String tenantId; } diff --git a/src/main/java/com/rj/entity/LbAssessmentApply.java b/src/main/java/com/rj/entity/LbAssessmentApply.java index 9ac4263..aca196b 100644 --- a/src/main/java/com/rj/entity/LbAssessmentApply.java +++ b/src/main/java/com/rj/entity/LbAssessmentApply.java @@ -54,6 +54,18 @@ public class LbAssessmentApply implements Serializable { @Schema(description = "团队长姓名") private String teamLeaderName; + @TableField("assessment_teacher_name") + @Schema(description = "评估老师姓名") + private String assessmentTeacherName; + + @TableField("moderator_name") + @Schema(description = "主持人姓名") + private String moderatorName; + + @TableField("meeting_number") + @Schema(description = "会议号") + private String meetingNumber; + @TableField("application_datetime") @Schema(description = "申请日期时间") private LocalDateTime applicationDatetime; diff --git a/src/main/java/com/rj/service/ILbAssessmentApplyService.java b/src/main/java/com/rj/service/ILbAssessmentApplyService.java index 37e9146..7204812 100644 --- a/src/main/java/com/rj/service/ILbAssessmentApplyService.java +++ b/src/main/java/com/rj/service/ILbAssessmentApplyService.java @@ -19,6 +19,14 @@ public interface ILbAssessmentApplyService extends IService { String applicantName, String applicantPhone, String colleagueName, - String teamLeaderName); + String teamLeaderName, + String assessmentTeacherName, + String moderatorName, + String meetingNumber); + + /** + * 根据自然语言申请评估信息调用大模型抽取为 {@link LbAssessmentApply}(不落库)。 + */ + Map parseFromAssessmentTextByLlm(String assessmentText, String tenantId); } diff --git a/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java b/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java index 73086f6..91f6e63 100644 --- a/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java +++ b/src/main/java/com/rj/service/impl/LbAssessmentApplyServiceImpl.java @@ -1,15 +1,26 @@ package com.rj.service.impl; +import com.alibaba.dashscope.aigc.generation.Generation; +import com.alibaba.dashscope.aigc.generation.GenerationParam; +import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.common.Message; +import com.alibaba.dashscope.common.Role; +import com.alibaba.dashscope.exception.InputRequiredException; +import com.alibaba.dashscope.exception.NoApiKeyException; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fasterxml.jackson.databind.ObjectMapper; import com.rj.entity.LbAssessmentApply; import com.rj.mapper.LbAssessmentApplyMapper; import com.rj.service.ILbAssessmentApplyService; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -20,6 +31,123 @@ public class LbAssessmentApplyServiceImpl extends ServiceImpl implements ILbAssessmentApplyService { + @Autowired + private ObjectMapper objectMapper; + + @Value("${langchain4j.open-ai.chat-model.model-name:qwen-plus}") + private String dashScopeChatModel; + + private static final String ASSESSMENT_PARSE_SYSTEM_PROMPT = """ + 你是信息抽取助手。用户会提供一段与「申请评估」相关的自然语言描述。 + 请只输出一个 JSON 对象,不要 markdown 代码块,不要解释性文字。 + 字段均为可选;无法从原文推断的字段请省略或设为 null。 + 字段名与含义(JSON 键名必须完全一致,与 Java 驼峰一致): + applicantName 申请人姓名; + applicantPhone 申请人电话; + applicantAge 年龄(整数); + workExperience 从业经历; + colleagueName 同事姓名; + colleaguePhone 同事电话; + teamLeaderName 团队长姓名; + assessmentTeacherName 评估老师姓名; + moderatorName 主持人姓名; + meetingNumber 会议号; + applicationDatetime 申请日期时间,优先 ISO-8601(如 2026-05-15T14:30:00),也可 yyyy-MM-dd HH:mm:ss;若仅有日期可设为当天 00:00:00。 + 不要输出 id、tenantId、createdAt、updatedAt。 + """; + + @Override + public Map parseFromAssessmentTextByLlm(String assessmentText, String tenantId) { + Map result = new HashMap<>(); + try { + if (assessmentText == null || assessmentText.trim().isEmpty()) { + result.put("success", false); + result.put("message", "申请评估文本不能为空"); + return result; + } + if (tenantId == null || tenantId.trim().isEmpty()) { + result.put("success", false); + result.put("message", "tenantId不能为空"); + return result; + } + + String apiKey = System.getenv("DASHSCOPE_API_KEY"); + if (apiKey == null || apiKey.isEmpty()) { + result.put("success", false); + result.put("message", "未配置环境变量 DASHSCOPE_API_KEY,无法调用大模型"); + return result; + } + + Generation gen = new Generation(); + Message systemMsg = Message.builder() + .role(Role.SYSTEM.getValue()) + .content(ASSESSMENT_PARSE_SYSTEM_PROMPT) + .build(); + Message userMsg = Message.builder() + .role(Role.USER.getValue()) + .content("申请评估信息如下:\n" + assessmentText.trim()) + .build(); + + GenerationParam param = GenerationParam.builder() + .apiKey(apiKey) + .model(dashScopeChatModel) + .messages(Arrays.asList(systemMsg, userMsg)) + .resultFormat(GenerationParam.ResultFormat.MESSAGE) + .build(); + + GenerationResult call = gen.call(param); + String raw = call.getOutput().getChoices().get(0).getMessage().getContent(); + if (raw == null || raw.trim().isEmpty()) { + result.put("success", false); + result.put("message", "大模型返回内容为空"); + return result; + } + + String json = normalizeJson(raw); + LbAssessmentApply entity = objectMapper.readValue(json, LbAssessmentApply.class); + + entity.setTenantId(tenantId.trim()); + entity.setId(null); + entity.setCreatedAt(null); + entity.setUpdatedAt(null); + + result.put("success", true); + result.put("message", "解析成功"); + result.put("data", entity); + return result; + } catch (NoApiKeyException e) { + log.error("DashScope API Key 异常", e); + result.put("success", false); + result.put("message", "API密钥异常:" + e.getMessage()); + return result; + } catch (InputRequiredException e) { + log.error("DashScope 入参异常", e); + result.put("success", false); + result.put("message", "调用大模型入参错误:" + e.getMessage()); + return result; + } catch (Exception e) { + log.error("申请评估信息大模型解析失败", e); + result.put("success", false); + result.put("message", "解析失败:" + e.getMessage()); + return result; + } + } + + private static String normalizeJson(String content) { + if (content == null) { + return ""; + } + String trimmed = content.trim(); + if (trimmed.startsWith("```")) { + int firstLineBreak = trimmed.indexOf('\n'); + int lastFence = trimmed.lastIndexOf("```"); + if (firstLineBreak >= 0 && lastFence > firstLineBreak) { + trimmed = trimmed.substring(firstLineBreak + 1, lastFence).trim(); + } + } + return trimmed; + } + @Override public Map add(LbAssessmentApply entity) { Map result = new HashMap<>(); @@ -109,7 +237,10 @@ public class LbAssessmentApplyServiceImpl String applicantName, String applicantPhone, String colleagueName, - String teamLeaderName) { + String teamLeaderName, + String assessmentTeacherName, + String moderatorName, + String meetingNumber) { Map result = new HashMap<>(); try { if (current == null || current < 1) { @@ -135,6 +266,15 @@ public class LbAssessmentApplyServiceImpl if (teamLeaderName != null && !teamLeaderName.trim().isEmpty()) { queryWrapper.like(LbAssessmentApply::getTeamLeaderName, teamLeaderName.trim()); } + if (assessmentTeacherName != null && !assessmentTeacherName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getAssessmentTeacherName, assessmentTeacherName.trim()); + } + if (moderatorName != null && !moderatorName.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getModeratorName, moderatorName.trim()); + } + if (meetingNumber != null && !meetingNumber.trim().isEmpty()) { + queryWrapper.like(LbAssessmentApply::getMeetingNumber, meetingNumber.trim()); + } queryWrapper.orderByDesc(LbAssessmentApply::getUpdatedAt) .orderByDesc(LbAssessmentApply::getCreatedAt);