Commit 6f97d3bd65770adab7dd3f9224d605f8670fc8c1
1 parent
06ca6a05
AI 对于时间的处理
Showing
3 changed files
with
51 additions
and
33 deletions
src/main/java/com/xly/agent/DynamicTableNl2SqlAiAgent.java
| ... | ... | @@ -28,27 +28,34 @@ public interface DynamicTableNl2SqlAiAgent { |
| 28 | 28 | 3.4 SQL所有的查询条件,如果是字符类型的字段,均需要加不为空判断,用示例格式判断,示例:ifnull(customername,'')<>''; |
| 29 | 29 | 3.5 SQL所有的查询条件,如果是日期类型的字段,均需要加不为空判断,用示例格式判断,示例:tmakedate is not Null; |
| 30 | 30 | 3.6 SQL所有的显示字段的别名中,不能出现空格,如: tCreateDate as earliest 订单日期,正确的应是 tCreateDate as earliest订单日期 |
| 31 | - 4. 安全约束:禁止生成任何DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等),禁止使用子查询、存储过程、自定义函数、临时表; | |
| 31 | + 3.7 在AVG聚合函数中不允许使用LAG、LEAD 等窗口函数 | |
| 32 | + 3.8 AVG(LAG(...))这种嵌套是不允许的 | |
| 33 | + 3.9 GROUP BY 后面不允许使用窗口函数 | |
| 34 | + 4. 安全约束: | |
| 35 | + - 禁止:DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等) | |
| 36 | + - 禁止:存储过程、自定义函数、临时表 | |
| 37 | + - 允许:子查询(当需要使用窗口函数LAG/ROW_NUMBER等时) | |
| 38 | + - 允许:CTE公用表表达式(WITH语句) | |
| 32 | 39 | 5. 精准性: |
| 33 | 40 | 5.1 严格按用户需求+传入的表结构生成,仅使用指定字段/表,无多余字段、无无效表关联、无冗余过滤条件; |
| 34 | 41 | 5.2 用户需求中没有明确的日期条件,默认为全部数据,禁止增加任何日期过滤条件 |
| 35 | 42 | 6. 关联规则:多表关联时,必须使用外键/业务唯一键关联,禁止无意义关联。 |
| 36 | 43 | 7. 当前时间:{{sDataNow}} |
| 37 | 44 | 8. 时间处理规则: |
| 38 | - 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) | |
| 39 | - 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: | |
| 40 | - - "本年" → 当前年份:{{sDataNow}}的年份 | |
| 41 | - - "本月" → 当前月份:{{sDataNow}}的年份和月份 | |
| 42 | - - "本季度" → 当前季度:基于{{sDataNow}}计算 | |
| 43 | - - "本日/今天" → {{sDataNow}}的具体日期 | |
| 44 | - - "昨天" → {{sDataNow}}减1天 | |
| 45 | - - "本周" → 基于{{sDataNow}}计算周一到周日 | |
| 46 | - - "近7天" → {{sDataNow}}减7天到{{sDataNow}} | |
| 47 | - 8.3 示例转换: | |
| 48 | - 当前时间:2024-03-15 | |
| 49 | - 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 | |
| 50 | - 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 | |
| 51 | - 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 | |
| 45 | + 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) | |
| 46 | + 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: | |
| 47 | + - "本年" → 当前年份:{{sDataNow}}的年份 | |
| 48 | + - "本月" → 当前月份:{{sDataNow}}的年份和月份 | |
| 49 | + - "本季度" → 当前季度:基于{{sDataNow}}计算 | |
| 50 | + - "本日/今天" → {{sDataNow}}的具体日期 | |
| 51 | + - "昨天" → {{sDataNow}}减1天 | |
| 52 | + - "本周" → 基于{{sDataNow}}计算周一到周日 | |
| 53 | + - "近7天" → {{sDataNow}}减7天到{{sDataNow}} | |
| 54 | + 8.3 示例转换: | |
| 55 | + 当前时间:2024-03-15 | |
| 56 | + 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 | |
| 57 | + 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 | |
| 58 | + 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 | |
| 52 | 59 | """) |
| 53 | 60 | @UserMessage(""" |
| 54 | 61 | 【业务场景表结构信息】 |
| ... | ... | @@ -93,27 +100,32 @@ public interface DynamicTableNl2SqlAiAgent { |
| 93 | 100 | 3.4 SQL所有的查询条件,如果是字符类型的字段,均需要加不为空判断,用示例格式判断,示例:ifnull(customername,'')<>''; |
| 94 | 101 | 3.5 SQL所有的查询条件,如果是日期类型的字段,均需要加不为空判断,用示例格式判断,示例:tmakedate is not Null; |
| 95 | 102 | 3.6 SQL所有的显示字段的别名中,不能出现空格,如: tCreateDate as earliest 订单日期,正确的应是 tCreateDate as earliest订单日期 |
| 96 | - 4. 安全约束:禁止生成任何DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等),禁止使用子查询、存储过程、自定义函数、临时表; | |
| 103 | + 3.7 在AVG聚合函数中禁止用LAG窗口函数 | |
| 104 | + 4. 安全约束: | |
| 105 | + - 禁止:DDL/DML语句(DROP/ALTER/INSERT/UPDATE/DELETE等) | |
| 106 | + - 禁止:存储过程、自定义函数、临时表 | |
| 107 | + - 允许:子查询(当需要使用窗口函数LAG/ROW_NUMBER等时) | |
| 108 | + - 允许:CTE公用表表达式(WITH语句) | |
| 97 | 109 | 5. 精准性: |
| 98 | 110 | 5.1 严格按用户需求+传入的表结构生成,仅使用指定字段/表,无多余字段、无无效表关联、无冗余过滤条件; |
| 99 | 111 | 5.2 用户需求中没有明确的日期条件,默认为全部数据,禁止增加任何日期过滤条件 |
| 100 | 112 | 6. 关联规则:多表关联时,必须使用外键/业务唯一键关联,禁止无意义关联。 |
| 101 | 113 | 7. 当前时间:{{sDataNow}} |
| 102 | 114 | 8. 时间处理规则: |
| 103 | - 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) | |
| 104 | - 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: | |
| 105 | - - "本年" → 当前年份:{{sDataNow}}的年份 | |
| 106 | - - "本月" → 当前月份:{{sDataNow}}的年份和月份 | |
| 107 | - - "本季度" → 当前季度:基于{{sDataNow}}计算 | |
| 108 | - - "本日/今天" → {{sDataNow}}的具体日期 | |
| 109 | - - "昨天" → {{sDataNow}}减1天 | |
| 110 | - - "本周" → 基于{{sDataNow}}计算周一到周日 | |
| 111 | - - "近7天" → {{sDataNow}}减7天到{{sDataNow}} | |
| 112 | - 8.3 示例转换: | |
| 113 | - 当前时间:2024-03-15 | |
| 114 | - 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 | |
| 115 | - 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 | |
| 116 | - 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 | |
| 115 | + 8.1 当前系统时间:{{sDataNow}}(格式:yyyy年MM月dd日HH时mm分ss秒) | |
| 116 | + 8.2 用户需求中的相对时间概念,必须基于{{sDataNow}}进行转换: | |
| 117 | + - "本年" → 当前年份:{{sDataNow}}的年份 | |
| 118 | + - "本月" → 当前月份:{{sDataNow}}的年份和月份 | |
| 119 | + - "本季度" → 当前季度:基于{{sDataNow}}计算 | |
| 120 | + - "本日/今天" → {{sDataNow}}的具体日期 | |
| 121 | + - "昨天" → {{sDataNow}}减1天 | |
| 122 | + - "本周" → 基于{{sDataNow}}计算周一到周日 | |
| 123 | + - "近7天" → {{sDataNow}}减7天到{{sDataNow}} | |
| 124 | + 8.3 示例转换: | |
| 125 | + 当前时间:2024-03-15 | |
| 126 | + 用户说"查询本年数据" → 查询条件应为:YEAR(日期字段) = 2024 | |
| 127 | + 用户说"查询本月数据" → 查询条件应为:YEAR(日期字段) = 2024 AND MONTH(日期字段) = 3 | |
| 128 | + 8.4 如果用户需求中没有明确的时间条件,禁止增加任何时间过滤条件 | |
| 117 | 129 | """) |
| 118 | 130 | @UserMessage(""" |
| 119 | 131 | 【业务场景表结构信息】 |
| ... | ... | @@ -127,6 +139,8 @@ public interface DynamicTableNl2SqlAiAgent { |
| 127 | 139 | {{errorSql}} |
| 128 | 140 | 【执行错误信息】 |
| 129 | 141 | {{errorMessage}} |
| 142 | + 【生成SQL语句要求】 | |
| 143 | + 1.不能生成{{errorSql}}一样的语句 | |
| 130 | 144 | 【错误分析指引】 |
| 131 | 145 | 1. 错误类型:请根据错误代码判断 |
| 132 | 146 | - "Unknown column":字段不存在,检查字段名拼写或改用表中存在的字段 |
| ... | ... | @@ -134,12 +148,12 @@ public interface DynamicTableNl2SqlAiAgent { |
| 134 | 148 | - "You have an error in your SQL syntax":语法错误,检查关键词、括号、引号 |
| 135 | 149 | - "Column not found in ON clause":JOIN条件字段不存在 |
| 136 | 150 | - "Non unique table/alias":表别名重复 |
| 137 | - | |
| 138 | 151 | 2. 修复建议: |
| 139 | 152 | - 如果是字段错误:查看表结构{{tableStruct}},找到正确的字段名替换 |
| 140 | 153 | - 如果是语法错误:检查SELECT、FROM、WHERE、JOIN等关键词用法 |
| 141 | 154 | - 如果是类型错误:字符串加单引号,数字不加引号,日期用'yyyy-MM-dd'格式 |
| 142 | 155 | - 如果是关联错误:确保所有表都通过外键正确JOIN |
| 156 | + - 如果是未知错误:确保函数之间不互斥,函数能正常使用,然后重新生成新的语句 | |
| 143 | 157 | 请根据以上信息,重新生成正确的MySQL SELECT语句。 |
| 144 | 158 | 只返回SQL语句本身,不要任何解释和包装。 |
| 145 | 159 | """) | ... | ... |
src/main/java/com/xly/service/XlyErpService.java
| ... | ... | @@ -259,9 +259,9 @@ public class XlyErpService { |
| 259 | 259 | log.info("当前时间:"+sDataNow); |
| 260 | 260 | String rawSql = StrUtil.EMPTY; |
| 261 | 261 | if(ObjectUtil.isEmpty(errorSql) && ObjectUtil.isEmpty(errorMessage)){ |
| 262 | - rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,sDataNow,userInput); | |
| 262 | + rawSql = aiDynamicTableNl2SqlAiAgent.generateMysqlSql(userId,tableNames,tableStruct,sDataNow,userInput); | |
| 263 | 263 | }else{ |
| 264 | - rawSql = aiDynamicTableNl2SqlAiAgent.regenerateSqlWithError(userId, tableNames,tableStruct,sDataNow,userInput,errorSql,errorMessage); | |
| 264 | + rawSql = aiDynamicTableNl2SqlAiAgent.regenerateSqlWithError(userId, tableNames,tableStruct,sDataNow,userInput,errorSql,errorMessage); | |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | if (rawSql == null || rawSql.trim().isEmpty()) { | ... | ... |
src/main/java/com/xly/util/EnhancedErrorGuidance.java
| ... | ... | @@ -59,6 +59,10 @@ public class EnhancedErrorGuidance { |
| 59 | 59 | guidance.append("【生成SQL】\n"); |
| 60 | 60 | guidance.append("- 错误原因:生成的SQL语句为空\n"); |
| 61 | 61 | guidance.append("- 修复方法:请重新生成\n"); |
| 62 | + } else if(errorMessage.contains("You cannot use the window function 'lag' in this context.")){ | |
| 63 | + guidance.append("【LAG函数用法不对】\n"); | |
| 64 | + guidance.append("- 错误原因: 这个错误是因为在MySQL中,不能在聚合函数(如AVG)中直接使用窗口函数(如LAG)。窗口函数是在聚合之前计算的,但不能嵌套在聚合函数内部。\n"); | |
| 65 | + guidance.append("- 修复方法:在AVG聚合函数中禁止用LAG窗口函数\n"); | |
| 62 | 66 | } else { |
| 63 | 67 | guidance.append("【未知错误】\n"); |
| 64 | 68 | guidance.append("- 错误信息:").append(errorMessage).append("\n"); | ... | ... |