diff --git a/src/main/java/com/xly/agent/DynamicTableNl2SqlAiAgent.java b/src/main/java/com/xly/agent/DynamicTableNl2SqlAiAgent.java index fb04ff3..7c2c5fa 100644 --- a/src/main/java/com/xly/agent/DynamicTableNl2SqlAiAgent.java +++ b/src/main/java/com/xly/agent/DynamicTableNl2SqlAiAgent.java @@ -28,27 +28,34 @@ public interface DynamicTableNl2SqlAiAgent { 3.4 SQL所有的查询条件,如果是字符类型的字段,均需要加不为空判断,用示例格式判断,示例:ifnull(customername,'')<>''; 3.5 SQL所有的查询条件,如果是日期类型的字段,均需要加不为空判断,用示例格式判断,示例:tmakedate is not Null; 3.6 SQL所有的显示字段的别名中,不能出现空格,如: tCreateDate as earliest 订单日期,正确的应是 tCreateDate as earliest订单日期 - 4. 安全约束:禁止生成任何DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等),禁止使用子查询、存储过程、自定义函数、临时表; + 3.7 在AVG聚合函数中不允许使用LAG、LEAD 等窗口函数 + 3.8 AVG(LAG(...))这种嵌套是不允许的 + 3.9 GROUP BY 后面不允许使用窗口函数 + 4. 安全约束: + - 禁止:DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等) + - 禁止:存储过程、自定义函数、临时表 + - 允许:子查询(当需要使用窗口函数LAG/ROW_NUMBER等时) + - 允许:CTE公用表表达式(WITH语句) 5. 精准性: 5.1 严格按用户需求+传入的表结构生成,仅使用指定字段/表,无多余字段、无无效表关联、无冗余过滤条件; 5.2 用户需求中没有明确的日期条件,默认为全部数据,禁止增加任何日期过滤条件 6. 关联规则:多表关联时,必须使用外键/业务唯一键关联,禁止无意义关联。 7. 当前时间:{{sDataNow}} 8. 时间处理规则: - 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) - 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: - - "本年" → 当前年份:{{sDataNow}}的年份 - - "本月" → 当前月份:{{sDataNow}}的年份和月份 - - "本季度" → 当前季度:基于{{sDataNow}}计算 - - "本日/今天" → {{sDataNow}}的具体日期 - - "昨天" → {{sDataNow}}减1天 - - "本周" → 基于{{sDataNow}}计算周一到周日 - - "近7天" → {{sDataNow}}减7天到{{sDataNow}} - 8.3 示例转换: - 当前时间:2024-03-15 - 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 - 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 - 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 + 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) + 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: + - "本年" → 当前年份:{{sDataNow}}的年份 + - "本月" → 当前月份:{{sDataNow}}的年份和月份 + - "本季度" → 当前季度:基于{{sDataNow}}计算 + - "本日/今天" → {{sDataNow}}的具体日期 + - "昨天" → {{sDataNow}}减1天 + - "本周" → 基于{{sDataNow}}计算周一到周日 + - "近7天" → {{sDataNow}}减7天到{{sDataNow}} + 8.3 示例转换: + 当前时间:2024-03-15 + 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 + 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 + 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 """) @UserMessage(""" 【业务场景表结构信息】 @@ -93,27 +100,32 @@ public interface DynamicTableNl2SqlAiAgent { 3.4 SQL所有的查询条件,如果是字符类型的字段,均需要加不为空判断,用示例格式判断,示例:ifnull(customername,'')<>''; 3.5 SQL所有的查询条件,如果是日期类型的字段,均需要加不为空判断,用示例格式判断,示例:tmakedate is not Null; 3.6 SQL所有的显示字段的别名中,不能出现空格,如: tCreateDate as earliest 订单日期,正确的应是 tCreateDate as earliest订单日期 - 4. 安全约束:禁止生成任何DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等),禁止使用子查询、存储过程、自定义函数、临时表; + 3.7 在AVG聚合函数中禁止用LAG窗口函数 + 4. 安全约束: + - 禁止:DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等) + - 禁止:存储过程、自定义函数、临时表 + - 允许:子查询(当需要使用窗口函数LAG/ROW_NUMBER等时) + - 允许:CTE公用表表达式(WITH语句) 5. 精准性: 5.1 严格按用户需求+传入的表结构生成,仅使用指定字段/表,无多余字段、无无效表关联、无冗余过滤条件; 5.2 用户需求中没有明确的日期条件,默认为全部数据,禁止增加任何日期过滤条件 6. 关联规则:多表关联时,必须使用外键/业务唯一键关联,禁止无意义关联。 7. 当前时间:{{sDataNow}} 8. 时间处理规则: - 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) - 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: - - "本年" → 当前年份:{{sDataNow}}的年份 - - "本月" → 当前月份:{{sDataNow}}的年份和月份 - - "本季度" → 当前季度:基于{{sDataNow}}计算 - - "本日/今天" → {{sDataNow}}的具体日期 - - "昨天" → {{sDataNow}}减1天 - - "本周" → 基于{{sDataNow}}计算周一到周日 - - "近7天" → {{sDataNow}}减7天到{{sDataNow}} - 8.3 示例转换: - 当前时间:2024-03-15 - 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 - 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 - 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 + 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) + 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: + - "本年" → 当前年份:{{sDataNow}}的年份 + - "本月" → 当前月份:{{sDataNow}}的年份和月份 + - "本季度" → 当前季度:基于{{sDataNow}}计算 + - "本日/今天" → {{sDataNow}}的具体日期 + - "昨天" → {{sDataNow}}减1天 + - "本周" → 基于{{sDataNow}}计算周一到周日 + - "近7天" → {{sDataNow}}减7天到{{sDataNow}} + 8.3 示例转换: + 当前时间:2024-03-15 + 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 + 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 + 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 """) @UserMessage(""" 【业务场景表结构信息】 @@ -127,6 +139,8 @@ public interface DynamicTableNl2SqlAiAgent { {{errorSql}} 【执行错误信息】 {{errorMessage}} + 【生成SQL语句要求】 + 1.不能生成{{errorSql}}一样的语句 【错误分析指引】 1. 错误类型:请根据错误代码判断 - "Unknown column":字段不存在,检查字段名拼写或改用表中存在的字段 @@ -134,12 +148,12 @@ public interface DynamicTableNl2SqlAiAgent { - "You have an error in your SQL syntax":语法错误,检查关键词、括号、引号 - "Column not found in ON clause":JOIN条件字段不存在 - "Non unique table/alias":表别名重复 - 2. 修复建议: - 如果是字段错误:查看表结构{{tableStruct}},找到正确的字段名替换 - 如果是语法错误:检查SELECT、FROM、WHERE、JOIN等关键词用法 - 如果是类型错误:字符串加单引号,数字不加引号,日期用'yyyy-MM-dd'格式 - 如果是关联错误:确保所有表都通过外键正确JOIN + - 如果是未知错误:确保函数之间不互斥,函数能正常使用,然后重新生成新的语句 请根据以上信息,重新生成正确的MySQL SELECT语句。 只返回SQL语句本身,不要任何解释和包装。 """) diff --git a/src/main/java/com/xly/service/XlyErpService.java b/src/main/java/com/xly/service/XlyErpService.java index 46ae6fb..f3b0500 100644 --- a/src/main/java/com/xly/service/XlyErpService.java +++ b/src/main/java/com/xly/service/XlyErpService.java @@ -259,9 +259,9 @@ public class XlyErpService { log.info("当前时间:"+sDataNow); String rawSql = StrUtil.EMPTY; if(ObjectUtil.isEmpty(errorSql) && ObjectUtil.isEmpty(errorMessage)){ - rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,sDataNow,userInput); + rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,sDataNow,userInput); }else{ - rawSql = aiDynamicTableNl2SqlAiAgent.regenerateSqlWithError(userId, tableNames,tableStruct,sDataNow,userInput,errorSql,errorMessage); + rawSql = aiDynamicTableNl2SqlAiAgent.regenerateSqlWithError(userId, tableNames,tableStruct,sDataNow,userInput,errorSql,errorMessage); } if (rawSql == null || rawSql.trim().isEmpty()) { diff --git a/src/main/java/com/xly/util/EnhancedErrorGuidance.java b/src/main/java/com/xly/util/EnhancedErrorGuidance.java index a3811d8..f443ade 100644 --- a/src/main/java/com/xly/util/EnhancedErrorGuidance.java +++ b/src/main/java/com/xly/util/EnhancedErrorGuidance.java @@ -59,6 +59,10 @@ public class EnhancedErrorGuidance { guidance.append("【生成SQL】\n"); guidance.append("- 错误原因:生成的SQL语句为空\n"); guidance.append("- 修复方法:请重新生成\n"); + } else if(errorMessage.contains("You cannot use the window function 'lag' in this context.")){ + guidance.append("【LAG函数用法不对】\n"); + guidance.append("- 错误原因: 这个错误是因为在MySQL中,不能在聚合函数(如AVG)中直接使用窗口函数(如LAG)。窗口函数是在聚合之前计算的,但不能嵌套在聚合函数内部。\n"); + guidance.append("- 修复方法:在AVG聚合函数中禁止用LAG窗口函数\n"); } else { guidance.append("【未知错误】\n"); guidance.append("- 错误信息:").append(errorMessage).append("\n");