package com.xly.service; import com.alibaba.fastjson2.JSON; import com.xly.agent.DynamicTableNl2SqlAiAgent; import com.xly.entity.DynamicNl2SqlRequest; import com.xly.entity.Nl2SqlResult; import com.xly.util.SqlExecuteUtil; import com.xly.util.SqlValidateUtil; import jakarta.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; /** * 动态表结构的NL2SQL业务服务层 * 适配任意表结构、多业务场景 */ @Service public class DynamicNl2SqlService { private static final Logger log = LoggerFactory.getLogger(DynamicNl2SqlService.class); @Resource private DynamicTableNl2SqlAiAgent dynamicTableNl2SqlAiAgent; @Resource private SqlExecuteUtil sqlExecuteUtil; /** * 执行动态表结构的NL2SQL全流程 * @param request 动态表结构请求(含db名、表名、表结构、用户问题) * @return 结构化NL2SQL结果 */ public Nl2SqlResult executeDynamicNl2Sql(DynamicNl2SqlRequest request) { log.info("开始执行动态表结构NL2SQL流程,请求:{}", JSON.toJSONString(request)); // 1. 入参非空校验(重点校验表结构和用户问题) if (request.getTableStruct() == null || request.getTableStruct().trim().isEmpty() || request.getQuestion() == null || request.getQuestion().trim().isEmpty()) { throw new IllegalArgumentException("表结构和用户查询问题不能为空"); } // 补全默认值(如数据库名默认取配置中的值) String tableNames = request.getTableNames() == null ? "" : request.getTableNames().trim(); String rawSql = "select * from " + tableNames + " where 1=1 "; // 2. 调用AI服务生成SQL(传入所有动态参数) // String rawSql = dynamicTableNl2SqlAiAgent.generateMysqlSql( // tableNames, // request.getTableStruct().trim(), // request.getQuestion().trim() // ); // if (rawSql == null || rawSql.trim().isEmpty()) { // throw new SqlGenerateException("AI服务生成SQL失败,返回结果为空"); // } // log.info("AI服务生成原始SQL:{}", rawSql); // 3. 清理SQL多余符号 + 生产级强校验(核心安全保障,不可省略) String cleanSql = SqlValidateUtil.cleanSqlSymbol(rawSql); SqlValidateUtil.validateMysqlSql(cleanSql); log.info("SQL清理并强校验通过,可执行SQL:{}", cleanSql); // 4. 执行SQL获取结构化结果 List> sqlResult = sqlExecuteUtil.executeSelectSql(cleanSql); log.info("MySQL SQL执行完成,返回结果条数:{}", sqlResult.size()); String resultExplain =""; // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务) String resultJson = JSON.toJSONString(sqlResult); // String resultExplain = dynamicTableNl2SqlAiAgent.explainSqlResult( // request.getQuestion().trim(), // cleanSql, // request.getTableStruct().trim(), // resultJson // ); // 6. 封装结果返回 Nl2SqlResult nl2SqlResult = new Nl2SqlResult(); nl2SqlResult.setGenerateSql(cleanSql); nl2SqlResult.setSqlResult(sqlResult); nl2SqlResult.setResultExplain(resultExplain); log.info("动态表结构NL2SQL流程执行完成"); return nl2SqlResult; } }