From 7fa4a6937d3b99674c8bce732d1775f7948cabdc Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Sat, 20 Dec 2025 19:19:54 +0800 Subject: [PATCH 01/10] fix: add error fetch --- .../dataagent/common/constant/Constant.java | 3 + .../config/DataAgentConfiguration.java | 1 + .../ai/dataagent/prompt/PromptConstant.java | 4 + .../dispatcher/PythonExecutorDispatcher.java | 8 +- .../workflow/node/PythonAnalyzeNode.java | 17 +++- .../workflow/node/PythonExecuteNode.java | 29 +++++++ .../prompts/python-analyze-fallback.txt | 78 +++++++++++++++++++ .../resources/prompts/python-generator.txt | 13 +++- 8 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java index d0249aaa..36573e05 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java @@ -130,6 +130,9 @@ private Constant() { public static final String PYTHON_TRIES_COUNT = "PYTHON_TRIES_COUNT"; + // 标记是否进入Python执行失败的降级模式(超过最大重试次数后触发) + public static final String PYTHON_FALLBACK_MODE = "PYTHON_FALLBACK_MODE"; + // If code execution succeeds, output code running result; if fails, output error // information public static final String PYTHON_EXECUTE_NODE_OUTPUT = "PYTHON_EXECUTE_NODE_OUTPUT"; diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java index b6889c90..93945705 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java @@ -155,6 +155,7 @@ public StateGraph nl2sqlGraph(NodeBeanUtil nodeBeanUtil) throws GraphStateExcept keyStrategyHashMap.put(SQL_RESULT_LIST_MEMORY, KeyStrategy.REPLACE); keyStrategyHashMap.put(PYTHON_IS_SUCCESS, KeyStrategy.REPLACE); keyStrategyHashMap.put(PYTHON_TRIES_COUNT, KeyStrategy.REPLACE); + keyStrategyHashMap.put(PYTHON_FALLBACK_MODE, KeyStrategy.REPLACE); keyStrategyHashMap.put(PYTHON_EXECUTE_NODE_OUTPUT, KeyStrategy.REPLACE); keyStrategyHashMap.put(PYTHON_GENERATE_NODE_OUTPUT, KeyStrategy.REPLACE); keyStrategyHashMap.put(PYTHON_ANALYSIS_NODE_OUTPUT, KeyStrategy.REPLACE); diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java index 25503985..0dbaa63d 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java @@ -85,6 +85,10 @@ public static PromptTemplate getPythonAnalyzePromptTemplate() { return new PromptTemplate(PromptLoader.loadPrompt("python-analyze")); } + public static PromptTemplate getPythonAnalyzeFallbackPromptTemplate() { + return new PromptTemplate(PromptLoader.loadPrompt("python-analyze-fallback")); + } + public static PromptTemplate getBusinessKnowledgePromptTemplate() { return new PromptTemplate(PromptLoader.loadPrompt("business-knowledge")); } diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java index 0f1764f1..7e2e1e04 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java @@ -33,6 +33,12 @@ public class PythonExecutorDispatcher implements EdgeAction { @Override public String apply(OverAllState state) throws Exception { + boolean isFallbackMode = StateUtil.getObjectValue(state, PYTHON_FALLBACK_MODE, Boolean.class, false); + if (isFallbackMode) { + log.warn("Python执行进入降级模式,跳过重试直接进入分析节点"); + return PYTHON_ANALYZE_NODE; + } + // Determine if failed boolean isSuccess = StateUtil.getObjectValue(state, PYTHON_IS_SUCCESS, Boolean.class, false); if (!isSuccess) { @@ -40,7 +46,7 @@ public String apply(OverAllState state) throws Exception { log.error("Python Executor Node Error: {}", message); int tries = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 0); if (tries <= 0) { - log.warn("Python Executor Node Error: Exceeding the maximum number of iterations"); + log.error("Python执行失败且已超过最大重试次数,流程终止"); return END; } else { diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java index 8460a00f..2b52d059 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java @@ -60,9 +60,20 @@ public Map apply(OverAllState state) throws Exception { Map sqlExecuteResult = StateUtil.getObjectValue(state, SQL_EXECUTE_NODE_OUTPUT, Map.class, new HashMap<>()); - // Load Python code generation template - String systemPrompt = PromptConstant.getPythonAnalyzePromptTemplate() - .render(Map.of("python_output", pythonOutput, "user_query", userQuery)); + // 检查是否进入降级模式 + boolean isFallbackMode = StateUtil.getObjectValue(state, PYTHON_FALLBACK_MODE, Boolean.class, false); + + String systemPrompt; + if (isFallbackMode) { + // 降级模式:使用降级提示词文件 + systemPrompt = PromptConstant.getPythonAnalyzeFallbackPromptTemplate() + .render(Map.of("user_query", userQuery)); + log.warn("Python分析节点检测到降级模式,使用兜底提示词"); + } else { + // 正常模式:Load Python code generation template + systemPrompt = PromptConstant.getPythonAnalyzePromptTemplate() + .render(Map.of("python_output", pythonOutput, "user_query", userQuery)); + } Flux pythonAnalyzeFlux = llmService.callSystem(systemPrompt); diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java index 7cc6114b..99c78153 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java @@ -69,6 +69,10 @@ public Map apply(OverAllState state) throws Exception { String pythonCode = StateUtil.getStringValue(state, PYTHON_GENERATE_NODE_OUTPUT); List> sqlResults = StateUtil.hasValue(state, SQL_RESULT_LIST_MEMORY) ? StateUtil.getListValue(state, SQL_RESULT_LIST_MEMORY) : new ArrayList<>(); + + // 检查重试次数 + int triesCount = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 5); + CodePoolExecutorService.TaskRequest taskRequest = new CodePoolExecutorService.TaskRequest(pythonCode, objectMapper.writeValueAsString(sqlResults), null); @@ -78,6 +82,31 @@ public Map apply(OverAllState state) throws Exception { String errorMsg = "Python Execute Failed!\nStdOut: " + taskResponse.stdOut() + "\nStdErr: " + taskResponse.stdErr() + "\nExceptionMsg: " + taskResponse.exceptionMsg(); log.error(errorMsg); + + // 检查是否超过重试次数,如果是则启动降级逻辑 + if (triesCount <= 0) { + log.error("Python执行失败且已超过最大重试次数,启动降级兜底逻辑。错误信息: {}", errorMsg); + + String fallbackOutput = "{}"; + + Flux fallbackDisplayFlux = Flux.create(emitter -> { + emitter.next(ChatResponseUtil.createResponse("开始执行Python代码...")); + emitter.next(ChatResponseUtil.createResponse("Python代码执行失败已超过最大重试次数,采用降级策略继续处理。")); + emitter.complete(); + }); + + Flux> fallbackGenerator = FluxUtil.createStreamingGeneratorWithMessages( + this.getClass(), state, + v -> Map.of( + PYTHON_EXECUTE_NODE_OUTPUT, fallbackOutput, + PYTHON_IS_SUCCESS, false, + PYTHON_FALLBACK_MODE, true + ), + fallbackDisplayFlux); + + return Map.of(PYTHON_EXECUTE_NODE_OUTPUT, fallbackGenerator); + } + throw new RuntimeException(errorMsg); } diff --git a/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt b/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt new file mode 100644 index 00000000..d0eb812a --- /dev/null +++ b/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt @@ -0,0 +1,78 @@ +# ROLE: 数据分析友好提示专家 + +你是一位专业的数据分析师,负责在数据分析功能不可用时,向用户提供友好、专业的说明和建议。 + +**当前情况**:Python数据分析代码执行失败,无法完成深入的数据分析。 + +你的任务是根据用户的查询需求,生成一个**简洁、友好、专业**的说明。 + +--- + +### 输入信息 + +【用户原始查询】 +{user_query} + +--- + +### 输出要求 + +1. **只输出自然语言说明**,不要包含任何代码、JSON、Markdown或其他格式。 +2. 告知用户数据分析功能暂时不可用,但保持友好的语气。 +3. 如果可能,基于用户的查询提供简单的总结或建议。 +4. 给出友好的提示,建议用户简化问题或稍后重试。 +5. **严禁提及技术细节**(如Python代码失败、系统错误等)。 +6. 保持专业和友好的语气,让用户感受到关怀。 + +--- + +### 输出内容结构 + +你的说明应包含以下三个部分: + +1. **现状说明**:简洁地告知数据分析功能暂时不可用 +2. **简要总结**:基于用户查询提供一个简单的说明(如果可行) +3. **友好建议**:给出实用的建议或替代方案 + +--- + +### 示例 + +#### 示例 1 +**用户原始查询**: +"统计各渠道的线索数量和转化率。" + +**输出**: +抱歉,当前深度数据分析功能暂时不可用。根据您的查询,建议您可以先通过基础报表查看各渠道的线索总量,稍后我们再为您提供详细的转化率分析。如果问题紧急,建议您简化查询范围(如只关注特定渠道),这样可能更容易获得结果。 + +--- + +#### 示例 2 +**用户原始查询**: +"分析过去一年的城市销售数据趋势。" + +**输出**: +目前数据分析功能暂时不可用,无法为您提供完整的趋势分析。建议您可以先查看近期的销售数据摘要,或者将查询范围缩小到最近一个月的数据。我们会尽快恢复完整的分析能力,请稍后重试。 + +--- + +#### 示例 3 +**用户原始查询**: +"计算牛奶销量与最高销量商品的差值。" + +**输出**: +抱歉,当前无法完成复杂的数据对比分析。建议您可以先分别查看牛奶的销量和销量排名前几的商品,手动进行对比。如果需要批量对比,建议稍后重试或联系技术支持获取帮助。 + +--- + +### 注意事项 + +1. **语气友好**:始终保持友好和关怀的语气,避免让用户感到挫败。 +2. **避免技术术语**:不要使用"Python执行失败"、"代码错误"、"系统异常"等技术性表述。 +3. **提供价值**:即使分析失败,也要尽量给用户提供有用的建议或替代方案。 +4. **简洁明了**:说明应简洁易懂,避免冗长复杂的句子。 +5. **积极态度**:传递出问题是临时的、可以解决的积极态度。 + +--- + +请根据以上规则生成符合要求的友好说明: diff --git a/data-agent-management/src/main/resources/prompts/python-generator.txt b/data-agent-management/src/main/resources/prompts/python-generator.txt index 337f2738..c000c8a4 100644 --- a/data-agent-management/src/main/resources/prompts/python-generator.txt +++ b/data-agent-management/src/main/resources/prompts/python-generator.txt @@ -45,6 +45,10 @@ try: # 将输入数据转换为DataFrame以便于分析 df = pd.DataFrame(input_data) + # 自动类型推断:将字符串形式的数值转换为实际数值类型(解决后端统一返回字符串的问题) + for col in df.columns: + df[col] = pd.to_numeric(df[col], errors='ignore') + # 动态分析逻辑 # 示例:计算某些统计指标 result = \{ @@ -79,8 +83,9 @@ except Exception: # 注意事项 1. **输入验证**:确保代码能够正确处理空输入或格式不正确的输入,并在异常时提供清晰的错误信息。**处理的数据必须来自`json.load(sys.stdin)`**。 -2. **性能优化**:尽量减少不必要的计算和内存占用,确保代码在性能约束内高效运行。 -3. **结果完整性**:输出的JSON对象应全面反映分析结果,且字段命名清晰易懂。 +2. **类型转换**:由于后端SQL查询结果统一转换为字符串格式,**必须在DataFrame创建后进行类型推断**,使用`pd.to_numeric()`将数值字符串转换为实际数值类型,以便进行数学运算和统计分析。 +3. **性能优化**:尽量减少不必要的计算和内存占用,确保代码在性能约束内高效运行。 +4. **结果完整性**:输出的JSON对象应全面反映分析结果,且字段命名清晰易懂。 --- @@ -101,6 +106,10 @@ try: # 转换为DataFrame df = pd.DataFrame(input_data) + # 自动类型推断:将字符串形式的数值转换为实际数值类型 + for col in df.columns: + df[col] = pd.to_numeric(df[col], errors='ignore') + # 动态分析逻辑 result = \{ "channel_stats": [] From 373ac2d52a9413b7d2359f77d7a5615a8f7e3772 Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Sat, 20 Dec 2025 19:24:08 +0800 Subject: [PATCH 02/10] fix: format --- .../dataagent/workflow/node/PythonAnalyzeNode.java | 3 ++- .../dataagent/workflow/node/PythonExecuteNode.java | 13 +++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java index 2b52d059..c85c4734 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java @@ -69,7 +69,8 @@ public Map apply(OverAllState state) throws Exception { systemPrompt = PromptConstant.getPythonAnalyzeFallbackPromptTemplate() .render(Map.of("user_query", userQuery)); log.warn("Python分析节点检测到降级模式,使用兜底提示词"); - } else { + } + else { // 正常模式:Load Python code generation template systemPrompt = PromptConstant.getPythonAnalyzePromptTemplate() .render(Map.of("python_output", pythonOutput, "user_query", userQuery)); diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java index 99c78153..04a0b635 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java @@ -95,14 +95,11 @@ public Map apply(OverAllState state) throws Exception { emitter.complete(); }); - Flux> fallbackGenerator = FluxUtil.createStreamingGeneratorWithMessages( - this.getClass(), state, - v -> Map.of( - PYTHON_EXECUTE_NODE_OUTPUT, fallbackOutput, - PYTHON_IS_SUCCESS, false, - PYTHON_FALLBACK_MODE, true - ), - fallbackDisplayFlux); + Flux> fallbackGenerator = FluxUtil + .createStreamingGeneratorWithMessages(this.getClass(), state, + v -> Map.of(PYTHON_EXECUTE_NODE_OUTPUT, fallbackOutput, PYTHON_IS_SUCCESS, false, + PYTHON_FALLBACK_MODE, true), + fallbackDisplayFlux); return Map.of(PYTHON_EXECUTE_NODE_OUTPUT, fallbackGenerator); } From 2e27b1dd4ee6540f2bb17e9b3e775148579b2d2a Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Sun, 21 Dec 2025 22:32:50 +0800 Subject: [PATCH 03/10] fix: fix count bug --- .../cloud/ai/dataagent/common/constant/Constant.java | 3 +++ .../workflow/dispatcher/PythonExecutorDispatcher.java | 4 ++-- .../ai/dataagent/workflow/node/PythonExecuteNode.java | 8 ++++---- .../ai/dataagent/workflow/node/PythonGenerateNode.java | 6 ++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java index 36573e05..88fda35e 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java @@ -130,6 +130,9 @@ private Constant() { public static final String PYTHON_TRIES_COUNT = "PYTHON_TRIES_COUNT"; + // Python执行的最大重试次数 + public static final int PYTHON_MAX_TRIES_COUNT = 5; + // 标记是否进入Python执行失败的降级模式(超过最大重试次数后触发) public static final String PYTHON_FALLBACK_MODE = "PYTHON_FALLBACK_MODE"; diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java index 7e2e1e04..51ddb4cc 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java @@ -45,8 +45,8 @@ public String apply(OverAllState state) throws Exception { String message = StateUtil.getStringValue(state, PYTHON_EXECUTE_NODE_OUTPUT); log.error("Python Executor Node Error: {}", message); int tries = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 0); - if (tries <= 0) { - log.error("Python执行失败且已超过最大重试次数,流程终止"); + if (tries >= PYTHON_MAX_TRIES_COUNT) { + log.error("Python执行失败且已超过最大重试次数(已尝试次数:{}),流程终止", tries); return END; } else { diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java index 04a0b635..0d337c53 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java @@ -71,7 +71,7 @@ public Map apply(OverAllState state) throws Exception { ? StateUtil.getListValue(state, SQL_RESULT_LIST_MEMORY) : new ArrayList<>(); // 检查重试次数 - int triesCount = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 5); + int triesCount = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 0); CodePoolExecutorService.TaskRequest taskRequest = new CodePoolExecutorService.TaskRequest(pythonCode, objectMapper.writeValueAsString(sqlResults), null); @@ -83,9 +83,9 @@ public Map apply(OverAllState state) throws Exception { + taskResponse.stdErr() + "\nExceptionMsg: " + taskResponse.exceptionMsg(); log.error(errorMsg); - // 检查是否超过重试次数,如果是则启动降级逻辑 - if (triesCount <= 0) { - log.error("Python执行失败且已超过最大重试次数,启动降级兜底逻辑。错误信息: {}", errorMsg); + // 检查是否超过最大重试次数 + if (triesCount >= PYTHON_MAX_TRIES_COUNT) { + log.error("Python执行失败且已超过最大重试次数(已尝试次数:{}),启动降级兜底逻辑。错误信息: {}", triesCount, errorMsg); String fallbackOutput = "{}"; diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonGenerateNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonGenerateNode.java index 6fb766a4..bf9bb007 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonGenerateNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonGenerateNode.java @@ -56,8 +56,6 @@ public class PythonGenerateNode implements NodeAction { private static final int SAMPLE_DATA_NUMBER = 5; - private static final int MAX_TRIES_COUNT = 5; - private final ObjectMapper objectMapper; private final CodeExecutorProperties codeExecutorProperties; @@ -78,7 +76,7 @@ public Map apply(OverAllState state) throws Exception { List> sqlResults = StateUtil.hasValue(state, SQL_RESULT_LIST_MEMORY) ? StateUtil.getListValue(state, SQL_RESULT_LIST_MEMORY) : new ArrayList<>(); boolean codeRunSuccess = StateUtil.getObjectValue(state, PYTHON_IS_SUCCESS, Boolean.class, true); - int triesCount = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, MAX_TRIES_COUNT); + int triesCount = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 0); String userPrompt = StateUtil.getCanonicalQuery(state); if (!codeRunSuccess) { @@ -121,7 +119,7 @@ public Map apply(OverAllState state) throws Exception { aiResponse.length() - TextType.PYTHON.getEndSign().length()); aiResponse = MarkdownParserUtil.extractRawText(aiResponse); log.info("Python Generate Code: {}", aiResponse); - return Map.of(PYTHON_GENERATE_NODE_OUTPUT, aiResponse, PYTHON_TRIES_COUNT, triesCount - 1); + return Map.of(PYTHON_GENERATE_NODE_OUTPUT, aiResponse, PYTHON_TRIES_COUNT, triesCount + 1); }, Flux.concat(Flux.just(ChatResponseUtil.createPureResponse(TextType.PYTHON.getStartSign())), pythonGenerateFlux, From a20e5224aac45acd097328f13aca714db632d699 Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Fri, 26 Dec 2025 16:15:24 +0800 Subject: [PATCH 04/10] fix: --- .../workflow/node/PythonAnalyzeNode.java | 8 +- .../prompts/python-analyze-fallback.txt | 135 ++++++++++++------ 2 files changed, 97 insertions(+), 46 deletions(-) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java index c85c4734..c252f492 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java @@ -23,6 +23,7 @@ import com.alibaba.cloud.ai.dataagent.prompt.PromptConstant; import com.alibaba.cloud.ai.dataagent.service.llm.LlmService; import com.alibaba.cloud.ai.dataagent.common.util.FluxUtil; +import com.alibaba.cloud.ai.dataagent.common.util.JsonUtil; import com.alibaba.cloud.ai.dataagent.common.util.PlanProcessUtil; import com.alibaba.cloud.ai.dataagent.common.util.StateUtil; import lombok.AllArgsConstructor; @@ -65,10 +66,11 @@ public Map apply(OverAllState state) throws Exception { String systemPrompt; if (isFallbackMode) { - // 降级模式:使用降级提示词文件 + // 降级模式,传入用户查询和 SQL 执行结果,用于基础数据分析 + String sqlResultsJson = JsonUtil.getObjectMapper().writeValueAsString(sqlExecuteResult); systemPrompt = PromptConstant.getPythonAnalyzeFallbackPromptTemplate() - .render(Map.of("user_query", userQuery)); - log.warn("Python分析节点检测到降级模式,使用兜底提示词"); + .render(Map.of("user_query", userQuery, "sql_results", sqlResultsJson)); + log.warn("Python分析节点检测到降级模式,使用SQL数据进行兜底分析"); } else { // 正常模式:Load Python code generation template diff --git a/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt b/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt index d0eb812a..8518d3a6 100644 --- a/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt +++ b/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt @@ -2,77 +2,126 @@ 你是一位专业的数据分析师,负责在数据分析功能不可用时,向用户提供友好、专业的说明和建议。 -**当前情况**:Python数据分析代码执行失败,无法完成深入的数据分析。 - -你的任务是根据用户的查询需求,生成一个**简洁、友好、专业**的说明。 +你是一位专业的数据分析助手,当前系统处于**基础分析模式**,只能基于 SQL 查询结果提供数据解读,无法执行高级 Python 分析。 --- -### 输入信息 +## 输入信息 -【用户原始查询】 +### 用户查询需求 {user_query} +### SQL 执行结果(已完成) +{sql_results} + --- -### 输出要求 +## 任务要求 -1. **只输出自然语言说明**,不要包含任何代码、JSON、Markdown或其他格式。 -2. 告知用户数据分析功能暂时不可用,但保持友好的语气。 -3. 如果可能,基于用户的查询提供简单的总结或建议。 -4. 给出友好的提示,建议用户简化问题或稍后重试。 -5. **严禁提及技术细节**(如Python代码失败、系统错误等)。 -6. 保持专业和友好的语气,让用户感受到关怀。 +你需要基于上述 SQL 执行结果,对用户的查询需求进行**基础数据分析和解读**,同时**明确说明当前的功能限制**。 ---- +### 输出结构(必须包含以下三部分) -### 输出内容结构 +#### 1. 基础数据分析(必须) +- 基于 SQL 结果的关键发现 +- 数据的主要趋势和特征 +- 异常值或特殊情况说明 +- 简单的统计总结(如总数、平均值、排名等) -你的说明应包含以下三个部分: +#### 2. 功能限制说明(必须) +明确告知用户以下限制: +- ️ 当前仅提供基于 SQL 查询的基础数据分析 +- ️ 无法生成可视化图表(如柱状图、折线图、饼图等) +- ️ 无法执行复杂的数据计算(如相关性分析、预测模型等) +- ️ 无法进行跨数据集的深度对比分析 -1. **现状说明**:简洁地告知数据分析功能暂时不可用 -2. **简要总结**:基于用户查询提供一个简单的说明(如果可行) -3. **友好建议**:给出实用的建议或替代方案 +#### 3. 建议(可选) +- 如果需要上述高级功能,建议采取的替代方案 +- 对当前数据的进一步探索建议 --- -### 示例 +## 输出格式要求 -#### 示例 1 -**用户原始查询**: -"统计各渠道的线索数量和转化率。" - -**输出**: -抱歉,当前深度数据分析功能暂时不可用。根据您的查询,建议您可以先通过基础报表查看各渠道的线索总量,稍后我们再为您提供详细的转化率分析。如果问题紧急,建议您简化查询范围(如只关注特定渠道),这样可能更容易获得结果。 +1. **使用自然语言**,保持专业和友好的语气 +2. **结构清晰**,分段明确,易于阅读 +3. **数据准确**,所有分析必须基于提供的 SQL 结果,不得编造 +4. **限制明确**,让用户清楚知道当前模式的能力边界 +5. **避免技术术语**,不要提及"Python 执行失败"、"代码错误"等 --- -#### 示例 2 -**用户原始查询**: -"分析过去一年的城市销售数据趋势。" +## 示例输出 -**输出**: -目前数据分析功能暂时不可用,无法为您提供完整的趋势分析。建议您可以先查看近期的销售数据摘要,或者将查询范围缩小到最近一个月的数据。我们会尽快恢复完整的分析能力,请稍后重试。 +### 示例1:销售数据分析 ---- +用户查询:统计各渠道的线索数量和转化率 -#### 示例 3 -**用户原始查询**: -"计算牛奶销量与最高销量商品的差值。" +基础数据分析: +根据 SQL 查询结果,系统已获取到各渠道的线索数据。主要发现如下: +- 渠道A共有1,250条线索,占总量的42% +- 渠道B共有980条线索,占总量的33% +- 渠道C共有750条线索,占总量的25% -**输出**: -抱歉,当前无法完成复杂的数据对比分析。建议您可以先分别查看牛奶的销量和销量排名前几的商品,手动进行对比。如果需要批量对比,建议稍后重试或联系技术支持获取帮助。 +从绝对数量看,渠道A表现最佳,其次是渠道B和渠道C。 + +功能限制说明: + 当前系统处于基础分析模式,仅提供了基于 SQL 的数据统计。由于技术限制,暂时无法提供: + 可视化图表(如柱状图对比各渠道线索量) + 转化率的精确计算(需要结合多个数据源进行复杂运算) + 趋势预测和深度洞察 + +建议: +如果需要详细的转化率分析和可视化图表,建议: +1. 将数据导出后使用 Excel 或专业 BI 工具进行分析 +2. 稍后重试本功能,系统恢复后可提供完整的高级分析 --- -### 注意事项 +### 示例2:城市销售趋势 + +用户查询:分析过去一年的城市销售数据趋势 + +基础数据分析: +根据 SQL 查询结果,系统已获取到过去一年12个月的城市销售数据: + 总销售额:8,500万元 + 月均销售额:708万元 + 销售额最高月份:12月(1,200万元) + 销售额最低月份:2月(450万元) + +整体趋势显示,销售额在年末达到高峰,春节期间出现明显下滑。 + +功能限制说明: +️ 当前系统处于基础分析模式,仅提供了基于 SQL 的数据汇总。由于技术限制,暂时无法提供: + 趋势折线图(展示12个月的销售曲线) + 同比、环比增长率计算 + 季节性分析和预测建模 + +建议: +如需深度趋势分析和可视化展示,建议稍后重试或使用专业数据分析工具。 + + +### 示例3:商品销量对比 + +用户查询:计算牛奶销量与最高销量商品的差值 + +基础数据分析: +根据 SQL 查询结果: + 牛奶销量:3,500件 + 销量最高商品(矿泉水):8,200件 + 差值:4,700件 + +牛奶销量约为最高销量商品的43%,仍有较大提升空间。 + +功能限制说明: +️ 当前系统处于基础分析模式,仅提供了基于 SQL 的数据对比。由于技术限制,暂时无法提供: + 可视化对比图表 + 批量多商品对比分析 + 销量差异的深层原因挖掘 -1. **语气友好**:始终保持友好和关怀的语气,避免让用户感到挫败。 -2. **避免技术术语**:不要使用"Python执行失败"、"代码错误"、"系统异常"等技术性表述。 -3. **提供价值**:即使分析失败,也要尽量给用户提供有用的建议或替代方案。 -4. **简洁明了**:说明应简洁易懂,避免冗长复杂的句子。 -5. **积极态度**:传递出问题是临时的、可以解决的积极态度。 +**建议**: +如需批量对比或深度分析,建议稍后重试或联系技术支持。 --- -请根据以上规则生成符合要求的友好说明: +请根据上述规则和示例,生成符合要求的基础分析结果。 From 1722e7f408c77f6e379b77716a0f7de27d2a22fc Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Fri, 26 Dec 2025 17:21:46 +0800 Subject: [PATCH 05/10] fix: remove ai --- .../ai/dataagent/prompt/PromptConstant.java | 4 - .../workflow/node/PythonAnalyzeNode.java | 31 +++-- .../prompts/python-analyze-fallback.txt | 127 ------------------ 3 files changed, 19 insertions(+), 143 deletions(-) delete mode 100644 data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java index 0dbaa63d..25503985 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/prompt/PromptConstant.java @@ -85,10 +85,6 @@ public static PromptTemplate getPythonAnalyzePromptTemplate() { return new PromptTemplate(PromptLoader.loadPrompt("python-analyze")); } - public static PromptTemplate getPythonAnalyzeFallbackPromptTemplate() { - return new PromptTemplate(PromptLoader.loadPrompt("python-analyze-fallback")); - } - public static PromptTemplate getBusinessKnowledgePromptTemplate() { return new PromptTemplate(PromptLoader.loadPrompt("business-knowledge")); } diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java index c252f492..3e165199 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java @@ -23,9 +23,9 @@ import com.alibaba.cloud.ai.dataagent.prompt.PromptConstant; import com.alibaba.cloud.ai.dataagent.service.llm.LlmService; import com.alibaba.cloud.ai.dataagent.common.util.FluxUtil; -import com.alibaba.cloud.ai.dataagent.common.util.JsonUtil; import com.alibaba.cloud.ai.dataagent.common.util.PlanProcessUtil; import com.alibaba.cloud.ai.dataagent.common.util.StateUtil; +import com.alibaba.cloud.ai.dataagent.common.util.ChatResponseUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.model.ChatResponse; @@ -64,20 +64,27 @@ public Map apply(OverAllState state) throws Exception { // 检查是否进入降级模式 boolean isFallbackMode = StateUtil.getObjectValue(state, PYTHON_FALLBACK_MODE, Boolean.class, false); - String systemPrompt; if (isFallbackMode) { - // 降级模式,传入用户查询和 SQL 执行结果,用于基础数据分析 - String sqlResultsJson = JsonUtil.getObjectMapper().writeValueAsString(sqlExecuteResult); - systemPrompt = PromptConstant.getPythonAnalyzeFallbackPromptTemplate() - .render(Map.of("user_query", userQuery, "sql_results", sqlResultsJson)); - log.warn("Python分析节点检测到降级模式,使用SQL数据进行兜底分析"); - } - else { - // 正常模式:Load Python code generation template - systemPrompt = PromptConstant.getPythonAnalyzePromptTemplate() - .render(Map.of("python_output", pythonOutput, "user_query", userQuery)); + // 降级模式 + String fallbackMessage = "Python 高级分析功能暂时不可用,请检查相关配置和服务状态或者提问方式。系统将基于 SQL 查询结果生成基础报告。"; + log.warn("Python分析节点检测到降级模式,返回固定提示信息"); + + Flux fallbackFlux = Flux.just(ChatResponseUtil.createResponse(fallbackMessage)); + + Flux> generator = FluxUtil.createStreamingGeneratorWithMessages( + this.getClass(), state, "正在处理分析结果...\n", "\n处理完成。", aiResponse -> { + Map updatedSqlResult = PlanProcessUtil.addStepResult(sqlExecuteResult, + currentStep, fallbackMessage); + log.info("python fallback message: {}", fallbackMessage); + return Map.of(SQL_EXECUTE_NODE_OUTPUT, updatedSqlResult, PLAN_CURRENT_STEP, currentStep + 1); + }, fallbackFlux); + + return Map.of(PYTHON_ANALYSIS_NODE_OUTPUT, generator); } + String systemPrompt = PromptConstant.getPythonAnalyzePromptTemplate() + .render(Map.of("python_output", pythonOutput, "user_query", userQuery)); + Flux pythonAnalyzeFlux = llmService.callSystem(systemPrompt); Flux> generator = FluxUtil.createStreamingGeneratorWithMessages(this.getClass(), diff --git a/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt b/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt deleted file mode 100644 index 8518d3a6..00000000 --- a/data-agent-management/src/main/resources/prompts/python-analyze-fallback.txt +++ /dev/null @@ -1,127 +0,0 @@ -# ROLE: 数据分析友好提示专家 - -你是一位专业的数据分析师,负责在数据分析功能不可用时,向用户提供友好、专业的说明和建议。 - -你是一位专业的数据分析助手,当前系统处于**基础分析模式**,只能基于 SQL 查询结果提供数据解读,无法执行高级 Python 分析。 - ---- - -## 输入信息 - -### 用户查询需求 -{user_query} - -### SQL 执行结果(已完成) -{sql_results} - ---- - -## 任务要求 - -你需要基于上述 SQL 执行结果,对用户的查询需求进行**基础数据分析和解读**,同时**明确说明当前的功能限制**。 - -### 输出结构(必须包含以下三部分) - -#### 1. 基础数据分析(必须) -- 基于 SQL 结果的关键发现 -- 数据的主要趋势和特征 -- 异常值或特殊情况说明 -- 简单的统计总结(如总数、平均值、排名等) - -#### 2. 功能限制说明(必须) -明确告知用户以下限制: -- ️ 当前仅提供基于 SQL 查询的基础数据分析 -- ️ 无法生成可视化图表(如柱状图、折线图、饼图等) -- ️ 无法执行复杂的数据计算(如相关性分析、预测模型等) -- ️ 无法进行跨数据集的深度对比分析 - -#### 3. 建议(可选) -- 如果需要上述高级功能,建议采取的替代方案 -- 对当前数据的进一步探索建议 - ---- - -## 输出格式要求 - -1. **使用自然语言**,保持专业和友好的语气 -2. **结构清晰**,分段明确,易于阅读 -3. **数据准确**,所有分析必须基于提供的 SQL 结果,不得编造 -4. **限制明确**,让用户清楚知道当前模式的能力边界 -5. **避免技术术语**,不要提及"Python 执行失败"、"代码错误"等 - ---- - -## 示例输出 - -### 示例1:销售数据分析 - -用户查询:统计各渠道的线索数量和转化率 - -基础数据分析: -根据 SQL 查询结果,系统已获取到各渠道的线索数据。主要发现如下: -- 渠道A共有1,250条线索,占总量的42% -- 渠道B共有980条线索,占总量的33% -- 渠道C共有750条线索,占总量的25% - -从绝对数量看,渠道A表现最佳,其次是渠道B和渠道C。 - -功能限制说明: - 当前系统处于基础分析模式,仅提供了基于 SQL 的数据统计。由于技术限制,暂时无法提供: - 可视化图表(如柱状图对比各渠道线索量) - 转化率的精确计算(需要结合多个数据源进行复杂运算) - 趋势预测和深度洞察 - -建议: -如果需要详细的转化率分析和可视化图表,建议: -1. 将数据导出后使用 Excel 或专业 BI 工具进行分析 -2. 稍后重试本功能,系统恢复后可提供完整的高级分析 - ---- - -### 示例2:城市销售趋势 - -用户查询:分析过去一年的城市销售数据趋势 - -基础数据分析: -根据 SQL 查询结果,系统已获取到过去一年12个月的城市销售数据: - 总销售额:8,500万元 - 月均销售额:708万元 - 销售额最高月份:12月(1,200万元) - 销售额最低月份:2月(450万元) - -整体趋势显示,销售额在年末达到高峰,春节期间出现明显下滑。 - -功能限制说明: -️ 当前系统处于基础分析模式,仅提供了基于 SQL 的数据汇总。由于技术限制,暂时无法提供: - 趋势折线图(展示12个月的销售曲线) - 同比、环比增长率计算 - 季节性分析和预测建模 - -建议: -如需深度趋势分析和可视化展示,建议稍后重试或使用专业数据分析工具。 - - -### 示例3:商品销量对比 - -用户查询:计算牛奶销量与最高销量商品的差值 - -基础数据分析: -根据 SQL 查询结果: - 牛奶销量:3,500件 - 销量最高商品(矿泉水):8,200件 - 差值:4,700件 - -牛奶销量约为最高销量商品的43%,仍有较大提升空间。 - -功能限制说明: -️ 当前系统处于基础分析模式,仅提供了基于 SQL 的数据对比。由于技术限制,暂时无法提供: - 可视化对比图表 - 批量多商品对比分析 - 销量差异的深层原因挖掘 - -**建议**: -如需批量对比或深度分析,建议稍后重试或联系技术支持。 - ---- - -请根据上述规则和示例,生成符合要求的基础分析结果。 From 3c3a6290b375a62ba981c66678720ebb71c0a355 Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Fri, 26 Dec 2025 17:51:00 +0800 Subject: [PATCH 06/10] fix: message --- .../cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java index 3e165199..4575530d 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonAnalyzeNode.java @@ -66,7 +66,7 @@ public Map apply(OverAllState state) throws Exception { if (isFallbackMode) { // 降级模式 - String fallbackMessage = "Python 高级分析功能暂时不可用,请检查相关配置和服务状态或者提问方式。系统将基于 SQL 查询结果生成基础报告。"; + String fallbackMessage = "Python 高级分析功能暂时不可用,出现错误"; log.warn("Python分析节点检测到降级模式,返回固定提示信息"); Flux fallbackFlux = Flux.just(ChatResponseUtil.createResponse(fallbackMessage)); From bfd6847bc97343181d9bc98619ca5a1363c4c649 Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Sun, 28 Dec 2025 18:27:09 +0800 Subject: [PATCH 07/10] fix: python max test --- .../cloud/ai/dataagent/common/constant/Constant.java | 3 --- .../ai/dataagent/config/CodeExecutorProperties.java | 5 +++++ .../ai/dataagent/config/DataAgentConfiguration.java | 5 +++-- .../workflow/dispatcher/PythonExecutorDispatcher.java | 9 ++++++++- .../ai/dataagent/workflow/node/PythonExecuteNode.java | 9 +++++++-- data-agent-management/src/main/resources/application.yml | 4 +++- 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java index 88fda35e..36573e05 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/common/constant/Constant.java @@ -130,9 +130,6 @@ private Constant() { public static final String PYTHON_TRIES_COUNT = "PYTHON_TRIES_COUNT"; - // Python执行的最大重试次数 - public static final int PYTHON_MAX_TRIES_COUNT = 5; - // 标记是否进入Python执行失败的降级模式(超过最大重试次数后触发) public static final String PYTHON_FALLBACK_MODE = "PYTHON_FALLBACK_MODE"; diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/CodeExecutorProperties.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/CodeExecutorProperties.java index 5b21cb82..23bdad94 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/CodeExecutorProperties.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/CodeExecutorProperties.java @@ -120,4 +120,9 @@ public class CodeExecutorProperties { */ String networkMode = "none"; + /** + * Python执行的最大重试次数 + */ + Integer pythonMaxTriesCount = 5; + } diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java index 93945705..da8d406c 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/config/DataAgentConfiguration.java @@ -107,7 +107,8 @@ public WebClient.Builder webClientBuilder(@Value("${webclient.response.timeout:6 } @Bean - public StateGraph nl2sqlGraph(NodeBeanUtil nodeBeanUtil) throws GraphStateException { + public StateGraph nl2sqlGraph(NodeBeanUtil nodeBeanUtil, CodeExecutorProperties codeExecutorProperties) + throws GraphStateException { KeyStrategyFactory keyStrategyFactory = () -> { HashMap keyStrategyHashMap = new HashMap<>(); @@ -204,7 +205,7 @@ public StateGraph nl2sqlGraph(NodeBeanUtil nodeBeanUtil) throws GraphStateExcept .addEdge(PLANNER_NODE, PLAN_EXECUTOR_NODE) // python nodes .addEdge(PYTHON_GENERATE_NODE, PYTHON_EXECUTE_NODE) - .addConditionalEdges(PYTHON_EXECUTE_NODE, edge_async(new PythonExecutorDispatcher()), + .addConditionalEdges(PYTHON_EXECUTE_NODE, edge_async(new PythonExecutorDispatcher(codeExecutorProperties)), Map.of(PYTHON_ANALYZE_NODE, PYTHON_ANALYZE_NODE, END, END, PYTHON_GENERATE_NODE, PYTHON_GENERATE_NODE)) .addEdge(PYTHON_ANALYZE_NODE, PLAN_EXECUTOR_NODE) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java index 51ddb4cc..765dcbd0 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/dispatcher/PythonExecutorDispatcher.java @@ -19,6 +19,7 @@ import com.alibaba.cloud.ai.graph.OverAllState; import com.alibaba.cloud.ai.graph.action.EdgeAction; import com.alibaba.cloud.ai.dataagent.common.util.StateUtil; +import com.alibaba.cloud.ai.dataagent.config.CodeExecutorProperties; import lombok.extern.slf4j.Slf4j; import static com.alibaba.cloud.ai.dataagent.common.constant.Constant.*; @@ -31,6 +32,12 @@ @Slf4j public class PythonExecutorDispatcher implements EdgeAction { + private final CodeExecutorProperties codeExecutorProperties; + + public PythonExecutorDispatcher(CodeExecutorProperties codeExecutorProperties) { + this.codeExecutorProperties = codeExecutorProperties; + } + @Override public String apply(OverAllState state) throws Exception { boolean isFallbackMode = StateUtil.getObjectValue(state, PYTHON_FALLBACK_MODE, Boolean.class, false); @@ -45,7 +52,7 @@ public String apply(OverAllState state) throws Exception { String message = StateUtil.getStringValue(state, PYTHON_EXECUTE_NODE_OUTPUT); log.error("Python Executor Node Error: {}", message); int tries = StateUtil.getObjectValue(state, PYTHON_TRIES_COUNT, Integer.class, 0); - if (tries >= PYTHON_MAX_TRIES_COUNT) { + if (tries >= codeExecutorProperties.getPythonMaxTriesCount()) { log.error("Python执行失败且已超过最大重试次数(已尝试次数:{}),流程终止", tries); return END; } diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java index 0d337c53..117dd083 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/workflow/node/PythonExecuteNode.java @@ -18,6 +18,7 @@ import com.alibaba.cloud.ai.dataagent.common.enums.TextType; import com.alibaba.cloud.ai.dataagent.common.util.JsonParseUtil; +import com.alibaba.cloud.ai.dataagent.config.CodeExecutorProperties; import com.alibaba.cloud.ai.graph.GraphResponse; import com.alibaba.cloud.ai.graph.OverAllState; import com.alibaba.cloud.ai.graph.action.NodeAction; @@ -55,10 +56,14 @@ public class PythonExecuteNode implements NodeAction { private final JsonParseUtil jsonParseUtil; - public PythonExecuteNode(CodePoolExecutorService codePoolExecutor, JsonParseUtil jsonParseUtil) { + private final CodeExecutorProperties codeExecutorProperties; + + public PythonExecuteNode(CodePoolExecutorService codePoolExecutor, JsonParseUtil jsonParseUtil, + CodeExecutorProperties codeExecutorProperties) { this.codePoolExecutor = codePoolExecutor; this.objectMapper = JsonUtil.getObjectMapper(); this.jsonParseUtil = jsonParseUtil; + this.codeExecutorProperties = codeExecutorProperties; } @Override @@ -84,7 +89,7 @@ public Map apply(OverAllState state) throws Exception { log.error(errorMsg); // 检查是否超过最大重试次数 - if (triesCount >= PYTHON_MAX_TRIES_COUNT) { + if (triesCount >= codeExecutorProperties.getPythonMaxTriesCount()) { log.error("Python执行失败且已超过最大重试次数(已尝试次数:{}),启动降级兜底逻辑。错误信息: {}", triesCount, errorMsg); String fallbackOutput = "{}"; diff --git a/data-agent-management/src/main/resources/application.yml b/data-agent-management/src/main/resources/application.yml index d2369c82..214bfd24 100644 --- a/data-agent-management/src/main/resources/application.yml +++ b/data-agent-management/src/main/resources/application.yml @@ -26,6 +26,8 @@ spring: code-executor: # 运行Python代码的环境(生产环境建议使用docker,不建议使用local) code-pool-executor: local + # Python执行的最大重试次数 + python-max-tries-count: 1 file: type: local path-prefix: data-agent @@ -57,4 +59,4 @@ logging: com.alibaba.cloud.ai.dataagent.service: debug com.alibaba.cloud.ai.dataagent.workflow.node: debug com.alibaba.cloud.ai.mapper: debug - org.springframework.jdbc: debug + org.springframework.jdbc: debug \ No newline at end of file From ffa7a1faf8cb2c7c66948ddd7e65c4fca96e586b Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Sun, 28 Dec 2025 18:33:27 +0800 Subject: [PATCH 08/10] fix: ci bug --- data-agent-management/src/main/resources/application.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/data-agent-management/src/main/resources/application.yml b/data-agent-management/src/main/resources/application.yml index 214bfd24..1a67bea1 100644 --- a/data-agent-management/src/main/resources/application.yml +++ b/data-agent-management/src/main/resources/application.yml @@ -49,6 +49,7 @@ spring: enabled: true mybatis: + configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl From 0581ffbf8c8c86b2117c7e0b74611259f2e1b860 Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Mon, 29 Dec 2025 13:30:12 +0800 Subject: [PATCH 09/10] fix: add timeout --- data-agent-management/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-agent-management/src/main/resources/application.yml b/data-agent-management/src/main/resources/application.yml index 1a67bea1..21537029 100644 --- a/data-agent-management/src/main/resources/application.yml +++ b/data-agent-management/src/main/resources/application.yml @@ -27,7 +27,7 @@ spring: # 运行Python代码的环境(生产环境建议使用docker,不建议使用local) code-pool-executor: local # Python执行的最大重试次数 - python-max-tries-count: 1 + python-max-tries-count: 5 file: type: local path-prefix: data-agent From 1cf1562aec82bab06dfaaabf36558b5715c1bb4b Mon Sep 17 00:00:00 2001 From: mengnankkkk Date: Mon, 29 Dec 2025 13:34:21 +0800 Subject: [PATCH 10/10] fix: ci bug --- data-agent-management/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-agent-management/src/main/resources/application.yml b/data-agent-management/src/main/resources/application.yml index 21537029..b821ad11 100644 --- a/data-agent-management/src/main/resources/application.yml +++ b/data-agent-management/src/main/resources/application.yml @@ -60,4 +60,4 @@ logging: com.alibaba.cloud.ai.dataagent.service: debug com.alibaba.cloud.ai.dataagent.workflow.node: debug com.alibaba.cloud.ai.mapper: debug - org.springframework.jdbc: debug \ No newline at end of file + org.springframework.jdbc: debug