评估申请调研大模型解析申请信息
This commit is contained in:
@@ -4,7 +4,11 @@ import com.rj.entity.LbAssessmentApply;
|
|||||||
import com.rj.service.ILbAssessmentApplyService;
|
import com.rj.service.ILbAssessmentApplyService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -19,6 +23,30 @@ public class LbAssessmentApplyController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ILbAssessmentApplyService lbAssessmentApplyService;
|
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<Map<String, Object>> parseAssessmentApplyFromText(
|
||||||
|
@Parameter(description = "申请评估文本与租户ID", required = true) @Valid @RequestBody ParseAssessmentTextRequest body) {
|
||||||
|
Map<String, Object> 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")
|
@PostMapping("/add")
|
||||||
@Operation(summary = "新增")
|
@Operation(summary = "新增")
|
||||||
public ResponseEntity<Map<String, Object>> add(
|
public ResponseEntity<Map<String, Object>> add(
|
||||||
@@ -64,9 +92,13 @@ public class LbAssessmentApplyController {
|
|||||||
@RequestParam(required = false) String applicantName,
|
@RequestParam(required = false) String applicantName,
|
||||||
@RequestParam(required = false) String applicantPhone,
|
@RequestParam(required = false) String applicantPhone,
|
||||||
@RequestParam(required = false) String colleagueName,
|
@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<String, Object> result = lbAssessmentApplyService.pageQuery(
|
Map<String, Object> 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");
|
Boolean success = (Boolean) result.get("success");
|
||||||
if (success != null && success) {
|
if (success != null && success) {
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ public class LbPurchaseApplyController {
|
|||||||
@NotBlank(message = "订货信息不能为空")
|
@NotBlank(message = "订货信息不能为空")
|
||||||
private String orderInfo;
|
private String orderInfo;
|
||||||
|
|
||||||
@Schema(description = "当前登录人租户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "当前登录人租户ID")
|
||||||
@NotBlank(message = "tenantId不能为空")
|
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,18 @@ public class LbAssessmentApply implements Serializable {
|
|||||||
@Schema(description = "团队长姓名")
|
@Schema(description = "团队长姓名")
|
||||||
private String teamLeaderName;
|
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")
|
@TableField("application_datetime")
|
||||||
@Schema(description = "申请日期时间")
|
@Schema(description = "申请日期时间")
|
||||||
private LocalDateTime applicationDatetime;
|
private LocalDateTime applicationDatetime;
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ public interface ILbAssessmentApplyService extends IService<LbAssessmentApply> {
|
|||||||
String applicantName,
|
String applicantName,
|
||||||
String applicantPhone,
|
String applicantPhone,
|
||||||
String colleagueName,
|
String colleagueName,
|
||||||
String teamLeaderName);
|
String teamLeaderName,
|
||||||
|
String assessmentTeacherName,
|
||||||
|
String moderatorName,
|
||||||
|
String meetingNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据自然语言申请评估信息调用大模型抽取为 {@link LbAssessmentApply}(不落库)。
|
||||||
|
*/
|
||||||
|
Map<String, Object> parseFromAssessmentTextByLlm(String assessmentText, String tenantId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
package com.rj.service.impl;
|
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.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.rj.entity.LbAssessmentApply;
|
import com.rj.entity.LbAssessmentApply;
|
||||||
import com.rj.mapper.LbAssessmentApplyMapper;
|
import com.rj.mapper.LbAssessmentApplyMapper;
|
||||||
import com.rj.service.ILbAssessmentApplyService;
|
import com.rj.service.ILbAssessmentApplyService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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 org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -20,6 +31,123 @@ public class LbAssessmentApplyServiceImpl
|
|||||||
extends ServiceImpl<LbAssessmentApplyMapper, LbAssessmentApply>
|
extends ServiceImpl<LbAssessmentApplyMapper, LbAssessmentApply>
|
||||||
implements ILbAssessmentApplyService {
|
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<String, Object> parseFromAssessmentTextByLlm(String assessmentText, String tenantId) {
|
||||||
|
Map<String, Object> 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
|
@Override
|
||||||
public Map<String, Object> add(LbAssessmentApply entity) {
|
public Map<String, Object> add(LbAssessmentApply entity) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
@@ -109,7 +237,10 @@ public class LbAssessmentApplyServiceImpl
|
|||||||
String applicantName,
|
String applicantName,
|
||||||
String applicantPhone,
|
String applicantPhone,
|
||||||
String colleagueName,
|
String colleagueName,
|
||||||
String teamLeaderName) {
|
String teamLeaderName,
|
||||||
|
String assessmentTeacherName,
|
||||||
|
String moderatorName,
|
||||||
|
String meetingNumber) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
if (current == null || current < 1) {
|
if (current == null || current < 1) {
|
||||||
@@ -135,6 +266,15 @@ public class LbAssessmentApplyServiceImpl
|
|||||||
if (teamLeaderName != null && !teamLeaderName.trim().isEmpty()) {
|
if (teamLeaderName != null && !teamLeaderName.trim().isEmpty()) {
|
||||||
queryWrapper.like(LbAssessmentApply::getTeamLeaderName, teamLeaderName.trim());
|
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)
|
queryWrapper.orderByDesc(LbAssessmentApply::getUpdatedAt)
|
||||||
.orderByDesc(LbAssessmentApply::getCreatedAt);
|
.orderByDesc(LbAssessmentApply::getCreatedAt);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user