Przeglądaj źródła

提交批处理逻辑,修改日志逻辑

wangyang 4 dni temu
rodzic
commit
f481f764ac

+ 2 - 2
.gitignore

@@ -43,8 +43,8 @@ ENV/
 logs/
 llmops/logs/
 
-# API results
-llmops/api_results/
+# API results (包括所有带编号的文件夹,如 api_results_1/, api_results_2/ 等)
+llmops/api_results*/
 
 # OS
 .DS_Store

+ 38 - 1
README

@@ -9,4 +9,41 @@ pip install langchain
 pip install langchain_openai
 pip install fastapi
 pip install uvicorn
-pip install pdfplumber   (pdf交易流水单解析需要)
+pip install pdfplumber   (pdf交易流水单解析需要)
+
+三、使用说明
+==========
+
+1. 环境准备:
+   # 安装依赖
+   pip install -r requirements.txt
+
+   # 配置API密钥
+   cp env_example.txt .env
+   # 编辑 .env 文件,填入你的 DEEPSEEK_API_KEY
+
+2. 批量运行工作流(推荐):
+   # 方法1:通过模块运行(推荐)
+   python -m llmops
+
+   # 方法2:直接执行文件(适用于PyCharm)
+   python llmops/batch_runner.py
+
+   # 如果需要修改参数,请直接编辑 llmops/batch_runner.py 中的配置参数:
+   # RUNS = 2         # 运行次数
+   # INDUSTRY = "农业"  # 行业
+   # DATA_FILE = "data_files/交易流水样例数据.csv"  # 数据文件
+   # QUESTION = "..."  # 查询问题
+
+⚠️ 重要:如果遇到依赖版本冲突,请参考 RUN_GUIDE.md 中的解决方案
+
+四、日志管理
+==========
+
+每次运行会创建独立的日志文件夹:
+- api_results_1/     # 第一次运行
+- api_results_2/     # 第二次运行
+- api_results_3/     # 第三次运行
+- ...
+
+这样便于整理和对比不同运行的结果。

+ 23 - 0
config.py

@@ -139,3 +139,26 @@ tx_flow_analysis_config = {
     "llm": model_name
 }
 
+# 从.env文件读取API密钥
+try:
+    from dotenv import load_dotenv
+    import os
+
+    # 加载.env文件
+    load_dotenv()
+
+    # 读取DeepSeek API密钥
+    DEEPSEEK_API_KEY = os.getenv('DEEPSEEK_API_KEY', '')
+
+    if not DEEPSEEK_API_KEY:
+        print("⚠️ 警告: 未找到 DEEPSEEK_API_KEY 环境变量,请在.env文件中设置")
+
+except ImportError:
+    print("⚠️ 警告: 未安装 python-dotenv 包,无法从.env文件读取API密钥")
+    print("请运行: pip install python-dotenv")
+    DEEPSEEK_API_KEY = ''
+
+# 如果没有从.env读取到,尝试从环境变量读取
+if not DEEPSEEK_API_KEY:
+    DEEPSEEK_API_KEY = os.getenv('DEEPSEEK_API_KEY', '')
+

+ 51 - 123
llmops/agents/metric_calculation_agent.py

@@ -272,38 +272,26 @@ class MetricCalculationAgent:
                                         # 从result字段中提取JSON
                                         extracted_result = self._extract_json_from_result(data["result"])
 
-                            # 记录API调用结果
+                            # 记录API调用结果 - 简化版
                             end_time = datetime.now()
                             call_id = f"api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                             api_call_info = {
                                 "call_id": call_id,
-                                "timestamp": end_time.isoformat(),
-                                "agent": "MetricCalculationAgent",
-                                "api_endpoint": url,
-                                "config_name": config_name,
-                                "request": {
-                                    "method": method,
-                                    "url": url,
-                                    "headers": headers,
-                                    "json_data": json_data if method.upper() == "POST" else None,
-                                    "params": params if method.upper() == "GET" else None,
-                                    "start_time": start_time.isoformat()
-                                },
                                 "response": {
                                     "status_code": response.status_code,
                                     "data": response_data,
-                                    "extracted_result": extracted_result,
-                                    "end_time": end_time.isoformat(),
-                                    "duration": (end_time - start_time).total_seconds()
-                                },
-                                "success": True
+                                    "extracted_result": extracted_result
+                                }
                             }
                             self.api_calls.append(api_call_info)
 
-                            # 保存API结果到文件
-                            api_results_dir = "api_results"
+                            # 保存API结果到文件 - 成功状态
+                            # 使用运行ID创建独立的文件夹
+                            run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                            api_results_dir = f"api_results_{run_id}"
                             os.makedirs(api_results_dir, exist_ok=True)
-                            filename = f"{call_id}.json"
+                            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                            filename = f"{timestamp}_{call_id}_success.json"
                             filepath = os.path.join(api_results_dir, filename)
 
                             try:
@@ -320,38 +308,26 @@ class MetricCalculationAgent:
                                 "status_code": response.status_code
                             }
                         except json.JSONDecodeError:
-                            # 记录API调用结果(JSON解析失败)
+                            # 记录API调用结果(JSON解析失败)- 简化版
                             end_time = datetime.now()
                             call_id = f"api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                             api_call_info = {
                                 "call_id": call_id,
-                                "timestamp": end_time.isoformat(),
-                                "agent": "MetricCalculationAgent",
-                                "api_endpoint": url,
-                                "config_name": config_name,
-                                "request": {
-                                    "method": method,
-                                    "url": url,
-                                    "headers": headers,
-                                    "json_data": json_data if method.upper() == "POST" else None,
-                                    "params": params if method.upper() == "GET" else None,
-                                    "start_time": start_time.isoformat()
-                                },
                                 "response": {
                                     "status_code": response.status_code,
                                     "data": response.text,
-                                    "error": "JSON解析失败",
-                                    "end_time": end_time.isoformat(),
-                                    "duration": (end_time - start_time).total_seconds()
-                                },
-                                "success": False
+                                    "error": "JSON解析失败"
+                                }
                             }
                             self.api_calls.append(api_call_info)
 
-                            # 保存API结果到文件
-                            api_results_dir = "api_results"
+                            # 保存API结果到文件 - 失败状态
+                            # 使用运行ID创建独立的文件夹
+                            run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                            api_results_dir = f"api_results_{run_id}"
                             os.makedirs(api_results_dir, exist_ok=True)
-                            filename = f"{call_id}.json"
+                            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                            filename = f"{timestamp}_{call_id}_fail.json"
                             filepath = os.path.join(api_results_dir, filename)
 
                             try:
@@ -368,37 +344,25 @@ class MetricCalculationAgent:
                                 "status_code": response.status_code
                             }
                     else:
-                        # 记录API调用结果(HTTP错误)
+                        # 记录API调用结果(HTTP错误)- 简化版
                         end_time = datetime.now()
                         call_id = f"api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                         api_call_info = {
                             "call_id": call_id,
-                            "timestamp": end_time.isoformat(),
-                            "agent": "MetricCalculationAgent",
-                            "api_endpoint": url,
-                            "config_name": config_name,
-                            "request": {
-                                "method": method,
-                                "url": url,
-                                "headers": headers,
-                                "json_data": json_data if method.upper() == "POST" else None,
-                                "params": params if method.upper() == "GET" else None,
-                                "start_time": start_time.isoformat()
-                            },
                             "response": {
                                 "status_code": response.status_code,
-                                "error": response.text,
-                                "end_time": end_time.isoformat(),
-                                "duration": (end_time - start_time).total_seconds()
-                            },
-                            "success": False
+                                "error": response.text
+                            }
                         }
                         self.api_calls.append(api_call_info)
 
-                        # 保存API结果到文件
-                        api_results_dir = "api_results"
+                        # 保存API结果到文件 - 失败状态
+                        # 使用运行ID创建独立的文件夹
+                        run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                        api_results_dir = f"api_results_{run_id}"
                         os.makedirs(api_results_dir, exist_ok=True)
-                        filename = f"{call_id}.json"
+                        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                        filename = f"{timestamp}_{call_id}_fail.json"
                         filepath = os.path.join(api_results_dir, filename)
 
                         try:
@@ -418,36 +382,24 @@ class MetricCalculationAgent:
                     break
 
                 except requests.exceptions.Timeout:
-                    # 记录API调用结果(超时)
+                    # 记录API调用结果(超时)- 简化版
                     end_time = datetime.now()
                     call_id = f"api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "MetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": config_name,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data if method.upper() == "POST" else None,
-                            "params": params if method.upper() == "GET" else None,
-                            "start_time": start_time.isoformat()
-                        },
                         "response": {
-                            "error": "API调用超时",
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": False
+                            "error": "API调用超时"
+                        }
                     }
                     self.api_calls.append(api_call_info)
 
                     # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
-                    filename = f"{call_id}.json"
+                    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                    filename = f"{timestamp}_{call_id}_fail.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:
@@ -469,36 +421,24 @@ class MetricCalculationAgent:
                             "message": "API调用超时"
                         }
                 except requests.exceptions.RequestException as e:
-                    # 记录API调用结果(请求异常)
+                    # 记录API调用结果(请求异常)- 简化版
                     end_time = datetime.now()
                     call_id = f"api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "MetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": config_name,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data if method.upper() == "POST" else None,
-                            "params": params if method.upper() == "GET" else None,
-                            "start_time": start_time.isoformat()
-                        },
                         "response": {
-                            "error": str(e),
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": False
+                            "error": str(e)
+                        }
                     }
                     self.api_calls.append(api_call_info)
 
                     # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
-                    filename = f"{call_id}.json"
+                    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                    filename = f"{timestamp}_{call_id}_fail.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:
@@ -520,36 +460,24 @@ class MetricCalculationAgent:
                             "message": f"API调用异常: {str(e)}"
                         }
                 except Exception as e:
-                    # 记录API调用结果(其他异常)
+                    # 记录API调用结果(其他异常)- 简化版
                     end_time = datetime.now()
                     call_id = f"api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "MetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": config_name,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data if method.upper() == "POST" else None,
-                            "params": params if method.upper() == "GET" else None,
-                            "start_time": start_time.isoformat()
-                        },
                         "response": {
-                            "error": str(e),
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": False
+                            "error": str(e)
+                        }
                     }
                     self.api_calls.append(api_call_info)
 
                     # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
-                    filename = f"{call_id}.json"
+                    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                    filename = f"{timestamp}_{call_id}_fail.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:

+ 28 - 21
llmops/agents/outline_agent.py

@@ -326,38 +326,45 @@ class OutlineGeneratorAgent:
             print(f"解析大纲响应失败: {e},使用默认大纲")
             # 不在这里创建大纲,在函数末尾统一处理
 
-        # 记录API调用结果
+        # 记录API调用结果 - 简化版:只保存提示词和结果大纲
         call_id = f"api_mll_大纲生成_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
+
+        # 从content中提取JSON结果
+        extracted_json = ""
+        try:
+            json_start = content.find('{')
+            json_end = content.rfind('}') + 1
+            if json_start >= 0 and json_end > json_start:
+                extracted_json = content[json_start:json_end]
+        except:
+            extracted_json = content  # 如果提取失败,使用原始content
+
         api_call_info = {
-            "call_id": call_id,
-            "timestamp": end_time.isoformat(),
-            "agent": "OutlineGeneratorAgent",
-            "model": "deepseek-chat",
-            "request": {
-                "question": question,
-                "sample_data_count": len(sample_data),
-                "prompt": prompt,
-                "start_time": start_time.isoformat()
-            },
-            "response": {
-                "content": content,
-                "end_time": end_time.isoformat(),
-                "duration": (end_time - start_time).total_seconds()
-            },
-            "success": True
+            "prompt": full_prompt,
+            "outline_result": extracted_json
         }
         self.api_calls.append(api_call_info)
 
-        # 保存API结果到文件
-        api_results_dir = "api_results"
+        # 保存API结果到文件 (Markdown格式,更易阅读)
+        # 使用运行ID创建独立的文件夹
+        run_id = os.environ.get('FLOW_RUN_ID', 'default')
+        api_results_dir = f"api_results_{run_id}"
         os.makedirs(api_results_dir, exist_ok=True)
         timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
-        filename = f"{timestamp}_{call_id}.json"
+        filename = f"{timestamp}_{call_id}.md"
         filepath = os.path.join(api_results_dir, filename)
 
         try:
             with open(filepath, 'w', encoding='utf-8') as f:
-                json.dump(api_call_info, f, ensure_ascii=False, indent=2)
+                f.write("# 大纲生成结果\n\n")
+                f.write("## 提示词入参\n\n")
+                f.write("```\n")
+                f.write(api_call_info["prompt"])
+                f.write("\n```\n\n")
+                f.write("## 生成的大纲结果\n\n")
+                f.write("```json\n")
+                f.write(api_call_info["outline_result"])
+                f.write("\n```\n")
             print(f"[API_RESULT] 保存API结果文件: {filepath}")
         except Exception as e:
             print(f"[ERROR] 保存API结果文件失败: {filepath}, 错误: {str(e)}")

+ 23 - 20
llmops/agents/planning_agent.py

@@ -211,39 +211,42 @@ class PlanningAgent:
             # 返回默认决策
             decision = self._get_default_decision(current_state)
 
-        # 记录API调用结果
+        # 记录API调用结果 - 简化版
         content = response.content if hasattr(response, 'content') else str(response)
+
+        # 从content中提取JSON结果
+        extracted_json = ""
+        try:
+            json_start = content.find('{')
+            json_end = content.rfind('}') + 1
+            if json_start >= 0 and json_end > json_start:
+                extracted_json = content[json_start:json_end]
+        except:
+            extracted_json = content  # 如果提取失败,使用原始content
+
         call_id = f"api_mll_规划决策_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
         api_call_info = {
             "call_id": call_id,
-            "timestamp": end_time.isoformat(),
-            "agent": "PlanningAgent",
-            "model": "deepseek-chat",
-            "request": {
-                "question": question,
-                "status_info": status_info,
-                "start_time": start_time.isoformat()
-            },
-            "response": {
-                "content": content,
-                "decision": decision.dict() if hasattr(decision, 'dict') else decision,
-                "end_time": end_time.isoformat(),
-                "duration": (end_time - start_time).total_seconds()
-            },
-            "success": True
+            "response": extracted_json
         }
         self.api_calls.append(api_call_info)
 
-        # 保存API结果到文件
-        api_results_dir = "api_results"
+        # 保存API结果到文件 - Markdown格式,更易阅读
+        # 使用运行ID创建独立的文件夹
+        run_id = os.environ.get('FLOW_RUN_ID', 'default')
+        api_results_dir = f"api_results_{run_id}"
         os.makedirs(api_results_dir, exist_ok=True)
         timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
-        filename = f"{timestamp}_{call_id}.json"
+        filename = f"{timestamp}_{call_id}.md"
         filepath = os.path.join(api_results_dir, filename)
 
         try:
             with open(filepath, 'w', encoding='utf-8') as f:
-                json.dump(api_call_info, f, ensure_ascii=False, indent=2)
+                f.write("# 规划决策结果\n\n")
+                f.write("## 决策结果\n\n")
+                f.write("```json\n")
+                f.write(api_call_info["response"])
+                f.write("\n```\n")
             print(f"[API_RESULT] 保存API结果文件: {filepath}")
         except Exception as e:
             print(f"[ERROR] 保存API结果文件失败: {filepath}, 错误: {str(e)}")

+ 117 - 232
llmops/agents/rules_engine_metric_calculation_agent.py

@@ -290,37 +290,22 @@ class RulesEngineMetricCalculationAgent:
                 try:
                     response_data = response.json()
 
-                    # 记录API调用结果
+                    # 记录API调用结果 - 简化版
                     end_time = datetime.now()
                     call_id = f"rules_api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "RulesEngineMetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": config_name,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data,
-                            "start_time": start_time.isoformat()
-                        },
-                        "response": {
-                            "status_code": response.status_code,
-                            "data": response_data,
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": True
+                        "response": response_data
                     }
                     self.api_calls.append(api_call_info)
 
-                    # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 保存API结果到文件 - 成功状态
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
                     timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
-                    filename = f"{timestamp}_{call_id}.json"
+                    filename = f"{timestamp}_{call_id}_success.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:
@@ -336,38 +321,26 @@ class RulesEngineMetricCalculationAgent:
                         "status_code": response.status_code
                     }
                 except json.JSONDecodeError:
-                    # 记录API调用结果(JSON解析失败)
+                    # 记录API调用结果(JSON解析失败)- 简化版
                     end_time = datetime.now()
                     call_id = f"rules_api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "RulesEngineMetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": config_name,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data,
-                            "start_time": start_time.isoformat()
-                        },
                         "response": {
                             "status_code": response.status_code,
                             "data": response.text,
-                            "error": "JSON解析失败",
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": False
+                            "error": "JSON解析失败"
+                        }
                     }
                     self.api_calls.append(api_call_info)
 
-                    # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 保存API结果到文件 - 失败状态
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
                     timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
-                    filename = f"{timestamp}_{call_id}.json"
+                    filename = f"{timestamp}_{call_id}_fail.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:
@@ -383,36 +356,25 @@ class RulesEngineMetricCalculationAgent:
                         "status_code": response.status_code
                     }
             else:
-                # 记录API调用结果(HTTP错误)
+                # 记录API调用结果(HTTP错误)- 简化版
                 end_time = datetime.now()
                 call_id = f"rules_api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                 api_call_info = {
                     "call_id": call_id,
-                    "timestamp": end_time.isoformat(),
-                    "agent": "RulesEngineMetricCalculationAgent",
-                    "api_endpoint": url,
-                    "config_name": config_name,
-                    "request": {
-                        "method": method,
-                        "url": url,
-                        "headers": headers,
-                        "json_data": json_data,
-                        "start_time": start_time.isoformat()
-                    },
                     "response": {
                         "status_code": response.status_code,
-                        "error": response.text,
-                        "end_time": end_time.isoformat(),
-                        "duration": (end_time - start_time).total_seconds()
-                    },
-                    "success": False
+                        "error": response.text
+                    }
                 }
                 self.api_calls.append(api_call_info)
 
-                # 保存API结果到文件
-                api_results_dir = "api_results"
+                # 保存API结果到文件 - 失败状态
+                # 使用运行ID创建独立的文件夹
+                run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                api_results_dir = f"api_results_{run_id}"
                 os.makedirs(api_results_dir, exist_ok=True)
-                filename = f"{call_id}.json"
+                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                filename = f"{timestamp}_{call_id}_fail.json"
                 filepath = os.path.join(api_results_dir, filename)
 
                 try:
@@ -429,91 +391,91 @@ class RulesEngineMetricCalculationAgent:
                 }
 
         except requests.exceptions.Timeout:
-            # 记录API调用结果(超时)
+            # 记录API调用结果(超时)- 简化版
             end_time = datetime.now()
             call_id = f"rules_api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
             api_call_info = {
                 "call_id": call_id,
-                "timestamp": end_time.isoformat(),
-                "agent": "RulesEngineMetricCalculationAgent",
-                "api_endpoint": url,
-                "config_name": config_name,
-                "request": {
-                    "method": method,
-                    "url": url,
-                    "headers": headers,
-                    "json_data": json_data if 'json_data' in locals() else None,
-                    "start_time": start_time.isoformat()
-                },
                 "response": {
-                    "error": "API调用超时",
-                    "end_time": end_time.isoformat(),
-                    "duration": (end_time - start_time).total_seconds()
-                },
-                "success": False
+                    "error": "API调用超时"
+                }
             }
             self.api_calls.append(api_call_info)
 
+            # 保存API结果到文件 - 失败状态
+            api_results_dir = "api_results"
+            os.makedirs(api_results_dir, exist_ok=True)
+            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+            filename = f"{timestamp}_{call_id}_fail.json"
+            filepath = os.path.join(api_results_dir, filename)
+
+            try:
+                with open(filepath, 'w', encoding='utf-8') as f:
+                    json.dump(api_call_info, f, ensure_ascii=False, indent=2)
+                print(f"[RULES_API_RESULT] 保存规则引擎API结果文件: {filepath}")
+            except Exception as e:
+                print(f"[ERROR] 保存规则引擎API结果文件失败: {filepath}, 错误: {str(e)}")
+
             return {
                 "success": False,
                 "message": "规则引擎API调用超时"
             }
         except requests.exceptions.RequestException as e:
-            # 记录API调用结果(请求异常)
+            # 记录API调用结果(请求异常)- 简化版
             end_time = datetime.now()
             call_id = f"rules_api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
             api_call_info = {
                 "call_id": call_id,
-                "timestamp": end_time.isoformat(),
-                "agent": "RulesEngineMetricCalculationAgent",
-                "api_endpoint": url,
-                "config_name": config_name,
-                "request": {
-                    "method": method,
-                    "url": url,
-                    "headers": headers,
-                    "json_data": json_data if 'json_data' in locals() else None,
-                    "start_time": start_time.isoformat()
-                },
                 "response": {
-                    "error": str(e),
-                    "end_time": end_time.isoformat(),
-                    "duration": (end_time - start_time).total_seconds()
-                },
-                "success": False
+                    "error": str(e)
+                }
             }
             self.api_calls.append(api_call_info)
 
+            # 保存API结果到文件 - 失败状态
+            api_results_dir = "api_results"
+            os.makedirs(api_results_dir, exist_ok=True)
+            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+            filename = f"{timestamp}_{call_id}_fail.json"
+            filepath = os.path.join(api_results_dir, filename)
+
+            try:
+                with open(filepath, 'w', encoding='utf-8') as f:
+                    json.dump(api_call_info, f, ensure_ascii=False, indent=2)
+                print(f"[RULES_API_RESULT] 保存规则引擎API结果文件: {filepath}")
+            except Exception as e:
+                print(f"[ERROR] 保存规则引擎API结果文件失败: {filepath}, 错误: {str(e)}")
+
             return {
                 "success": False,
                 "message": f"规则引擎API调用异常: {str(e)}"
             }
         except Exception as e:
-            # 记录API调用结果(其他异常)
+            # 记录API调用结果(其他异常)- 简化版
             end_time = datetime.now()
             call_id = f"rules_api_{config_name}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
             api_call_info = {
                 "call_id": call_id,
-                "timestamp": end_time.isoformat(),
-                "agent": "RulesEngineMetricCalculationAgent",
-                "api_endpoint": url,
-                "config_name": config_name,
-                "request": {
-                    "method": method,
-                    "url": url,
-                    "headers": headers,
-                    "json_data": json_data if 'json_data' in locals() else None,
-                    "start_time": start_time.isoformat()
-                },
                 "response": {
-                    "error": str(e),
-                    "end_time": end_time.isoformat(),
-                    "duration": (end_time - start_time).total_seconds()
-                },
-                "success": False
+                    "error": str(e)
+                }
             }
             self.api_calls.append(api_call_info)
 
+            # 保存API结果到文件 - 失败状态
+            api_results_dir = "api_results"
+            os.makedirs(api_results_dir, exist_ok=True)
+            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+            filename = f"{timestamp}_{call_id}_fail.json"
+            filepath = os.path.join(api_results_dir, filename)
+
+            try:
+                with open(filepath, 'w', encoding='utf-8') as f:
+                    json.dump(api_call_info, f, ensure_ascii=False, indent=2)
+                print(f"[RULES_API_RESULT] 保存规则引擎API结果文件: {filepath}")
+            except Exception as e:
+                print(f"[ERROR] 保存规则引擎API结果文件失败: {filepath}, 错误: {str(e)}")
+
             return {
                 "success": False,
                 "message": f"处理规则引擎API调用时发生错误: {str(e)}"
@@ -621,37 +583,22 @@ class RulesEngineMetricCalculationAgent:
                 try:
                     response_data = response.json()
 
-                    # 记录API调用结果
+                    # 记录API调用结果 - 简化版
                     end_time = datetime.now()
                     call_id = f"rules_api_{knowledge_id}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "RulesEngineMetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": knowledge_id,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data,
-                            "start_time": start_time.isoformat()
-                        },
-                        "response": {
-                            "status_code": response.status_code,
-                            "data": response_data,
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": True
+                        "response": response_data
                     }
                     self.api_calls.append(api_call_info)
 
-                    # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 保存API结果到文件 - 成功状态
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
                     timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
-                    filename = f"{timestamp}_{call_id}.json"
+                    filename = f"{timestamp}_{call_id}_success.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:
@@ -667,38 +614,26 @@ class RulesEngineMetricCalculationAgent:
                         "status_code": response.status_code
                     }
                 except json.JSONDecodeError:
-                    # 记录JSON解析失败的API调用
+                    # 记录JSON解析失败的API调用 - 简化版
                     end_time = datetime.now()
                     call_id = f"rules_api_{knowledge_id}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                     api_call_info = {
                         "call_id": call_id,
-                        "timestamp": end_time.isoformat(),
-                        "agent": "RulesEngineMetricCalculationAgent",
-                        "api_endpoint": url,
-                        "config_name": knowledge_id,
-                        "request": {
-                            "method": method,
-                            "url": url,
-                            "headers": headers,
-                            "json_data": json_data,
-                            "start_time": start_time.isoformat()
-                        },
                         "response": {
                             "status_code": response.status_code,
                             "data": response.text,
-                            "error": "JSON解析失败",
-                            "end_time": end_time.isoformat(),
-                            "duration": (end_time - start_time).total_seconds()
-                        },
-                        "success": False
+                            "error": "JSON解析失败"
+                        }
                     }
                     self.api_calls.append(api_call_info)
 
-                    # 保存API结果到文件
-                    api_results_dir = "api_results"
+                    # 保存API结果到文件 - 失败状态
+                    # 使用运行ID创建独立的文件夹
+                    run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                    api_results_dir = f"api_results_{run_id}"
                     os.makedirs(api_results_dir, exist_ok=True)
                     timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
-                    filename = f"{timestamp}_{call_id}.json"
+                    filename = f"{timestamp}_{call_id}_fail.json"
                     filepath = os.path.join(api_results_dir, filename)
 
                     try:
@@ -714,36 +649,25 @@ class RulesEngineMetricCalculationAgent:
                         "status_code": response.status_code
                     }
             else:
-                # 记录失败的API调用
+                # 记录失败的API调用 - 简化版
                 end_time = datetime.now()
                 call_id = f"rules_api_{knowledge_id}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
                 api_call_info = {
                     "call_id": call_id,
-                    "timestamp": end_time.isoformat(),
-                    "agent": "RulesEngineMetricCalculationAgent",
-                    "api_endpoint": url,
-                    "config_name": knowledge_id,
-                    "request": {
-                        "method": method,
-                        "url": url,
-                        "headers": headers,
-                        "json_data": json_data,
-                        "start_time": start_time.isoformat()
-                    },
                     "response": {
                         "status_code": response.status_code,
-                        "error": response.text,
-                        "end_time": end_time.isoformat(),
-                        "duration": (end_time - start_time).total_seconds()
-                    },
-                    "success": False
+                        "error": response.text
+                    }
                 }
                 self.api_calls.append(api_call_info)
 
-                # 保存API结果到文件
-                api_results_dir = "api_results"
+                # 保存API结果到文件 - 失败状态
+                # 使用运行ID创建独立的文件夹
+                run_id = os.environ.get('FLOW_RUN_ID', 'default')
+                api_results_dir = f"api_results_{run_id}"
                 os.makedirs(api_results_dir, exist_ok=True)
-                filename = f"{call_id}.json"
+                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+                filename = f"{timestamp}_{call_id}_fail.json"
                 filepath = os.path.join(api_results_dir, filename)
 
                 try:
@@ -760,35 +684,22 @@ class RulesEngineMetricCalculationAgent:
                 }
 
         except requests.exceptions.Timeout:
-            # 记录API调用结果(超时)
+            # 记录API调用结果(超时)- 简化版
             end_time = datetime.now()
             call_id = f"rules_api_{knowledge_id}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
             api_call_info = {
                 "call_id": call_id,
-                "timestamp": end_time.isoformat(),
-                "agent": "RulesEngineMetricCalculationAgent",
-                "api_endpoint": url,
-                "config_name": knowledge_id,
-                "request": {
-                    "method": method,
-                    "url": url,
-                    "headers": headers,
-                    "json_data": json_data if 'json_data' in locals() else None,
-                    "start_time": start_time.isoformat()
-                },
                 "response": {
-                    "error": "API调用超时",
-                    "end_time": end_time.isoformat(),
-                    "duration": (end_time - start_time).total_seconds()
-                },
-                "success": False
+                    "error": "API调用超时"
+                }
             }
             self.api_calls.append(api_call_info)
 
-            # 保存API结果到文件
+            # 保存API结果到文件 - 失败状态
             api_results_dir = "api_results"
             os.makedirs(api_results_dir, exist_ok=True)
-            filename = f"{call_id}.json"
+            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+            filename = f"{timestamp}_{call_id}_fail.json"
             filepath = os.path.join(api_results_dir, filename)
 
             try:
@@ -803,35 +714,22 @@ class RulesEngineMetricCalculationAgent:
                 "message": "规则引擎API调用超时"
             }
         except requests.exceptions.RequestException as e:
-            # 记录API调用结果(请求异常)
+            # 记录API调用结果(请求异常)- 简化版
             end_time = datetime.now()
             call_id = f"rules_api_{knowledge_id}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
             api_call_info = {
                 "call_id": call_id,
-                "timestamp": end_time.isoformat(),
-                "agent": "RulesEngineMetricCalculationAgent",
-                "api_endpoint": url,
-                "config_name": knowledge_id,
-                "request": {
-                    "method": method,
-                    "url": url,
-                    "headers": headers,
-                    "json_data": json_data if 'json_data' in locals() else None,
-                    "start_time": start_time.isoformat()
-                },
                 "response": {
-                    "error": str(e),
-                    "end_time": end_time.isoformat(),
-                    "duration": (end_time - start_time).total_seconds()
-                },
-                "success": False
+                    "error": str(e)
+                }
             }
             self.api_calls.append(api_call_info)
 
-            # 保存API结果到文件
+            # 保存API结果到文件 - 失败状态
             api_results_dir = "api_results"
             os.makedirs(api_results_dir, exist_ok=True)
-            filename = f"{call_id}.json"
+            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+            filename = f"{timestamp}_{call_id}_fail.json"
             filepath = os.path.join(api_results_dir, filename)
 
             try:
@@ -846,35 +744,22 @@ class RulesEngineMetricCalculationAgent:
                 "message": f"规则引擎API调用异常: {str(e)}"
             }
         except Exception as e:
-            # 记录API调用结果(其他异常)
+            # 记录API调用结果(其他异常)- 简化版
             end_time = datetime.now()
             call_id = f"rules_api_{knowledge_id}_{'{:.2f}'.format((end_time - start_time).total_seconds())}"
             api_call_info = {
                 "call_id": call_id,
-                "timestamp": end_time.isoformat(),
-                "agent": "RulesEngineMetricCalculationAgent",
-                "api_endpoint": url,
-                "config_name": knowledge_id,
-                "request": {
-                    "method": method,
-                    "url": url,
-                    "headers": headers,
-                    "json_data": json_data if 'json_data' in locals() else None,
-                    "start_time": start_time.isoformat()
-                },
                 "response": {
-                    "error": str(e),
-                    "end_time": end_time.isoformat(),
-                    "duration": (end_time - start_time).total_seconds()
-                },
-                "success": False
+                    "error": str(e)
+                }
             }
             self.api_calls.append(api_call_info)
 
-            # 保存API结果到文件
+            # 保存API结果到文件 - 失败状态
             api_results_dir = "api_results"
             os.makedirs(api_results_dir, exist_ok=True)
-            filename = f"{call_id}.json"
+            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+            filename = f"{timestamp}_{call_id}_fail.json"
             filepath = os.path.join(api_results_dir, filename)
 
             try:

+ 203 - 0
llmops/batch_runner.py

@@ -0,0 +1,203 @@
+#!/usr/bin/env python3
+"""
+批量运行器 - 批量执行Complete Agent Flow
+========================================
+
+此脚本可以批量运行多次完整的智能体工作流,每次运行会创建独立的日志文件夹。
+
+使用方法:
+    python batch_runner.py
+
+配置参数:
+    - 运行次数: RUNS = 10
+    - 行业: INDUSTRY = "农业"
+    - 数据文件: DATA_FILE = "data_files/交易流水样例数据.csv"
+    - 查询问题: QUESTION = "请生成一份详细的农业经营贷流水分析报告..."
+
+文件夹结构:
+    api_results_1/     # 第一次运行的日志
+    api_results_2/     # 第二次运行的日志
+    ...
+    api_results_10/    # 第十次运行的日志
+
+作者: Big Agent Team
+版本: 1.0.0
+创建时间: 2024-12-20
+"""
+
+import asyncio
+import os
+from datetime import datetime
+from typing import List, Dict, Any
+
+import sys
+import os
+
+# 添加项目根目录到路径,以便导入config
+current_dir = os.path.dirname(os.path.abspath(__file__))
+parent_dir = os.path.dirname(current_dir)
+sys.path.insert(0, parent_dir)
+
+# 根据执行方式选择导入方式
+if __name__ == "__main__":
+    # 直接执行文件时,使用绝对导入
+    from llmops.complete_agent_flow_rule import run_complete_agent_flow
+    from llmops.agents.data_manager import DataManager
+else:
+    # 作为模块导入时,使用相对导入
+    from .complete_agent_flow_rule import run_complete_agent_flow
+    from .agents.data_manager import DataManager
+
+import config
+
+# ========== 配置参数 ==========
+RUNS = 2  # 运行次数
+INDUSTRY = "农业"  # 行业
+DATA_FILE = "data_files/交易流水样例数据.csv"  # 数据文件路径
+QUESTION = "请生成一份详细的农业经营贷流水分析报告,需要包含:1.总收入和总支出统计 2.收入笔数和支出笔数 3.各类型收入支出占比分析 4.交易对手收入支出TOP3排名 5.按月份的收入支出趋势分析 6.账户数量和交易时间范围统计 7.资金流入流出月度统计等全面指标"  # 分析查询
+# ==============================
+
+
+async def run_single_flow(run_id: str, question: str, industry: str, data: List[Dict[str, Any]], file_name: str) -> Dict[str, Any]:
+    """
+    运行单个工作流实例
+
+    Args:
+        run_id: 运行ID
+        question: 用户查询
+        industry: 行业
+        data: 数据集
+        file_name: 文件名
+
+    Returns:
+        运行结果
+    """
+    print(f"\n{'='*60}")
+    print(f"🚀 开始运行 #{run_id}")
+    print(f"📁 日志文件夹: api_results_{run_id}")
+    print(f"{'='*60}")
+
+    try:
+        result = await run_complete_agent_flow(
+            question=question,
+            industry=industry,
+            data=data,
+            file_name=file_name,
+            api_key=config.DEEPSEEK_API_KEY,
+            session_id=f"batch-run-{run_id}",
+            run_id=run_id
+        )
+
+        if result.get('success'):
+            summary = result.get('execution_summary', {})
+            print(f"✅ 运行 #{run_id} 成功完成")
+            print(f"   规划步骤: {summary.get('planning_steps', 0)}")
+            print(f"   指标计算: {summary.get('metrics_computed', 0)}")
+        else:
+            print(f"❌ 运行 #{run_id} 失败: {result.get('error', '未知错误')}")
+
+        return result
+
+    except Exception as e:
+        print(f"❌ 运行 #{run_id} 发生异常: {e}")
+        return {
+            "success": False,
+            "error": str(e),
+            "run_id": run_id
+        }
+
+
+async def run_batch(runs: int, question: str, industry: str, data_file: str):
+    """
+    批量运行工作流
+
+    Args:
+        runs: 运行次数
+        question: 用户查询
+        industry: 行业
+        data_file: 数据文件路径
+    """
+    print("🚀 批量运行器启动")
+    print(f"📊 计划运行次数: {runs}")
+    print(f"🏭 行业: {industry}")
+    print(f"📁 数据文件: {data_file}")
+    print(f"❓ 查询: {question}")
+    print(f"{'='*80}")
+
+    # 检查API密钥
+    if not config.DEEPSEEK_API_KEY:
+        print("❌ 未找到API密钥,请检查config.py")
+        return
+
+    # 加载数据
+    try:
+        # 如果是相对路径,从项目根目录查找
+        if not os.path.isabs(data_file):
+            data_file = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), data_file)
+        data = DataManager.load_data_from_csv_file(data_file)
+        print(f"📊 数据加载成功: {len(data)} 条记录")
+    except Exception as e:
+        print(f"❌ 数据加载失败: {e}")
+        return
+
+    # 运行结果统计
+    successful_runs = 0
+    failed_runs = 0
+    results = []
+
+    # 逐个运行
+    for i in range(1, runs + 1):
+        run_id = str(i)
+        result = await run_single_flow(run_id, question, industry, data, os.path.basename(data_file))
+
+        results.append(result)
+
+        if result.get('success'):
+            successful_runs += 1
+        else:
+            failed_runs += 1
+
+        # 添加短暂延迟,避免API调用过于频繁
+        if i < runs:  # 最后一次不需要延迟
+            await asyncio.sleep(1)
+
+    # 输出统计结果
+    print(f"\n{'='*80}")
+    print("📊 批量运行完成统计")
+    print(f"{'='*80}")
+    print(f"总运行次数: {runs}")
+    print(f"成功次数: {successful_runs}")
+    print(f"失败次数: {failed_runs}")
+    print(f"成功率: {successful_runs/runs*100:.1f}%")
+
+    # 显示各运行的日志文件夹
+    print(f"\n📁 日志文件夹列表:")
+    for i in range(1, runs + 1):
+        folder_name = f"api_results_{i}"
+        status = "✅" if results[i-1].get('success') else "❌"
+        print(f"  {status} {folder_name}")
+
+    print("\n🎉 批量运行完成!")
+    print(f"💡 提示: 每次运行的完整日志保存在对应的 api_results_[数字] 文件夹中")
+
+
+def main():
+    """主函数"""
+    print("🚀 使用配置参数运行批量任务")
+    print(f"📊 运行次数: {RUNS}")
+    print(f"🏭 行业: {INDUSTRY}")
+    print(f"📁 数据文件: {DATA_FILE}")
+    print(f"❓ 查询: {QUESTION[:50]}...")
+    print("-" * 80)
+
+    # 运行批量任务
+    asyncio.run(run_batch(
+        runs=RUNS,
+        question=QUESTION,
+        industry=INDUSTRY,
+        data_file=DATA_FILE
+    ))
+
+
+if __name__ == "__main__":
+    main()

+ 15 - 61
llmops/complete_agent_flow_rule.py

@@ -32,7 +32,7 @@ from typing import Dict, Any, List
 from datetime import datetime
 from langgraph.graph import StateGraph, START, END
 
-from workflow_state import (
+from .workflow_state import (
     IntegratedWorkflowState,
     create_initial_integrated_state,
     get_calculation_progress,
@@ -40,28 +40,32 @@ from workflow_state import (
     update_state_with_planning_decision,
     update_state_with_data_classified,
     convert_numpy_types,
-
 )
-from llmops.agents.outline_agent import  generate_report_outline
-from llmops.agents.planning_agent import  plan_next_action
-from llmops.agents.rules_engine_metric_calculation_agent import RulesEngineMetricCalculationAgent
-from llmops.agents.data_manager import DataManager
+from .agents.outline_agent import generate_report_outline
+from .agents.planning_agent import plan_next_action
+from .agents.rules_engine_metric_calculation_agent import RulesEngineMetricCalculationAgent
+from .agents.data_manager import DataManager
 import os
-from llmops.agents.data_classify_agent import data_classify
+from .agents.data_classify_agent import data_classify
 
 class CompleteAgentFlow:
     """完整的智能体工作流"""
 
-    def __init__(self, api_key: str, base_url: str = "https://api.deepseek.com"):
+    def __init__(self, api_key: str, base_url: str = "https://api.deepseek.com", run_id: str = None):
         """
         初始化完整的工作流
 
         Args:
             api_key: DeepSeek API密钥
             base_url: DeepSeek API基础URL
+            run_id: 运行ID,用于区分不同的运行实例(可选)
         """
         self.api_key = api_key
         self.base_url = base_url
+        self.run_id = run_id or "default"
+
+        # 设置环境变量,让所有agent使用统一的文件夹
+        os.environ['FLOW_RUN_ID'] = self.run_id
 
         # 初始规则引擎智能体
         self.rules_engine_agent = RulesEngineMetricCalculationAgent(api_key, base_url)
@@ -601,7 +605,7 @@ class CompleteAgentFlow:
 
 
 # 便捷函数
-async def run_complete_agent_flow(question: str, industry: str, data: List[Dict[str, Any]], file_name: str, api_key: str, session_id: str = None, use_rules_engine_only: bool = False, use_traditional_engine_only: bool = False) -> Dict[str, Any]:
+async def run_complete_agent_flow(question: str, industry: str, data: List[Dict[str, Any]], file_name: str, api_key: str, session_id: str = None, use_rules_engine_only: bool = False, use_traditional_engine_only: bool = False, run_id: str = None) -> Dict[str, Any]:
     """
     运行完整智能体工作流的便捷函数
 
@@ -613,60 +617,10 @@ async def run_complete_agent_flow(question: str, industry: str, data: List[Dict[
         session_id: 会话ID
         use_rules_engine_only: 是否只使用规则引擎指标计算
         use_traditional_engine_only: 是否只使用传统引擎指标计算
+        run_id: 运行ID,用于区分不同的运行实例
 
     Returns:
         工作流结果
     """
-    workflow = CompleteAgentFlow(api_key)
+    workflow = CompleteAgentFlow(api_key, run_id=run_id)
     return await workflow.run_workflow(question, industry, data, file_name, session_id, use_rules_engine_only, use_traditional_engine_only)
-
-
-# 主函数用于测试
-async def main():
-    """主函数:执行系统测试"""
-    print("🚀 执行CompleteAgentFlow系统测试")
-    print("=" * 50)
-
-    # 导入配置
-    import config
-
-    if not config.DEEPSEEK_API_KEY:
-        print("❌ 未找到API密钥")
-        return
-
-    # 行业
-    industry = "农业"
-
-    # 测试文件
-    file_name = "交易流水样例数据.csv"
-    curr_dir = os.path.dirname(os.path.abspath(__file__))
-    file_path = os.path.join(curr_dir, "..", "data_files", file_name)
-
-    # 加载测试数据集并展示两条样例
-    test_data = DataManager.load_data_from_csv_file(file_path)
-
-    print(f"📊 读取测试数据文件: {file_name} 数据, 加载 {len(test_data)} 条记录")
-    print(f"测试数据样例: {test_data[0:1]}")
-
-    # 执行测试
-    result = await run_complete_agent_flow(
-        question="请生成一份详细的农业经营贷流水分析报告,需要包含:1.总收入和总支出统计 2.收入笔数和支出笔数 3.各类型收入支出占比分析 4.交易对手收入支出TOP3排名 5.按月份的收入支出趋势分析 6.账户数量和交易时间范围统计 7.资金流入流出月度统计等全面指标",
-        industry = industry,
-        data=test_data,
-        file_name=file_name,
-        api_key=config.DEEPSEEK_API_KEY,
-        session_id="direct-test"
-    )
-
-    print(f"📋 结果: {'✅ 成功' if result.get('success') else '❌ 失败'}")
-
-    if result.get('success'):
-        summary = result.get('execution_summary', {})
-        print(f"   规划步骤: {summary.get('planning_steps', 0)}")
-        print(f"   指标计算: {summary.get('metrics_computed', 0)}")
-        print("🎉 测试成功!")
-    return result
-
-if __name__ == "__main__":
-    import asyncio
-    asyncio.run(main())

+ 1 - 0
requirements.txt

@@ -46,3 +46,4 @@ uuid_utils==0.12.0
 uvicorn==0.38.0
 xxhash==3.6.0
 zstandard==0.25.0
+python-dotenv==1.0.0