From aeb124afcef69c8e43230bc0b31cee0616a5d9c9 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期四, 12 三月 2026 13:53:47 +0800
Subject: [PATCH] #
---
src/main/java/com/zy/ai/service/impl/AiPromptTemplateServiceImpl.java | 262 ++++++++++++++++++++++++++
src/main/resources/sql/20260312_create_sys_ai_prompt_template.sql | 18 +
src/main/java/com/zy/ai/controller/AiPromptTemplateController.java | 97 +++++++++
src/main/java/com/zy/ai/entity/AiPromptTemplate.java | 56 +++++
src/main/java/com/zy/ai/enums/AiPromptScene.java | 35 +++
src/main/java/com/zy/ai/mapper/AiPromptTemplateMapper.java | 11 +
src/main/java/com/zy/ai/utils/AiPromptUtils.java | 19 +
src/main/java/com/zy/ai/service/WcsDiagnosisService.java | 25 +
src/main/java/com/zy/ai/service/AiPromptTemplateService.java | 22 ++
9 files changed, 538 insertions(+), 7 deletions(-)
diff --git a/src/main/java/com/zy/ai/controller/AiPromptTemplateController.java b/src/main/java/com/zy/ai/controller/AiPromptTemplateController.java
new file mode 100644
index 0000000..7e919c5
--- /dev/null
+++ b/src/main/java/com/zy/ai/controller/AiPromptTemplateController.java
@@ -0,0 +1,97 @@
+package com.zy.ai.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.core.annotations.ManagerAuth;
+import com.core.common.R;
+import com.zy.ai.entity.AiPromptTemplate;
+import com.zy.ai.service.AiPromptTemplateService;
+import com.zy.common.web.BaseController;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/ai/prompt/template")
+@RequiredArgsConstructor
+public class AiPromptTemplateController extends BaseController {
+
+ private final AiPromptTemplateService aiPromptTemplateService;
+
+ @GetMapping("/sceneList/auth")
+ @ManagerAuth
+ public R sceneList() {
+ return R.ok(aiPromptTemplateService.listSupportedScenes());
+ }
+
+ @GetMapping("/list/auth")
+ @ManagerAuth
+ public R list(@RequestParam(value = "sceneCode", required = false) String sceneCode,
+ @RequestParam(value = "published", required = false) Short published,
+ @RequestParam(value = "status", required = false) Short status) {
+ QueryWrapper<AiPromptTemplate> wrapper = new QueryWrapper<>();
+ if (sceneCode != null && !sceneCode.trim().isEmpty()) {
+ wrapper.eq("scene_code", sceneCode.trim());
+ }
+ if (published != null) {
+ wrapper.eq("published", published);
+ }
+ if (status != null) {
+ wrapper.eq("status", status);
+ }
+ wrapper.orderByAsc("scene_code").orderByDesc("version").orderByDesc("id");
+ List<AiPromptTemplate> list = aiPromptTemplateService.list(wrapper);
+ return R.ok(list);
+ }
+
+ @GetMapping("/active/auth")
+ @ManagerAuth
+ public R active(@RequestParam("sceneCode") String sceneCode) {
+ try {
+ return R.ok(aiPromptTemplateService.resolvePublished(sceneCode));
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("/save/auth")
+ @ManagerAuth
+ public R save(@RequestBody AiPromptTemplate template) {
+ try {
+ return R.ok(aiPromptTemplateService.savePrompt(template, getUserId()));
+ } catch (IllegalArgumentException e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("/publish/auth")
+ @ManagerAuth
+ public R publish(@RequestParam("id") Long id) {
+ try {
+ return R.ok(aiPromptTemplateService.publishPrompt(id, getUserId()));
+ } catch (IllegalArgumentException e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("/delete/auth")
+ @ManagerAuth
+ public R delete(@RequestParam("id") Long id) {
+ try {
+ return R.ok(aiPromptTemplateService.deletePrompt(id));
+ } catch (IllegalArgumentException e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("/initDefaults/auth")
+ @ManagerAuth
+ public R initDefaults() {
+ return R.ok(aiPromptTemplateService.initDefaultsIfMissing());
+ }
+}
diff --git a/src/main/java/com/zy/ai/entity/AiPromptTemplate.java b/src/main/java/com/zy/ai/entity/AiPromptTemplate.java
new file mode 100644
index 0000000..a915108
--- /dev/null
+++ b/src/main/java/com/zy/ai/entity/AiPromptTemplate.java
@@ -0,0 +1,56 @@
+package com.zy.ai.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("sys_ai_prompt_template")
+public class AiPromptTemplate implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ private String name;
+
+ @TableField("scene_code")
+ private String sceneCode;
+
+ private Integer version;
+
+ private String content;
+
+ /**
+ * 1 鍚敤 0 绂佺敤
+ */
+ private Short status;
+
+ /**
+ * 1 宸插彂甯� 0 鏈彂甯�
+ */
+ private Short published;
+
+ @TableField("created_by")
+ private Long createdBy;
+
+ @TableField("published_by")
+ private Long publishedBy;
+
+ @TableField("published_time")
+ private Date publishedTime;
+
+ @TableField("create_time")
+ private Date createTime;
+
+ @TableField("update_time")
+ private Date updateTime;
+
+ private String memo;
+}
diff --git a/src/main/java/com/zy/ai/enums/AiPromptScene.java b/src/main/java/com/zy/ai/enums/AiPromptScene.java
new file mode 100644
index 0000000..42b65ee
--- /dev/null
+++ b/src/main/java/com/zy/ai/enums/AiPromptScene.java
@@ -0,0 +1,35 @@
+package com.zy.ai.enums;
+
+public enum AiPromptScene {
+
+ DIAGNOSE_STREAM("wcs_diagnose_stream", "WCS宸℃璇婃柇"),
+ SENSOR_CHAT("wcs_sensor_chat", "WCS涓撳闂瓟");
+
+ private final String code;
+ private final String label;
+
+ AiPromptScene(String code, String label) {
+ this.code = code;
+ this.label = label;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public static AiPromptScene ofCode(String code) {
+ if (code == null) {
+ return null;
+ }
+ for (AiPromptScene item : values()) {
+ if (item.code.equals(code)) {
+ return item;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/zy/ai/mapper/AiPromptTemplateMapper.java b/src/main/java/com/zy/ai/mapper/AiPromptTemplateMapper.java
new file mode 100644
index 0000000..c4d251a
--- /dev/null
+++ b/src/main/java/com/zy/ai/mapper/AiPromptTemplateMapper.java
@@ -0,0 +1,11 @@
+package com.zy.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zy.ai.entity.AiPromptTemplate;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface AiPromptTemplateMapper extends BaseMapper<AiPromptTemplate> {
+}
diff --git a/src/main/java/com/zy/ai/service/AiPromptTemplateService.java b/src/main/java/com/zy/ai/service/AiPromptTemplateService.java
new file mode 100644
index 0000000..e269966
--- /dev/null
+++ b/src/main/java/com/zy/ai/service/AiPromptTemplateService.java
@@ -0,0 +1,22 @@
+package com.zy.ai.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zy.ai.entity.AiPromptTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+public interface AiPromptTemplateService extends IService<AiPromptTemplate> {
+
+ AiPromptTemplate resolvePublished(String sceneCode);
+
+ AiPromptTemplate savePrompt(AiPromptTemplate template, Long operatorUserId);
+
+ AiPromptTemplate publishPrompt(Long id, Long operatorUserId);
+
+ boolean deletePrompt(Long id);
+
+ int initDefaultsIfMissing();
+
+ List<Map<String, Object>> listSupportedScenes();
+}
diff --git a/src/main/java/com/zy/ai/service/WcsDiagnosisService.java b/src/main/java/com/zy/ai/service/WcsDiagnosisService.java
index 7c10893..757e877 100644
--- a/src/main/java/com/zy/ai/service/WcsDiagnosisService.java
+++ b/src/main/java/com/zy/ai/service/WcsDiagnosisService.java
@@ -2,11 +2,13 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
+import com.zy.ai.entity.AiPromptTemplate;
import com.zy.ai.entity.ChatCompletionRequest;
import com.zy.ai.entity.ChatCompletionResponse;
import com.zy.ai.entity.WcsDiagnosisRequest;
+import com.zy.ai.enums.AiPromptScene;
import com.zy.ai.mcp.service.SpringAiMcpToolManager;
-import com.zy.ai.utils.AiPromptUtils;
+import com.zy.ai.service.AiPromptTemplateService;
import com.zy.ai.utils.AiUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
@@ -32,24 +34,25 @@
@Autowired
private RedisUtil redisUtil;
@Autowired
- private AiPromptUtils aiPromptUtils;
- @Autowired
private AiUtils aiUtils;
@Autowired
private SpringAiMcpToolManager mcpToolManager;
+ @Autowired
+ private AiPromptTemplateService aiPromptTemplateService;
public void diagnoseStream(WcsDiagnosisRequest request, SseEmitter emitter) {
List<ChatCompletionRequest.Message> messages = new ArrayList<>();
+ AiPromptTemplate promptTemplate = aiPromptTemplateService.resolvePublished(AiPromptScene.DIAGNOSE_STREAM.getCode());
ChatCompletionRequest.Message mcpSystem = new ChatCompletionRequest.Message();
mcpSystem.setRole("system");
- mcpSystem.setContent(aiPromptUtils.getAiDiagnosePromptMcp());
+ mcpSystem.setContent(promptTemplate.getContent());
ChatCompletionRequest.Message mcpUser = new ChatCompletionRequest.Message();
mcpUser.setRole("user");
mcpUser.setContent(aiUtils.buildDiagnosisUserContentMcp(request));
- runMcpStreamingDiagnosis(messages, mcpSystem, mcpUser, 0.3, 2048, emitter, null);
+ runMcpStreamingDiagnosis(messages, mcpSystem, mcpUser, promptTemplate, 0.3, 2048, emitter, null);
}
public void askStream(String prompt,
@@ -81,16 +84,17 @@
}
final String finalChatId = chatId;
+ AiPromptTemplate promptTemplate = aiPromptTemplateService.resolvePublished(AiPromptScene.SENSOR_CHAT.getCode());
ChatCompletionRequest.Message mcpSystem = new ChatCompletionRequest.Message();
mcpSystem.setRole("system");
- mcpSystem.setContent(aiPromptUtils.getWcsSensorPromptMcp());
+ mcpSystem.setContent(promptTemplate.getContent());
ChatCompletionRequest.Message mcpUser = new ChatCompletionRequest.Message();
mcpUser.setRole("user");
mcpUser.setContent("銆愮敤鎴锋彁闂�慭n" + (prompt == null ? "" : prompt));
- runMcpStreamingDiagnosis(messages, mcpSystem, mcpUser, 0.3, 2048, emitter, finalChatId);
+ runMcpStreamingDiagnosis(messages, mcpSystem, mcpUser, promptTemplate, 0.3, 2048, emitter, finalChatId);
}
public List<Map<String, Object>> listChats() {
@@ -161,6 +165,7 @@
private void runMcpStreamingDiagnosis(List<ChatCompletionRequest.Message> baseMessages,
ChatCompletionRequest.Message systemPrompt,
ChatCompletionRequest.Message userQuestion,
+ AiPromptTemplate promptTemplate,
Double temperature,
Integer maxTokens,
SseEmitter emitter,
@@ -272,6 +277,12 @@
Map<String, Object> meta = new java.util.HashMap<>();
meta.put("chatId", chatId);
meta.put("title", buildTitleFromPrompt(userQuestion.getContent()));
+ if (promptTemplate != null) {
+ meta.put("promptTemplateId", promptTemplate.getId());
+ meta.put("promptSceneCode", promptTemplate.getSceneCode());
+ meta.put("promptVersion", promptTemplate.getVersion());
+ meta.put("promptName", promptTemplate.getName());
+ }
meta.put("createdAt", createdAt);
meta.put("updatedAt", System.currentTimeMillis());
redisUtil.hmset(metaKey, meta, CHAT_TTL_SECONDS);
diff --git a/src/main/java/com/zy/ai/service/impl/AiPromptTemplateServiceImpl.java b/src/main/java/com/zy/ai/service/impl/AiPromptTemplateServiceImpl.java
new file mode 100644
index 0000000..fedfd7f
--- /dev/null
+++ b/src/main/java/com/zy/ai/service/impl/AiPromptTemplateServiceImpl.java
@@ -0,0 +1,262 @@
+package com.zy.ai.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zy.ai.entity.AiPromptTemplate;
+import com.zy.ai.enums.AiPromptScene;
+import com.zy.ai.mapper.AiPromptTemplateMapper;
+import com.zy.ai.service.AiPromptTemplateService;
+import com.zy.ai.utils.AiPromptUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service("aiPromptTemplateService")
+@RequiredArgsConstructor
+public class AiPromptTemplateServiceImpl extends ServiceImpl<AiPromptTemplateMapper, AiPromptTemplate> implements AiPromptTemplateService {
+
+ private final AiPromptUtils aiPromptUtils;
+
+ @Override
+ public AiPromptTemplate resolvePublished(String sceneCode) {
+ AiPromptScene scene = requireScene(sceneCode);
+ AiPromptTemplate prompt = findPublished(scene.getCode());
+ if (prompt == null) {
+ synchronized (("ai_prompt_scene_init_" + scene.getCode()).intern()) {
+ prompt = findPublished(scene.getCode());
+ if (prompt == null) {
+ prompt = ensurePublishedScene(scene);
+ }
+ }
+ }
+
+ if (prompt == null) {
+ throw new IllegalStateException("鏈壘鍒板凡鍙戝竷鐨� Prompt锛宻ceneCode=" + scene.getCode());
+ }
+ return prompt;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public AiPromptTemplate savePrompt(AiPromptTemplate template, Long operatorUserId) {
+ if (template == null) {
+ throw new IllegalArgumentException("Prompt 涓嶈兘涓虹┖");
+ }
+ AiPromptScene scene = requireScene(template.getSceneCode());
+ String content = template.getContent();
+ if (content == null || content.trim().isEmpty()) {
+ throw new IllegalArgumentException("Prompt 鍐呭涓嶈兘涓虹┖");
+ }
+
+ if (template.getId() == null) {
+ AiPromptTemplate entity = new AiPromptTemplate();
+ int version = nextVersion(scene.getCode());
+ entity.setName(defaultName(scene, version, template.getName()));
+ entity.setSceneCode(scene.getCode());
+ entity.setVersion(version);
+ entity.setContent(content);
+ entity.setStatus(normalizeStatus(template.getStatus()));
+ entity.setPublished((short) 0);
+ entity.setCreatedBy(operatorUserId);
+ entity.setMemo(trim(template.getMemo()));
+ this.save(entity);
+ return entity;
+ }
+
+ AiPromptTemplate db = this.getById(template.getId());
+ if (db == null) {
+ throw new IllegalArgumentException("Prompt 涓嶅瓨鍦�");
+ }
+ if (!scene.getCode().equals(db.getSceneCode())) {
+ throw new IllegalArgumentException("涓嶅厑璁镐慨鏀� Prompt 鎵�灞炲満鏅�");
+ }
+ if (Short.valueOf((short) 1).equals(db.getPublished())) {
+ throw new IllegalArgumentException("宸插彂甯� Prompt 涓嶅厑璁哥洿鎺ヤ慨鏀癸紝璇锋柊寤虹増鏈悗鍐嶅彂甯�");
+ }
+
+ db.setName(defaultName(scene, db.getVersion() == null ? 1 : db.getVersion(), template.getName()));
+ db.setContent(content);
+ db.setStatus(normalizeStatus(template.getStatus()));
+ db.setMemo(trim(template.getMemo()));
+ this.updateById(db);
+ return db;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public AiPromptTemplate publishPrompt(Long id, Long operatorUserId) {
+ if (id == null) {
+ throw new IllegalArgumentException("id 涓嶈兘涓虹┖");
+ }
+ AiPromptTemplate db = this.getById(id);
+ if (db == null) {
+ throw new IllegalArgumentException("Prompt 涓嶅瓨鍦�");
+ }
+ if (db.getContent() == null || db.getContent().trim().isEmpty()) {
+ throw new IllegalArgumentException("Prompt 鍐呭涓嶈兘涓虹┖");
+ }
+
+ UpdateWrapper<AiPromptTemplate> clearWrapper = new UpdateWrapper<>();
+ clearWrapper.eq("scene_code", db.getSceneCode()).set("published", 0);
+ this.update(clearWrapper);
+
+ db.setPublished((short) 1);
+ db.setStatus((short) 1);
+ db.setPublishedBy(operatorUserId);
+ db.setPublishedTime(new Date());
+ if (db.getVersion() == null || db.getVersion() <= 0) {
+ db.setVersion(nextVersion(db.getSceneCode()));
+ }
+ if (db.getName() == null || db.getName().trim().isEmpty()) {
+ AiPromptScene scene = requireScene(db.getSceneCode());
+ db.setName(defaultName(scene, db.getVersion(), null));
+ }
+ this.updateById(db);
+ return db;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean deletePrompt(Long id) {
+ if (id == null) {
+ return false;
+ }
+ AiPromptTemplate db = this.getById(id);
+ if (db == null) {
+ return false;
+ }
+ if (Short.valueOf((short) 1).equals(db.getPublished())) {
+ throw new IllegalArgumentException("宸插彂甯� Prompt 涓嶅厑璁稿垹闄わ紝璇峰厛鍙戝竷鍏朵粬鐗堟湰");
+ }
+ return this.removeById(id);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int initDefaultsIfMissing() {
+ int changed = 0;
+ for (AiPromptScene scene : AiPromptScene.values()) {
+ AiPromptTemplate prompt = findPublished(scene.getCode());
+ if (prompt == null) {
+ ensurePublishedScene(scene);
+ changed++;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public List<Map<String, Object>> listSupportedScenes() {
+ List<Map<String, Object>> result = new ArrayList<>();
+ for (AiPromptScene scene : AiPromptScene.values()) {
+ HashMap<String, Object> item = new HashMap<>();
+ item.put("code", scene.getCode());
+ item.put("label", scene.getLabel());
+ result.add(item);
+ }
+ return result;
+ }
+
+ private AiPromptTemplate ensurePublishedScene(AiPromptScene scene) {
+ AiPromptTemplate latest = findLatest(scene.getCode());
+ if (latest == null) {
+ AiPromptTemplate seed = new AiPromptTemplate();
+ seed.setName(defaultName(scene, 1, null));
+ seed.setSceneCode(scene.getCode());
+ seed.setVersion(1);
+ seed.setContent(aiPromptUtils.getDefaultPrompt(scene.getCode()));
+ seed.setStatus((short) 1);
+ seed.setPublished((short) 1);
+ seed.setPublishedTime(new Date());
+ seed.setMemo("绯荤粺鍒濆鍖栭粯璁� Prompt");
+ this.save(seed);
+ log.info("Initialized default AI prompt, sceneCode={}, version={}", scene.getCode(), seed.getVersion());
+ return seed;
+ }
+
+ UpdateWrapper<AiPromptTemplate> clearWrapper = new UpdateWrapper<>();
+ clearWrapper.eq("scene_code", scene.getCode()).set("published", 0);
+ this.update(clearWrapper);
+
+ latest.setStatus((short) 1);
+ latest.setPublished((short) 1);
+ if (latest.getPublishedTime() == null) {
+ latest.setPublishedTime(new Date());
+ }
+ this.updateById(latest);
+ return latest;
+ }
+
+ private AiPromptTemplate findPublished(String sceneCode) {
+ QueryWrapper<AiPromptTemplate> wrapper = new QueryWrapper<>();
+ wrapper.eq("scene_code", sceneCode)
+ .eq("status", 1)
+ .eq("published", 1)
+ .orderByDesc("version")
+ .orderByDesc("id")
+ .last("limit 1");
+ return this.getOne(wrapper, false);
+ }
+
+ private AiPromptTemplate findLatest(String sceneCode) {
+ QueryWrapper<AiPromptTemplate> wrapper = new QueryWrapper<>();
+ wrapper.eq("scene_code", sceneCode)
+ .orderByDesc("version")
+ .orderByDesc("id")
+ .last("limit 1");
+ return this.getOne(wrapper, false);
+ }
+
+ private int nextVersion(String sceneCode) {
+ QueryWrapper<AiPromptTemplate> wrapper = new QueryWrapper<>();
+ wrapper.eq("scene_code", sceneCode)
+ .select("max(version) as version");
+ Map<String, Object> row = this.getMap(wrapper);
+ if (row == null || row.get("version") == null) {
+ return 1;
+ }
+ Object value = row.get("version");
+ if (value instanceof Number) {
+ return ((Number) value).intValue() + 1;
+ }
+ return Integer.parseInt(String.valueOf(value)) + 1;
+ }
+
+ private Short normalizeStatus(Short status) {
+ return status != null && status == 0 ? (short) 0 : (short) 1;
+ }
+
+ private String defaultName(AiPromptScene scene, Integer version, String name) {
+ String value = trim(name);
+ if (value != null && !value.isEmpty()) {
+ return value;
+ }
+ return scene.getLabel() + " v" + version;
+ }
+
+ private AiPromptScene requireScene(String sceneCode) {
+ String code = trim(sceneCode);
+ AiPromptScene scene = AiPromptScene.ofCode(code);
+ if (scene == null) {
+ throw new IllegalArgumentException("涓嶆敮鎸佺殑 Prompt 鍦烘櫙: " + sceneCode);
+ }
+ return scene;
+ }
+
+ private String trim(String value) {
+ if (value == null) {
+ return null;
+ }
+ String trimmed = value.trim();
+ return trimmed.isEmpty() ? null : trimmed;
+ }
+}
diff --git a/src/main/java/com/zy/ai/utils/AiPromptUtils.java b/src/main/java/com/zy/ai/utils/AiPromptUtils.java
index 71b4a3c..3fed8c0 100644
--- a/src/main/java/com/zy/ai/utils/AiPromptUtils.java
+++ b/src/main/java/com/zy/ai/utils/AiPromptUtils.java
@@ -1,10 +1,29 @@
package com.zy.ai.utils;
+import com.zy.ai.enums.AiPromptScene;
import org.springframework.stereotype.Component;
@Component
public class AiPromptUtils {
+ public String getDefaultPrompt(String sceneCode) {
+ AiPromptScene scene = AiPromptScene.ofCode(sceneCode);
+ if (scene == null) {
+ throw new IllegalArgumentException("涓嶆敮鎸佺殑 Prompt 鍦烘櫙: " + sceneCode);
+ }
+ return getDefaultPrompt(scene);
+ }
+
+ public String getDefaultPrompt(AiPromptScene scene) {
+ if (scene == AiPromptScene.DIAGNOSE_STREAM) {
+ return getAiDiagnosePromptMcp();
+ }
+ if (scene == AiPromptScene.SENSOR_CHAT) {
+ return getWcsSensorPromptMcp();
+ }
+ throw new IllegalArgumentException("涓嶆敮鎸佺殑 Prompt 鍦烘櫙: " + scene.getCode());
+ }
+
//AI璇婃柇绯荤粺Prompt
public String getAiDiagnosePromptMcp() {
String prompt = "浣犳槸涓�鍚嶈祫娣� WCS锛堜粨鍌ㄦ帶鍒剁郴缁燂級涓庤嚜鍔ㄥ寲绔嬪簱涓撳锛岀啛鎮夛細鍫嗗灈鏈恒�佽緭閫佺嚎銆佹彁鍗囨満銆佺┛姊溅绛夎澶囩殑浠诲姟鍒嗛厤鍜岃繍琛岄�昏緫锛屼篃鐔熸倝甯歌鐨勭郴缁熷崱姝汇�佷换鍔′笉鎵ц銆佽澶囩┖闂蹭絾鏃犱换鍔$瓑闂妯″紡銆俓n\n" +
diff --git a/src/main/resources/sql/20260312_create_sys_ai_prompt_template.sql b/src/main/resources/sql/20260312_create_sys_ai_prompt_template.sql
new file mode 100644
index 0000000..a64c476
--- /dev/null
+++ b/src/main/resources/sql/20260312_create_sys_ai_prompt_template.sql
@@ -0,0 +1,18 @@
+CREATE TABLE IF NOT EXISTS `sys_ai_prompt_template` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '涓婚敭',
+ `name` VARCHAR(128) NOT NULL COMMENT 'Prompt 鍚嶇О',
+ `scene_code` VARCHAR(64) NOT NULL COMMENT '鍦烘櫙缂栫爜',
+ `version` INT NOT NULL COMMENT '鐗堟湰鍙�',
+ `content` LONGTEXT NOT NULL COMMENT 'Prompt 鍐呭',
+ `status` TINYINT NOT NULL DEFAULT 1 COMMENT '鐘舵��:1鍚敤0绂佺敤',
+ `published` TINYINT NOT NULL DEFAULT 0 COMMENT '鏄惁宸插彂甯�:1鏄�0鍚�',
+ `created_by` BIGINT DEFAULT NULL COMMENT '鍒涘缓浜�',
+ `published_by` BIGINT DEFAULT NULL COMMENT '鍙戝竷浜�',
+ `published_time` DATETIME DEFAULT NULL COMMENT '鍙戝竷鏃堕棿',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+ `memo` VARCHAR(255) DEFAULT NULL COMMENT '澶囨敞',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_sys_ai_prompt_scene_version` (`scene_code`, `version`),
+ KEY `idx_sys_ai_prompt_scene_publish` (`scene_code`, `published`, `status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI Prompt 妯℃澘鐗堟湰琛�';
--
Gitblit v1.9.1