diff --git a/src/main/java/cn/rosercode/ledgerly/prompt/PromptTemplateService.java b/src/main/java/cn/rosercode/ledgerly/prompt/PromptTemplateService.java
index d813c7e..0f1399a 100644
--- a/src/main/java/cn/rosercode/ledgerly/prompt/PromptTemplateService.java
+++ b/src/main/java/cn/rosercode/ledgerly/prompt/PromptTemplateService.java
@@ -1,7 +1,7 @@
package cn.rosercode.ledgerly.prompt;
-import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -15,8 +15,9 @@ import cn.rosercode.ledgerly.common.BusinessException;
* AI 提示词模板渲染组件。
*
*
统一从 {@code classpath:/prompts/} 加载 Thymeleaf 文本模板(TEXT 模式)。
- * 每个模板对应一个语义化方法,调用方只需传入该模板所需数据、无需关心模板名,
- * 使提示词与 Java 代码解耦、便于集中维护。模板解析规则见
+ * 每个 AI 功能的系统提示词与用户提示词位于同一模板文件的不同片段
+ * ({@code system} / {@code user}),每个片段对应一个语义化方法,调用方只需传入该片段
+ * 所需数据、无需关心模板名,使提示词与 Java 代码解耦、便于集中维护。模板解析规则见
* {@code application.yml} 的 {@code spring.thymeleaf} 配置。
*
* @date 2026-09-21 10:58:05
@@ -37,7 +38,7 @@ public class PromptTemplateService {
}
/**
- * 渲染自然语言记账的系统提示词(模板 {@code ai-record-system})。
+ * 渲染自然语言记账的系统提示词(模板 {@code ai-record} 的 {@code system} 片段)。
*
* @param typeDesc 收支类型说明
* @param channelDesc 交易渠道说明
@@ -56,11 +57,11 @@ public class PromptTemplateService {
variables.put("tagNames", tagNames);
variables.put("now", now);
variables.put("exampleTime", exampleTime);
- return render("ai-record-system", variables);
+ return render("ai-record", "system", variables);
}
/**
- * 渲染图片记账的系统提示词(模板 {@code ai-record-image-system})。
+ * 渲染图片记账的系统提示词(模板 {@code ai-record-image} 的 {@code system} 片段)。
*
* @param typeDesc 收支类型说明
* @param channelDesc 交易渠道说明
@@ -79,11 +80,11 @@ public class PromptTemplateService {
variables.put("tagNames", tagNames);
variables.put("now", now);
variables.put("exampleTime", exampleTime);
- return render("ai-record-image-system", variables);
+ return render("ai-record-image", "system", variables);
}
/**
- * 渲染自然语言查询的系统提示词(模板 {@code ai-query-system})。
+ * 渲染自然语言查询的系统提示词(模板 {@code ai-query} 的 {@code system} 片段)。
*
* @param typeDesc 收支类型说明
* @param channelDesc 交易渠道说明
@@ -100,11 +101,11 @@ public class PromptTemplateService {
variables.put("categoryNames", categoryNames);
variables.put("tagNames", tagNames);
variables.put("today", today);
- return render("ai-query-system", variables);
+ return render("ai-query", "system", variables);
}
/**
- * 渲染自然语言统计查询的系统提示词(模板 {@code ai-statistics-system})。
+ * 渲染自然语言统计查询的系统提示词(模板 {@code ai-statistics} 的 {@code system} 片段)。
*
* @param typeDesc 收支类型说明
* @param channelDesc 交易渠道说明
@@ -121,11 +122,11 @@ public class PromptTemplateService {
variables.put("categoryNames", categoryNames);
variables.put("tagNames", tagNames);
variables.put("today", today);
- return render("ai-statistics-system", variables);
+ return render("ai-statistics", "system", variables);
}
/**
- * 渲染自然语言转 SQL 的系统提示词(模板 {@code ai-sql-system})。
+ * 渲染自然语言转 SQL 的系统提示词(模板 {@code ai-sql} 的 {@code system} 片段)。
*
* @param dialect 当前数据库方言(MySQL / SQLite)
* @param today 当天日期(yyyy-MM-dd)
@@ -137,119 +138,279 @@ public class PromptTemplateService {
variables.put("dialect", dialect);
variables.put("today", today);
variables.put("schema", schema);
- return render("ai-sql-system", variables);
+ return render("ai-sql", "system", variables);
}
/**
- * 渲染生成分类的系统提示词(模板 {@code ai-category-system})。
+ * 渲染生成分类的系统提示词(模板 {@code ai-category} 的 {@code system} 片段)。
*
* @param typeDesc 收支类型说明
* @return 系统提示词
*/
public String categorySystemPrompt(String typeDesc) {
- return render("ai-category-system", Map.of("typeDesc", typeDesc));
+ return render("ai-category", "system", Map.of("typeDesc", typeDesc));
}
/**
- * 渲染生成标签的系统提示词(模板 {@code ai-tag-system})。
+ * 渲染生成标签的系统提示词(模板 {@code ai-tag} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String tagSystemPrompt() {
- return render("ai-tag-system", null);
+ return render("ai-tag", "system", null);
}
/**
- * 渲染生成交易渠道的系统提示词(模板 {@code ai-channel-system})。
+ * 渲染生成交易渠道的系统提示词(模板 {@code ai-channel} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String channelSystemPrompt() {
- return render("ai-channel-system", null);
+ return render("ai-channel", "system", null);
}
/**
- * 渲染生成账单关系名称与备注的系统提示词(模板 {@code ai-relation-system})。
+ * 渲染生成账单关系名称与备注的系统提示词(模板 {@code ai-relation} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String relationSystemPrompt() {
- return render("ai-relation-system", null);
+ return render("ai-relation", "system", null);
}
/**
- * 渲染 Emoji 图标建议的系统提示词(模板 {@code ai-decoration-emoji-system})。
+ * 渲染 Emoji 图标建议的系统提示词(模板 {@code ai-decoration-emoji} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String decorationEmojiSystemPrompt() {
- return render("ai-decoration-emoji-system", null);
+ return render("ai-decoration-emoji", "system", null);
}
/**
- * 渲染配色建议的系统提示词(模板 {@code ai-decoration-color-system})。
+ * 渲染配色建议的系统提示词(模板 {@code ai-decoration-color} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String decorationColorSystemPrompt() {
- return render("ai-decoration-color-system", null);
+ return render("ai-decoration-color", "system", null);
}
/**
- * 渲染严格模式分类标签建议的系统提示词(模板 {@code ai-suggestion-strict-system})。
+ * 渲染严格模式分类标签建议的系统提示词(模板 {@code ai-suggestion} 的 {@code strictSystem} 片段)。
*
* @return 系统提示词
*/
public String suggestionStrictSystemPrompt() {
- return render("ai-suggestion-strict-system", null);
+ return render("ai-suggestion", "strictSystem", null);
}
/**
- * 渲染增强模式分类标签建议的系统提示词(模板 {@code ai-suggestion-new-system})。
+ * 渲染增强模式分类标签建议的系统提示词(模板 {@code ai-suggestion} 的 {@code newSystem} 片段)。
*
* @param scope 建议范围(CATEGORY / TAG / BOTH),决定追加的限定说明
* @return 系统提示词
*/
public String suggestionNewSystemPrompt(String scope) {
- return render("ai-suggestion-new-system", Map.of("scope", scope));
+ return render("ai-suggestion", "newSystem", Map.of("scope", scope));
}
/**
- * 渲染规则生成的系统提示词(模板 {@code ai-rule-system})。
+ * 渲染规则生成的系统提示词(模板 {@code ai-rule} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String ruleSystemPrompt() {
- return render("ai-rule-system", null);
+ return render("ai-rule", "system", null);
}
/**
- * 渲染连接测试的系统提示词(模板 {@code ai-config-test-system})。
+ * 渲染连接测试的系统提示词(模板 {@code ai-config-test} 的 {@code system} 片段)。
*
* @return 系统提示词
*/
public String configTestSystemPrompt() {
- return render("ai-config-test-system", null);
+ return render("ai-config-test", "system", null);
}
/**
- * 渲染连接测试的用户提示词(模板 {@code ai-config-test-user})。
+ * 渲染连接测试的用户提示词(模板 {@code ai-config-test} 的 {@code user} 片段)。
*
* @return 用户提示词
*/
public String configTestUserPrompt() {
- return render("ai-config-test-user", null);
+ return render("ai-config-test", "user", null);
}
/**
- * 渲染提示词模板,模板名与变量由各专用方法提供。
+ * 渲染自然语言记账的用户提示词(模板 {@code ai-record} 的 {@code user} 片段)。
+ *
+ * @param text 用户输入的记账内容
+ * @return 用户提示词
+ */
+ public String recordUserPrompt(String text) {
+ return render("ai-record", "user", Map.of("text", text));
+ }
+
+ /**
+ * 渲染图片记账的用户提示词(模板 {@code ai-record-image} 的 {@code user} 片段)。
+ *
+ * @param hint 用户附加说明,可为 null(模板回退默认提示语)
+ * @return 用户提示词
+ */
+ public String recordImageUserPrompt(String hint) {
+ Map variables = new LinkedHashMap<>();
+ variables.put("hint", hint);
+ return render("ai-record-image", "user", variables);
+ }
+
+ /**
+ * 渲染自然语言查询的用户提示词(模板 {@code ai-query} 的 {@code user} 片段)。
+ *
+ * @param query 用户输入的查询内容
+ * @return 用户提示词
+ */
+ public String queryUserPrompt(String query) {
+ return render("ai-query", "user", Map.of("query", query));
+ }
+
+ /**
+ * 渲染自然语言统计查询的用户提示词(模板 {@code ai-statistics} 的 {@code user} 片段)。
+ *
+ * @param query 用户输入的统计查询内容
+ * @return 用户提示词
+ */
+ public String statisticsUserPrompt(String query) {
+ return render("ai-statistics", "user", Map.of("query", query));
+ }
+
+ /**
+ * 渲染自然语言转 SQL 的用户提示词(模板 {@code ai-sql} 的 {@code user} 片段)。
+ *
+ * @param query 用户输入的查询内容
+ * @return 用户提示词
+ */
+ public String textToSqlUserPrompt(String query) {
+ return render("ai-sql", "user", Map.of("query", query));
+ }
+
+ /**
+ * 渲染生成分类的用户提示词(模板 {@code ai-category} 的 {@code user} 片段)。
+ *
+ * @param text 用户输入的分类描述
+ * @return 用户提示词
+ */
+ public String categoryUserPrompt(String text) {
+ return render("ai-category", "user", Map.of("text", text));
+ }
+
+ /**
+ * 渲染生成标签的用户提示词(模板 {@code ai-tag} 的 {@code user} 片段)。
+ *
+ * @param text 用户输入的标签描述
+ * @return 用户提示词
+ */
+ public String tagUserPrompt(String text) {
+ return render("ai-tag", "user", Map.of("text", text));
+ }
+
+ /**
+ * 渲染生成交易渠道的用户提示词(模板 {@code ai-channel} 的 {@code user} 片段)。
+ *
+ * @param text 用户输入的渠道描述
+ * @return 用户提示词
+ */
+ public String channelUserPrompt(String text) {
+ return render("ai-channel", "user", Map.of("text", text));
+ }
+
+ /**
+ * 渲染 Emoji 建议的用户提示词(模板 {@code ai-decoration-emoji} 的 {@code user} 片段)。
+ *
+ * @param name 分类名称
+ * @param typeLabel 收支类型中文说明
+ * @return 用户提示词
+ */
+ public String decorationEmojiUserPrompt(String name, String typeLabel) {
+ Map variables = new LinkedHashMap<>();
+ variables.put("name", name);
+ variables.put("typeLabel", typeLabel);
+ return render("ai-decoration-emoji", "user", variables);
+ }
+
+ /**
+ * 渲染配色建议的用户提示词(模板 {@code ai-decoration-color} 的 {@code user} 片段)。
+ *
+ * @param name 标签名称
+ * @return 用户提示词
+ */
+ public String decorationColorUserPrompt(String name) {
+ return render("ai-decoration-color", "user", Map.of("name", name));
+ }
+
+ /**
+ * 渲染账单关系的用户提示词(模板 {@code ai-relation} 的 {@code user} 片段)。
+ *
+ * @param typeLabel 关系类型中文说明
+ * @param members 成员账单列表(键:type、channel、categoryName、remark)
+ * @return 用户提示词
+ */
+ public String relationUserPrompt(String typeLabel, List