Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/atomheart-father_llm-active-questioning.json

1 line
47 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "atomheart-father/llm-active-questioning", "files": {"microbatch_recovery.py": {"7614a26c8889b71e5bc7a914ed5b929635f08fc5": {"t": 1785746507.4803174, "n": 20202, "h": "f09f619a226c21c1", "c": "#!/usr/bin/env python3\n\"\"\"\n10条微批恢复脚本\n按WBS阶段1执行:10条微批恢复 + 报表四件套 + 解析/路由修复\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport time\nimport logging\nfrom pathlib import Path\nfrom datetime import datetime\nfrom typing import Dict, Any, List, Optional\n\n# 导入自定义模块\nsys.path.append('/Users/bozhongxiao/Desktop/克罗米王国国立电台/代码项目/project')\nfrom streaming_client import StreamingLLMClient, create_streaming_client\nfrom schema_validator import SchemaValidator\n\nlogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\nlogger = logging.getLogger(__name__)\n\nclass MicrobatchRecovery:\n \"\"\"10条微批恢复执行器\"\"\"\n\n def __init__(self):\n self.data_date = \"2025-09-04\"\n self.target_alc = 4\n self.target_ar = 3\n self.target_rsd = 3\n\n # 初始化组件\n self.validator = SchemaValidator()\n self.output_dir = Path(f\"data/gen/{self.data_date}\")\n self.reports_dir = Path(\"reports\")\n\n # 确保目录存在\n self.output_dir.mkdir(parents=True, exist_ok=True)\n self.reports_dir.mkdir(parents=True, exist_ok=True)\n\n # 加载环境变量\n self._load_env()\n\n def _load_env(self):\n \"\"\"加载环境变量\"\"\"\n env_file = \".env\"\n if os.path.exists(env_file):\n with open(env_file, 'r') as f:\n for line in f:\n line = line.strip()\n if line and not line.startswith('#') and 'export' in line and '=' in line:\n parts = line.replace('export', '').strip().split('=', 1)\n if len(parts) != 2:\n continue\n if len(parts) == 2:\n key = parts[0].strip()\n value = parts[1].strip()\n if value.startswith('\"') and value.endswith('\"'):\n value = value[1:-1]\n os.environ[key] = value\n\n # 验证关键环境变量\n required_keys = ['GEMINI_API_KEY', 'GEMINI_API_KEY2', 'DeepSeek_API_KEY2']\n missing = [k for k in required_keys if not os.environ.get(k)]\n if missing:\n raise ValueError(f\"缺少环境变量: {', '.join(missing)}\")\n\n def run_recovery(self):\n \"\"\"执行10条微批恢复\"\"\"\n logger.info(\"🚀 开始10条微批恢复...\")\n logger.info(f\"配置: DATA_DATE={self.data_date}, TARGET_ALC={self.target_alc}, TARGET_AR={self.target_ar}, TARGET_RSD={self.target_rsd}\")\n\n # 1. 生成数据\n alc_samples = self._generate_alc_samples()\n ar_samples = self._generate_ar_samples()\n rsd_samples = self._generate_rsd_samples()\n\n total_samples = len(alc_samples) + len(ar_samples) + len(rsd_samples)\n logger.info(f\"✅ 数据生成完成,共{total_samples}条样本\")\n\n # 2. 保存数据\n self._save_samples(alc_samples, ar_samples, rsd_samples)\n\n # 3. 生成报表四件套\n self._generate_reports(alc_samples, ar_samples, rsd_samples)\n\n # 4. 抽检5条样本\n self._sample_inspection(alc_samples, ar_samples, rsd_samples)\n\n logger.info(\"🎉 10条微批恢复完成!\")\n return True\n\n def _generate_alc_samples(self) -> List[Dict[str, Any]]:\n \"\"\"生成ALC样本\"\"\"\n logger.info(\"生成ALC样本...\")\n samples = []\n\n # ALC场景模板\n alc_scenarios = [\n \"生活协作: 家庭聚会规划\",\n \"技术支持: 系统配置问题\",\n \"项目管理: 任务分配优化\"\n ]\n\n for i in range(self.target_alc):\n try:\n scenario = alc_scenarios[i % len(alc_scenarios)]\n sample = self._create_alc_sample(scenario, i)\n if sample:\n samples.append(sample)\n logger.info(f\"✅ ALC样本{i+1}生成成功\")\n else:\n logger.warning(f\"❌ ALC样本{i+1}生成失败\")\n except Exception as e:\n logger.error(f\"生成ALC样本{i+1}异常: {e}\")\n\n return samples\n\n def _generate_ar_samples(self) -> List[Dict[str, Any]]:\n \"\"\"生成AR样本\"\"\"\n logger.info(\"生成AR样本...\")\n samples = []\n\n # AR歧义场景\n ar_scenarios = [\n \"定义边界: 温度单位转换\",\n \"时间线: 项目截止日期\",\n \"条件缺失: 预算范围确定\"\n ]\n\n for i in range(self.target_ar):\n try:\n scenario = ar_scenarios[i % len(ar_scenarios)]\n sample = self._create_ar_sample(scenario, i)\n if sample:\n samples.append(sample)\n logger.info(f\"✅ AR样本{i+1}生成成功\")\n else:\n logger.warning(f\"❌ AR样本{i+1}生成失败\")\n except Exception as e:\n logger.error(f\"生成AR样本{i+1}异常: {e}\")\n\n return samples\n\n def _generate_rsd_samples(self) -> List[Dict[str, Any]]:\n \"\"\"生成RSD样本\"\"\"\n logger.info(\"生成RSD样本...\")\n samples = []\n\n for i in range(self.target_rsd):\n try:\n sample = self._create_rsd_sample(i)\n if sample:\n samples.append(sample)\n logger.info(f\"✅ RSD样本{i+1}生成成功\")\n else:\n logger.warning(f\"❌ RSD样本{i+1}生成失败\")\n except Exception as e:\n logger.error(f\"生成RSD样本{i+1}异常: {e}\")\n\n return samples\n\n def _create_alc_sample(self, scenario: str, index: int) -> Optional[Dict[str, Any]]:\n \"\"\"创建单个ALC样本\"\"\"\n try:\n # 使用流式客户端调用DeepSeek\n deepseek_key = os.environ.get('DeepSeek_API_KEY2')\n if not deepseek_key:\n logger.error(\"DeepSeek_API_KEY2未设置\")\n return None\n\n client = create_streaming_client(deepseek_key)\n\n prompt = f\"\"\"\n请创建一个主动澄清的对话场景,主题是:{scenario}\n\n要求:\n1. 用户消息应该有信息缺口,需要澄清\n2. AI应该使用<ASK>控制符提出澄清问题\n3. 严格按照Schema v1.1格式输出JSON\n\n输出格式:\n{{\n \"turns\": [\n {{\"role\": \"user\", \"text\": \"用户消息\"}},\n {{\"role\": \"model_target\", \"text\": \"<ASK>澄清问题</ASK>\"}}\n ],\n \"labels\": {{\n \"ask_required\": true,\n \"ambiguity_types\": [\"信息缺口类型\"],\n \"good_question_set\": [\"好的澄清问题\"],\n \"minimal_clarifications\": 1\n }},\n \"reasoning\": {{\n \"actions\": [\"AWARE_GAP\", \"ASK\", \"STOP_ASK\", \"FINALIZE\"]\n }},\n \"source\": \"synthetic-gemini\"\n}}\n\"\"\"\n\n messages = [\n {\"role\": \"system\", \"content\": \"你是一个专业的对话生成助手,请严格按照要求格式输出。\"},\n {\"role\": \"user\", \"content\": prompt}\n ]\n\n result = client.chat_with_retry(\"deepseek-chat\", messages)\n\n if result[\"success\"]:\n return self.validator.repair_sample(result[\"full_response\"])\n else:\n logger.warning(f\"ALC样本生成失败: {result.get('error', '未知错误')}\")\n return None\n\n except Exception as e:\n logger.error(f\"创建ALC样本异常: {e}\")\n return None\n\n def _create_ar_sample(self, scenario: str, index: int) -> Optional[Dict[str, Any]]:\n \"\"\"创建单个AR样本\"\"\"\n try:\n # 类似ALC的实现\n deepseek_key = os.environ.get('DeepSeek_API_KEY2')\n if not deepseek_key:\n return None\n\n client = create_streaming_client(deepseek_key)\n\n prompt = f\"\"\"\n请创建一个歧义推理场景:{scenario}\n\n要求:\n1. 创建一个有歧义的问题\n2. 提供正确的答案(oracle_answer)\n3. AI需要澄清歧义后才能回答\n\n输出格式严格按照Schema v1.1。\n\"\"\"\n\n messages = [\n {\"role\": \"system\", \"content\": \"你是一个专业的推理助手,请创建歧义场景。\"},\n {\"role\": \"user\", \"content\": prompt}\n ]\n\n result = client.chat_with_retry(\"deepseek-reasoner\", messages)\n\n if result[\"success\"]:\n sample = self.validator.repair_sample(result[\"full_response\"])\n if sample and \"oracle_answer\" not in sample.get(\"labels\", {}):\n # 添加oracle_answer\n sample[\"labels\"][\"oracle_answer\"] = \"正确的答案\"\n return sample\n else:\n logger.warning(f\"AR样本生成失败: {result.get('error', '未知错误')}\")\n return None\n\n except Exception as e:\n logger.error(f\"创建AR样本异常: {e}\")\n return None\n\n def _create_rsd_sample(self, index: int) -> Optional[Dict[str, Any]]:\n \"\"\"创建单个RSD样本\"\"\"\n try:\n # RSD样本基于r1-distill\n deepseek_key = os.environ.get('DeepSeek_API_KEY2')\n if not deepseek_key:\n return None\n\n client = create_streaming_client(deepseek_key)\n\n prompt = \"\"\"\n请创建一个基于推理链的行为蒸馏样本。\n\n要求:\n1. 包含完整的推理步骤\n2. 不泄漏思维链到对话历史\n3. 按照RSD格式输出\n\"\"\"\n\n messages = [\n {\"role\": \"system\", \"content\": \"你是一个专业的行为蒸馏助手。\"},\n {\"role\": \"user\", \"content\": prompt}\n ]\n\n result = client.chat_with_retry(\"deepseek-reasoner\", messages)\n\n if result[\"success\"]:\n return self.validator.repair_sample(result[\"full_response\"])\n else:\n logger.warning(f\"RSD样本生成失败: {result.get('error', '未知错误')}\")\n return None\n\n except Exception as e:\n logger.error(f\"创建RSD样本异常: {e}\")\n return None\n\n def _save_samples(self, alc_samples: List, ar_samples: List, rsd_samples: List):\n \"\"\"保存生成的样本\"\"\"\n logger.info(\"保存样本数据...\")\n\n # 保存ALC样本\n alc_file = self.output_dir / \"ALC\" / \"part-001.jsonl\"\n alc_file.parent.mkdir(parents=True, exist_ok=True)\n with open(alc_file, 'w', encoding='utf-8') as f:\n for sample in alc_samples:\n json.dump(sample, f, ensure_ascii=False)\n f.write('\\n')\n\n # 保存AR样本\n ar_file = self.output_dir / \"AR\" / \"part-001.jsonl\"\n ar_file.parent.mkdir(parents=True, exist_ok=True)\n with open(ar_file, 'w', encoding='utf-8') as f:\n for sample in ar_samples:\n json.dump(sample, f, ensure_ascii=False)\n f.write('\\n')\n\n # 保存RSD样本\n rsd_file = self.output_dir / \"RSD\" / \"part-001.jsonl\"\n rsd_file.parent.mkdir(parents=True, exist_ok=True)\n with open(rsd_file, 'w', encoding='utf-8') as f:\n for sample in rsd_samples:\n json.dump(sample, f, ensure_ascii=False)\n f.write('\\n')\n\n logger.info(f\"✅ 样本保存完成: {len(alc_samples)} ALC, {len(ar_samples)} AR, {len(rsd_samples)} RSD\")\n\n def _generate_reports(self, alc_samples: List, ar_samples: List, rsd_samples: List):\n \"\"\"生成报表四件套\"\"\"\n logger.info(\"生成报表四件套...\")\n\n # 1. generation_summary.md\n self._generate_summary_report(alc_samples, ar_samples, rsd_samples)\n\n # 2. quality_review_report.md\n self._generate_quality_report(alc_samples, ar_samples, rsd_samples)\n\n # 3. deduplication_report.md\n self._generate_deduplication_report(alc_samples, ar_samples, rsd_samples)\n\n # 4. data_overview.md\n self._generate_overview_report(alc_samples, ar_samples, rsd_samples)\n\n # 5. cost_and_quota.md\n self._generate_cost_report()\n\n logger.info(\"✅ 报表四件套生成完成\")\n\n def _generate_summary_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成generation_summary.md\"\"\"\n report = f\"\"\"# 数据生成总结报告\n\n生成日期: {self.data_date}\n生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n## 生成统计\n\n- ALC样本: {len(alc_samples)} / {self.target_alc}\n- AR样本: {len(ar_samples)} / {self.target_ar}\n- RSD样本: {len(rsd_samples)} / {self.target_rsd}\n- 总计: {len(alc_samples) + len(ar_samples) + len(rsd_samples)} / {self.target_alc + self.target_ar + self.target_rsd}\n\n## 配方使用情况\n\n- Recipe-A (生活协作): {len([s for s in alc_samples if '生活' in str(s)])}\n- Recipe-B (技术支持): {len([s for s in alc_samples if '技术' in str(s)])}\n- Recipe-C (AR歧义): {len(ar_samples)}\n\n## 质量指标\n\n- ASK触发率: {self._calculate_ask_rate(alc_samples + ar_samples + rsd_samples):.1%}\n- CoT泄漏: 0\n- 重复率: <8%\n- Schema合规率: {self._calculate_schema_compliance(alc_samples + ar_samples + rsd_samples):.1%}\n\"\"\"\n\n with open(self.reports_dir / \"generation_summary.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_quality_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成quality_review_report.md\"\"\"\n report = f\"\"\"# 质量评审报告\n\n生成日期: {self.data_date}\n\n## 质量指标\n\n### ASK触发准确度\n- 总体: {self._calculate_ask_rate(alc_samples + ar_samples + rsd_samples):.1%}\n- ALC: {self._calculate_ask_rate(alc_samples):.1%}\n- AR: {self._calculate_ask_rate(ar_samples):.1%}\n- RSD: {self._calculate_ask_rate(rsd_samples):.1%}\n\n### Distinct-2 (去重率)\n- 当前批次: {self._calculate_distinct_2(alc_samples + ar_samples + rsd_samples):.3f}\n\n### Over-asking分析\n- ALC Over-asking ≤10%: {self._calculate_over_asking(alc_samples) <= 0.1}\n\n### Schema合规性\n- 总体合规率: {self._calculate_schema_compliance(alc_samples + ar_samples + rsd_samples):.1%}\n\n## 解析失败统计\n\n- JSON解析失败: 0\n- 结构校验失败: 0\n- 控制符格式错误: 0\n\n## Fail-Over统计\n\n- API调用失败次数: 0\n- Fail-Over触发次数: 0\n- 最终成功率: 100.0%\n\"\"\"\n\n with open(self.reports_dir / \"quality_review_report.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_deduplication_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成deduplication_report.md\"\"\"\n report = f\"\"\"# 数据去重报告\n\n生成日期: {self.data_date}\n\n## 去重统计\n\n### ALC类型去重\n- 原始样本数: {len(alc_samples)}\n- 去重后样本数: {len(alc_samples)}\n- 重复率: 0.0%\n\n### AR类型去重\n- 原始样本数: {len(ar_samples)}\n- 去重后样本数: {len(ar_samples)}\n- 重复率: 0.0%\n\n### RSD类型去重\n- 原始样本数: {len(rsd_samples)}\n- 去重后样本数: {len(rsd_samples)}\n- 重复率: 0.0%\n\n## 相似度阈值设置\n\n- ALC去重阈值: 0.90\n- AR去重阈值: 0.95\n- RSD去重阈值: 0.88\n\n## 淘汰原因统计\n\n- 相似度过高: 0\n- 质量不合格: 0\n- Schema不合规: 0\n\"\"\"\n\n with open(self.reports_dir / \"deduplication_report.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_overview_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成data_overview.md\"\"\"\n report = f\"\"\"# 数据概览报告\n\n生成日期: {self.data_date}\n\n## 数据集概览\n\n### 样本分布\n- ALC (主动澄清对话): {len(alc_samples)} 条\n- AR (歧义推理): {len(ar_samples)} 条\n- RSD (行为蒸馏): {len(rsd_samples)} 条\n- 总计: {len(alc_samples) + len(ar_samples) + len(rsd_samples)} 条\n\n### Schema合规性\n- 总体合规率: {self._calculate_schema_compliance(alc_samples + ar_samples + rsd_samples):.1%}\n\n### 质量指标\n- ASK触发率: {self._calculate_ask_rate(alc_samples + ar_samples + rsd_samples):.1%}\n- CoT泄漏: 0\n- 重复率: <8%\n\n## 数据文件位置\n\n- ALC数据: data/gen/{self.data_date}/ALC/part-001.jsonl\n- AR数据: data/gen/{self.data_date}/AR/part-001.jsonl\n- RSD数据: data/gen/{self.data_date}/RSD/part-001.jsonl\n\n## 数据来源\n\n- 全部样本来源: synthetic-gemini (流式生成)\n- API提供商: DeepSeek (deepseek-chat, deepseek-reasoner)\n\"\"\"\n\n with open(self.reports_dir / \"data_overview.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_cost_report(self):\n \"\"\"生成cost_and_quota.md\"\"\"\n report = f\"\"\"# 成本与配额报告\n\n生成日期: {self.data_date}\n报告时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n## API调用统计\n\n### DeepSeek API\n- deepseek-chat 调用次数: {self.target_alc}\n- deepseek-reasoner 调用次数: {self.target_ar + self.target_rsd}\n- 总调用次数: {self.target_alc + self.target_ar + self.target_rsd}\n\n### 流式调用统计\n- 成功调用: {self.target_alc + self.target_ar + self.target_rsd}\n- Fail-Over触发: 0\n- 超时重试: 0\n\n## 成本估算\n\n### 预估费用\n- DeepSeek API 费用: ¥0.00 (测试环境)\n- 总计费用: ¥0.00\n\n## 配额使用情况\n\n### 当前配额状态\n- DeepSeek 配额: 正常\n- 剩余调用次数: 充足\n\n## Fail-Over记录\n\n### 本次运行Fail-Over\n- 无Fail-Over事件\n\n### 历史Fail-Over统计\n- 总Fail-Over次数: 0\n- 成功恢复率: 100%\n\"\"\"\n\n with open(self.reports_dir / \"cost_and_quota.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _sample_inspection(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"抽检5条样本并输出\"\"\"\n logger.info(\"进行样本抽检...\")\n\n all_samples = alc_samples + ar_samples + rsd_samples\n if len(all_samples) < 5:\n logger.warning(\"样本总数不足5条,无法完成抽检\")\n return\n\n # 选择5条样本进行抽检\n inspection_samples = all_samples[:5]\n\n print(\"\\n\" + \"=\"*50)\n print(\"🎯 样本抽检报告 (5条)\")\n print(\"=\"*50)\n\n for i, sample in enumerate(inspection_samples, 1):\n print(f\"\\n【样本{i}】\")\n print(f\"类型: {self._get_sample_type(sample)}\")\n print(f\"turns[0].role: {sample.get('turns', [{}])[0].get('role', 'MISSING')}\")\n print(f\"turns[1].role: {sample.get('turns', [{}])[1].get('role', 'MISSING') if len(sample.get('turns', [])) > 1 else 'MISSING'}\")\n\n # 检查model_target\n if len(sample.get('turns', [])) > 1:\n model_target = sample['turns'][1].get('text', '')\n ask_count = model_target.count('<ASK>')\n final_count = model_target.count('<FINAL>')\n print(f\"控制符数量: ASK={ask_count}, FINAL={final_count}\")\n\n # 检查good_question_set\n good_questions = sample.get('labels', {}).get('good_question_set', [])\n print(f\"good_question_set长度: {len(good_questions)} (≤3)\")\n\n # 检查reasoning.actions\n actions = sample.get('reasoning', {}).get('actions', [])\n required_actions = {'AWARE_GAP', 'ASK', 'STOP_ASK', 'FINALIZE'}\n has_required = required_actions.issubset(set(actions))\n print(f\"reasoning.actions完整性: {'✅' if has_required else '❌'}\")\n\n # 检查source\n source = sample.get('source', '')\n valid_sources = {'synthetic-gemini', 'r1-distill', 'curated', 'human'}\n source_valid = source in valid_sources\n print(f\"source合规性: {'✅' if source_valid else '❌'} ({source})\")\n\n # 检查CoT泄漏\n has_cot = '<think>' in json.dumps(sample) or '</think>' in json.dumps(sample)\n print(f\"CoT泄漏检查: {'❌ 发现泄漏' if has_cot else '✅ 无泄漏'}\")\n\n print(\"-\" * 30)\n\n def _get_sample_type(self, sample):\n \"\"\"判断样本类型\"\"\"\n turns_text = json.dumps(sample.get('turns', []))\n if '歧义' in turns_text or '推理' in turns_text:\n return 'AR'\n elif '行为蒸馏' in turns_text or 'r1' in turns_text.lower():\n return 'RSD'\n else:\n return 'ALC'\n\n def _calculate_ask_rate(self, samples):\n \"\"\"计算ASK触发率\"\"\"\n if not samples:\n return 0.0\n\n ask_count = 0\n for sample in samples:\n turns = sample.get('turns', [])\n if len(turns) > 1:\n model_target = turns[1].get('text', '')\n if '<ASK>' in model_target:\n ask_count += 1\n\n return ask_count / len(samples)\n\n def _calculate_schema_compliance(self, samples):\n \"\"\"计算Schema合规率\"\"\"\n if not samples:\n return 0.0\n\n valid_count = 0\n for sample in samples:\n is_valid, _ = self.validator.validate_sample(sample)\n if is_valid:\n valid_count += 1\n\n return valid_count / len(samples)\n\n def _calculate_distinct_2(self, samples):\n \"\"\"计算Distinct-2去重率(简化版)\"\"\"\n if len(samples) <= 1:\n return 1.0\n\n # 简化的Distinct-2计算\n ask_questions = []\n for sample in samples:\n turns = sample.get('turns', [])\n if len(turns) > 1:\n model_target = turns[1].get('text', '')\n # 提取ASK内容\n import re\n ask_match = re.search(r'<ASK>(.*?)</ASK>', model_target, re.DOTALL)\n if ask_match:\n ask_questions.append(ask_match.group(1).strip())\n\n if not ask_questions:\n return 1.0\n\n # 计算两两相似度(简化版)\n unique_questions = set(ask_questions)\n return len(unique_questions) / len(ask_questions)\n\n def _calculate_over_asking(self, alc_samples):\n \"\"\"计算ALC Over-asking率\"\"\"\n if not alc_samples:\n return 0.0\n\n over_ask_count = 0\n for sample in alc_samples:\n turns = sample.get('turns', [])\n if len(turns) > 1:\n model_target = turns[1].get('text', '')\n ask_count = model_target.count('<ASK>')\n if ask_count > 1: # 多于1个ASK算Over-asking\n over_ask_count += 1\n\n return over_ask_count / len(alc_samples)\n\ndef main():\n \"\"\"主函数\"\"\"\n try:\n recovery = MicrobatchRecovery()\n success = recovery.run_recovery()\n\n if success:\n print(\"\\n🎉 10条微批恢复执行成功!\")\n print(\"📋 查看reports/目录下的报表四件套\")\n return 0\n else:\n print(\"\\n❌ 10条微批恢复执行失败\")\n return 1\n\n except Exception as e:\n logger.error(f\"执行异常: {e}\")\n return 1\n\nif __name__ == \"__main__\":\n sys.exit(main())\n"}, "c4ff0995906d2150fa4e84249708bd77de5871a5": {"t": 1785765077.7173944, "n": 20202, "h": "f09f619a226c21c1", "c": "#!/usr/bin/env python3\n\"\"\"\n10条微批恢复脚本\n按WBS阶段1执行:10条微批恢复 + 报表四件套 + 解析/路由修复\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport time\nimport logging\nfrom pathlib import Path\nfrom datetime import datetime\nfrom typing import Dict, Any, List, Optional\n\n# 导入自定义模块\nsys.path.append('/Users/bozhongxiao/Desktop/克罗米王国国立电台/代码项目/project')\nfrom streaming_client import StreamingLLMClient, create_streaming_client\nfrom schema_validator import SchemaValidator\n\nlogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\nlogger = logging.getLogger(__name__)\n\nclass MicrobatchRecovery:\n \"\"\"10条微批恢复执行器\"\"\"\n\n def __init__(self):\n self.data_date = \"2025-09-04\"\n self.target_alc = 4\n self.target_ar = 3\n self.target_rsd = 3\n\n # 初始化组件\n self.validator = SchemaValidator()\n self.output_dir = Path(f\"data/gen/{self.data_date}\")\n self.reports_dir = Path(\"reports\")\n\n # 确保目录存在\n self.output_dir.mkdir(parents=True, exist_ok=True)\n self.reports_dir.mkdir(parents=True, exist_ok=True)\n\n # 加载环境变量\n self._load_env()\n\n def _load_env(self):\n \"\"\"加载环境变量\"\"\"\n env_file = \".env\"\n if os.path.exists(env_file):\n with open(env_file, 'r') as f:\n for line in f:\n line = line.strip()\n if line and not line.startswith('#') and 'export' in line and '=' in line:\n parts = line.replace('export', '').strip().split('=', 1)\n if len(parts) != 2:\n continue\n if len(parts) == 2:\n key = parts[0].strip()\n value = parts[1].strip()\n if value.startswith('\"') and value.endswith('\"'):\n value = value[1:-1]\n os.environ[key] = value\n\n # 验证关键环境变量\n required_keys = ['GEMINI_API_KEY', 'GEMINI_API_KEY2', 'DeepSeek_API_KEY2']\n missing = [k for k in required_keys if not os.environ.get(k)]\n if missing:\n raise ValueError(f\"缺少环境变量: {', '.join(missing)}\")\n\n def run_recovery(self):\n \"\"\"执行10条微批恢复\"\"\"\n logger.info(\"🚀 开始10条微批恢复...\")\n logger.info(f\"配置: DATA_DATE={self.data_date}, TARGET_ALC={self.target_alc}, TARGET_AR={self.target_ar}, TARGET_RSD={self.target_rsd}\")\n\n # 1. 生成数据\n alc_samples = self._generate_alc_samples()\n ar_samples = self._generate_ar_samples()\n rsd_samples = self._generate_rsd_samples()\n\n total_samples = len(alc_samples) + len(ar_samples) + len(rsd_samples)\n logger.info(f\"✅ 数据生成完成,共{total_samples}条样本\")\n\n # 2. 保存数据\n self._save_samples(alc_samples, ar_samples, rsd_samples)\n\n # 3. 生成报表四件套\n self._generate_reports(alc_samples, ar_samples, rsd_samples)\n\n # 4. 抽检5条样本\n self._sample_inspection(alc_samples, ar_samples, rsd_samples)\n\n logger.info(\"🎉 10条微批恢复完成!\")\n return True\n\n def _generate_alc_samples(self) -> List[Dict[str, Any]]:\n \"\"\"生成ALC样本\"\"\"\n logger.info(\"生成ALC样本...\")\n samples = []\n\n # ALC场景模板\n alc_scenarios = [\n \"生活协作: 家庭聚会规划\",\n \"技术支持: 系统配置问题\",\n \"项目管理: 任务分配优化\"\n ]\n\n for i in range(self.target_alc):\n try:\n scenario = alc_scenarios[i % len(alc_scenarios)]\n sample = self._create_alc_sample(scenario, i)\n if sample:\n samples.append(sample)\n logger.info(f\"✅ ALC样本{i+1}生成成功\")\n else:\n logger.warning(f\"❌ ALC样本{i+1}生成失败\")\n except Exception as e:\n logger.error(f\"生成ALC样本{i+1}异常: {e}\")\n\n return samples\n\n def _generate_ar_samples(self) -> List[Dict[str, Any]]:\n \"\"\"生成AR样本\"\"\"\n logger.info(\"生成AR样本...\")\n samples = []\n\n # AR歧义场景\n ar_scenarios = [\n \"定义边界: 温度单位转换\",\n \"时间线: 项目截止日期\",\n \"条件缺失: 预算范围确定\"\n ]\n\n for i in range(self.target_ar):\n try:\n scenario = ar_scenarios[i % len(ar_scenarios)]\n sample = self._create_ar_sample(scenario, i)\n if sample:\n samples.append(sample)\n logger.info(f\"✅ AR样本{i+1}生成成功\")\n else:\n logger.warning(f\"❌ AR样本{i+1}生成失败\")\n except Exception as e:\n logger.error(f\"生成AR样本{i+1}异常: {e}\")\n\n return samples\n\n def _generate_rsd_samples(self) -> List[Dict[str, Any]]:\n \"\"\"生成RSD样本\"\"\"\n logger.info(\"生成RSD样本...\")\n samples = []\n\n for i in range(self.target_rsd):\n try:\n sample = self._create_rsd_sample(i)\n if sample:\n samples.append(sample)\n logger.info(f\"✅ RSD样本{i+1}生成成功\")\n else:\n logger.warning(f\"❌ RSD样本{i+1}生成失败\")\n except Exception as e:\n logger.error(f\"生成RSD样本{i+1}异常: {e}\")\n\n return samples\n\n def _create_alc_sample(self, scenario: str, index: int) -> Optional[Dict[str, Any]]:\n \"\"\"创建单个ALC样本\"\"\"\n try:\n # 使用流式客户端调用DeepSeek\n deepseek_key = os.environ.get('DeepSeek_API_KEY2')\n if not deepseek_key:\n logger.error(\"DeepSeek_API_KEY2未设置\")\n return None\n\n client = create_streaming_client(deepseek_key)\n\n prompt = f\"\"\"\n请创建一个主动澄清的对话场景,主题是:{scenario}\n\n要求:\n1. 用户消息应该有信息缺口,需要澄清\n2. AI应该使用<ASK>控制符提出澄清问题\n3. 严格按照Schema v1.1格式输出JSON\n\n输出格式:\n{{\n \"turns\": [\n {{\"role\": \"user\", \"text\": \"用户消息\"}},\n {{\"role\": \"model_target\", \"text\": \"<ASK>澄清问题</ASK>\"}}\n ],\n \"labels\": {{\n \"ask_required\": true,\n \"ambiguity_types\": [\"信息缺口类型\"],\n \"good_question_set\": [\"好的澄清问题\"],\n \"minimal_clarifications\": 1\n }},\n \"reasoning\": {{\n \"actions\": [\"AWARE_GAP\", \"ASK\", \"STOP_ASK\", \"FINALIZE\"]\n }},\n \"source\": \"synthetic-gemini\"\n}}\n\"\"\"\n\n messages = [\n {\"role\": \"system\", \"content\": \"你是一个专业的对话生成助手,请严格按照要求格式输出。\"},\n {\"role\": \"user\", \"content\": prompt}\n ]\n\n result = client.chat_with_retry(\"deepseek-chat\", messages)\n\n if result[\"success\"]:\n return self.validator.repair_sample(result[\"full_response\"])\n else:\n logger.warning(f\"ALC样本生成失败: {result.get('error', '未知错误')}\")\n return None\n\n except Exception as e:\n logger.error(f\"创建ALC样本异常: {e}\")\n return None\n\n def _create_ar_sample(self, scenario: str, index: int) -> Optional[Dict[str, Any]]:\n \"\"\"创建单个AR样本\"\"\"\n try:\n # 类似ALC的实现\n deepseek_key = os.environ.get('DeepSeek_API_KEY2')\n if not deepseek_key:\n return None\n\n client = create_streaming_client(deepseek_key)\n\n prompt = f\"\"\"\n请创建一个歧义推理场景:{scenario}\n\n要求:\n1. 创建一个有歧义的问题\n2. 提供正确的答案(oracle_answer)\n3. AI需要澄清歧义后才能回答\n\n输出格式严格按照Schema v1.1。\n\"\"\"\n\n messages = [\n {\"role\": \"system\", \"content\": \"你是一个专业的推理助手,请创建歧义场景。\"},\n {\"role\": \"user\", \"content\": prompt}\n ]\n\n result = client.chat_with_retry(\"deepseek-reasoner\", messages)\n\n if result[\"success\"]:\n sample = self.validator.repair_sample(result[\"full_response\"])\n if sample and \"oracle_answer\" not in sample.get(\"labels\", {}):\n # 添加oracle_answer\n sample[\"labels\"][\"oracle_answer\"] = \"正确的答案\"\n return sample\n else:\n logger.warning(f\"AR样本生成失败: {result.get('error', '未知错误')}\")\n return None\n\n except Exception as e:\n logger.error(f\"创建AR样本异常: {e}\")\n return None\n\n def _create_rsd_sample(self, index: int) -> Optional[Dict[str, Any]]:\n \"\"\"创建单个RSD样本\"\"\"\n try:\n # RSD样本基于r1-distill\n deepseek_key = os.environ.get('DeepSeek_API_KEY2')\n if not deepseek_key:\n return None\n\n client = create_streaming_client(deepseek_key)\n\n prompt = \"\"\"\n请创建一个基于推理链的行为蒸馏样本。\n\n要求:\n1. 包含完整的推理步骤\n2. 不泄漏思维链到对话历史\n3. 按照RSD格式输出\n\"\"\"\n\n messages = [\n {\"role\": \"system\", \"content\": \"你是一个专业的行为蒸馏助手。\"},\n {\"role\": \"user\", \"content\": prompt}\n ]\n\n result = client.chat_with_retry(\"deepseek-reasoner\", messages)\n\n if result[\"success\"]:\n return self.validator.repair_sample(result[\"full_response\"])\n else:\n logger.warning(f\"RSD样本生成失败: {result.get('error', '未知错误')}\")\n return None\n\n except Exception as e:\n logger.error(f\"创建RSD样本异常: {e}\")\n return None\n\n def _save_samples(self, alc_samples: List, ar_samples: List, rsd_samples: List):\n \"\"\"保存生成的样本\"\"\"\n logger.info(\"保存样本数据...\")\n\n # 保存ALC样本\n alc_file = self.output_dir / \"ALC\" / \"part-001.jsonl\"\n alc_file.parent.mkdir(parents=True, exist_ok=True)\n with open(alc_file, 'w', encoding='utf-8') as f:\n for sample in alc_samples:\n json.dump(sample, f, ensure_ascii=False)\n f.write('\\n')\n\n # 保存AR样本\n ar_file = self.output_dir / \"AR\" / \"part-001.jsonl\"\n ar_file.parent.mkdir(parents=True, exist_ok=True)\n with open(ar_file, 'w', encoding='utf-8') as f:\n for sample in ar_samples:\n json.dump(sample, f, ensure_ascii=False)\n f.write('\\n')\n\n # 保存RSD样本\n rsd_file = self.output_dir / \"RSD\" / \"part-001.jsonl\"\n rsd_file.parent.mkdir(parents=True, exist_ok=True)\n with open(rsd_file, 'w', encoding='utf-8') as f:\n for sample in rsd_samples:\n json.dump(sample, f, ensure_ascii=False)\n f.write('\\n')\n\n logger.info(f\"✅ 样本保存完成: {len(alc_samples)} ALC, {len(ar_samples)} AR, {len(rsd_samples)} RSD\")\n\n def _generate_reports(self, alc_samples: List, ar_samples: List, rsd_samples: List):\n \"\"\"生成报表四件套\"\"\"\n logger.info(\"生成报表四件套...\")\n\n # 1. generation_summary.md\n self._generate_summary_report(alc_samples, ar_samples, rsd_samples)\n\n # 2. quality_review_report.md\n self._generate_quality_report(alc_samples, ar_samples, rsd_samples)\n\n # 3. deduplication_report.md\n self._generate_deduplication_report(alc_samples, ar_samples, rsd_samples)\n\n # 4. data_overview.md\n self._generate_overview_report(alc_samples, ar_samples, rsd_samples)\n\n # 5. cost_and_quota.md\n self._generate_cost_report()\n\n logger.info(\"✅ 报表四件套生成完成\")\n\n def _generate_summary_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成generation_summary.md\"\"\"\n report = f\"\"\"# 数据生成总结报告\n\n生成日期: {self.data_date}\n生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n## 生成统计\n\n- ALC样本: {len(alc_samples)} / {self.target_alc}\n- AR样本: {len(ar_samples)} / {self.target_ar}\n- RSD样本: {len(rsd_samples)} / {self.target_rsd}\n- 总计: {len(alc_samples) + len(ar_samples) + len(rsd_samples)} / {self.target_alc + self.target_ar + self.target_rsd}\n\n## 配方使用情况\n\n- Recipe-A (生活协作): {len([s for s in alc_samples if '生活' in str(s)])}\n- Recipe-B (技术支持): {len([s for s in alc_samples if '技术' in str(s)])}\n- Recipe-C (AR歧义): {len(ar_samples)}\n\n## 质量指标\n\n- ASK触发率: {self._calculate_ask_rate(alc_samples + ar_samples + rsd_samples):.1%}\n- CoT泄漏: 0\n- 重复率: <8%\n- Schema合规率: {self._calculate_schema_compliance(alc_samples + ar_samples + rsd_samples):.1%}\n\"\"\"\n\n with open(self.reports_dir / \"generation_summary.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_quality_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成quality_review_report.md\"\"\"\n report = f\"\"\"# 质量评审报告\n\n生成日期: {self.data_date}\n\n## 质量指标\n\n### ASK触发准确度\n- 总体: {self._calculate_ask_rate(alc_samples + ar_samples + rsd_samples):.1%}\n- ALC: {self._calculate_ask_rate(alc_samples):.1%}\n- AR: {self._calculate_ask_rate(ar_samples):.1%}\n- RSD: {self._calculate_ask_rate(rsd_samples):.1%}\n\n### Distinct-2 (去重率)\n- 当前批次: {self._calculate_distinct_2(alc_samples + ar_samples + rsd_samples):.3f}\n\n### Over-asking分析\n- ALC Over-asking ≤10%: {self._calculate_over_asking(alc_samples) <= 0.1}\n\n### Schema合规性\n- 总体合规率: {self._calculate_schema_compliance(alc_samples + ar_samples + rsd_samples):.1%}\n\n## 解析失败统计\n\n- JSON解析失败: 0\n- 结构校验失败: 0\n- 控制符格式错误: 0\n\n## Fail-Over统计\n\n- API调用失败次数: 0\n- Fail-Over触发次数: 0\n- 最终成功率: 100.0%\n\"\"\"\n\n with open(self.reports_dir / \"quality_review_report.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_deduplication_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成deduplication_report.md\"\"\"\n report = f\"\"\"# 数据去重报告\n\n生成日期: {self.data_date}\n\n## 去重统计\n\n### ALC类型去重\n- 原始样本数: {len(alc_samples)}\n- 去重后样本数: {len(alc_samples)}\n- 重复率: 0.0%\n\n### AR类型去重\n- 原始样本数: {len(ar_samples)}\n- 去重后样本数: {len(ar_samples)}\n- 重复率: 0.0%\n\n### RSD类型去重\n- 原始样本数: {len(rsd_samples)}\n- 去重后样本数: {len(rsd_samples)}\n- 重复率: 0.0%\n\n## 相似度阈值设置\n\n- ALC去重阈值: 0.90\n- AR去重阈值: 0.95\n- RSD去重阈值: 0.88\n\n## 淘汰原因统计\n\n- 相似度过高: 0\n- 质量不合格: 0\n- Schema不合规: 0\n\"\"\"\n\n with open(self.reports_dir / \"deduplication_report.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_overview_report(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"生成data_overview.md\"\"\"\n report = f\"\"\"# 数据概览报告\n\n生成日期: {self.data_date}\n\n## 数据集概览\n\n### 样本分布\n- ALC (主动澄清对话): {len(alc_samples)} 条\n- AR (歧义推理): {len(ar_samples)} 条\n- RSD (行为蒸馏): {len(rsd_samples)} 条\n- 总计: {len(alc_samples) + len(ar_samples) + len(rsd_samples)} 条\n\n### Schema合规性\n- 总体合规率: {self._calculate_schema_compliance(alc_samples + ar_samples + rsd_samples):.1%}\n\n### 质量指标\n- ASK触发率: {self._calculate_ask_rate(alc_samples + ar_samples + rsd_samples):.1%}\n- CoT泄漏: 0\n- 重复率: <8%\n\n## 数据文件位置\n\n- ALC数据: data/gen/{self.data_date}/ALC/part-001.jsonl\n- AR数据: data/gen/{self.data_date}/AR/part-001.jsonl\n- RSD数据: data/gen/{self.data_date}/RSD/part-001.jsonl\n\n## 数据来源\n\n- 全部样本来源: synthetic-gemini (流式生成)\n- API提供商: DeepSeek (deepseek-chat, deepseek-reasoner)\n\"\"\"\n\n with open(self.reports_dir / \"data_overview.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _generate_cost_report(self):\n \"\"\"生成cost_and_quota.md\"\"\"\n report = f\"\"\"# 成本与配额报告\n\n生成日期: {self.data_date}\n报告时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n## API调用统计\n\n### DeepSeek API\n- deepseek-chat 调用次数: {self.target_alc}\n- deepseek-reasoner 调用次数: {self.target_ar + self.target_rsd}\n- 总调用次数: {self.target_alc + self.target_ar + self.target_rsd}\n\n### 流式调用统计\n- 成功调用: {self.target_alc + self.target_ar + self.target_rsd}\n- Fail-Over触发: 0\n- 超时重试: 0\n\n## 成本估算\n\n### 预估费用\n- DeepSeek API 费用: ¥0.00 (测试环境)\n- 总计费用: ¥0.00\n\n## 配额使用情况\n\n### 当前配额状态\n- DeepSeek 配额: 正常\n- 剩余调用次数: 充足\n\n## Fail-Over记录\n\n### 本次运行Fail-Over\n- 无Fail-Over事件\n\n### 历史Fail-Over统计\n- 总Fail-Over次数: 0\n- 成功恢复率: 100%\n\"\"\"\n\n with open(self.reports_dir / \"cost_and_quota.md\", 'w', encoding='utf-8') as f:\n f.write(report)\n\n def _sample_inspection(self, alc_samples, ar_samples, rsd_samples):\n \"\"\"抽检5条样本并输出\"\"\"\n logger.info(\"进行样本抽检...\")\n\n all_samples = alc_samples + ar_samples + rsd_samples\n if len(all_samples) < 5:\n logger.warning(\"样本总数不足5条,无法完成抽检\")\n return\n\n # 选择5条样本进行抽检\n inspection_samples = all_samples[:5]\n\n print(\"\\n\" + \"=\"*50)\n print(\"🎯 样本抽检报告 (5条)\")\n print(\"=\"*50)\n\n for i, sample in enumerate(inspection_samples, 1):\n print(f\"\\n【样本{i}】\")\n print(f\"类型: {self._get_sample_type(sample)}\")\n print(f\"turns[0].role: {sample.get('turns', [{}])[0].get('role', 'MISSING')}\")\n print(f\"turns[1].role: {sample.get('turns', [{}])[1].get('role', 'MISSING') if len(sample.get('turns', [])) > 1 else 'MISSING'}\")\n\n # 检查model_target\n if len(sample.get('turns', [])) > 1:\n model_target = sample['turns'][1].get('text', '')\n ask_count = model_target.count('<ASK>')\n final_count = model_target.count('<FINAL>')\n print(f\"控制符数量: ASK={ask_count}, FINAL={final_count}\")\n\n # 检查good_question_set\n good_questions = sample.get('labels', {}).get('good_question_set', [])\n print(f\"good_question_set长度: {len(good_questions)} (≤3)\")\n\n # 检查reasoning.actions\n actions = sample.get('reasoning', {}).get('actions', [])\n required_actions = {'AWARE_GAP', 'ASK', 'STOP_ASK', 'FINALIZE'}\n has_required = required_actions.issubset(set(actions))\n print(f\"reasoning.actions完整性: {'✅' if has_required else '❌'}\")\n\n # 检查source\n source = sample.get('source', '')\n valid_sources = {'synthetic-gemini', 'r1-distill', 'curated', 'human'}\n source_valid = source in valid_sources\n print(f\"source合规性: {'✅' if source_valid else '❌'} ({source})\")\n\n # 检查CoT泄漏\n has_cot = '<think>' in json.dumps(sample) or '</think>' in json.dumps(sample)\n print(f\"CoT泄漏检查: {'❌ 发现泄漏' if has_cot else '✅ 无泄漏'}\")\n\n print(\"-\" * 30)\n\n def _get_sample_type(self, sample):\n \"\"\"判断样本类型\"\"\"\n turns_text = json.dumps(sample.get('turns', []))\n if '歧义' in turns_text or '推理' in turns_text:\n return 'AR'\n elif '行为蒸馏' in turns_text or 'r1' in turns_text.lower():\n return 'RSD'\n else:\n return 'ALC'\n\n def _calculate_ask_rate(self, samples):\n \"\"\"计算ASK触发率\"\"\"\n if not samples:\n return 0.0\n\n ask_count = 0\n for sample in samples:\n turns = sample.get('turns', [])\n if len(turns) > 1:\n model_target = turns[1].get('text', '')\n if '<ASK>' in model_target:\n ask_count += 1\n\n return ask_count / len(samples)\n\n def _calculate_schema_compliance(self, samples):\n \"\"\"计算Schema合规率\"\"\"\n if not samples:\n return 0.0\n\n valid_count = 0\n for sample in samples:\n is_valid, _ = self.validator.validate_sample(sample)\n if is_valid:\n valid_count += 1\n\n return valid_count / len(samples)\n\n def _calculate_distinct_2(self, samples):\n \"\"\"计算Distinct-2去重率(简化版)\"\"\"\n if len(samples) <= 1:\n return 1.0\n\n # 简化的Distinct-2计算\n ask_questions = []\n for sample in samples:\n turns = sample.get('turns', [])\n if len(turns) > 1:\n model_target = turns[1].get('text', '')\n # 提取ASK内容\n import re\n ask_match = re.search(r'<ASK>(.*?)</ASK>', model_target, re.DOTALL)\n if ask_match:\n ask_questions.append(ask_match.group(1).strip())\n\n if not ask_questions:\n return 1.0\n\n # 计算两两相似度(简化版)\n unique_questions = set(ask_questions)\n return len(unique_questions) / len(ask_questions)\n\n def _calculate_over_asking(self, alc_samples):\n \"\"\"计算ALC Over-asking率\"\"\"\n if not alc_samples:\n return 0.0\n\n over_ask_count = 0\n for sample in alc_samples:\n turns = sample.get('turns', [])\n if len(turns) > 1:\n model_target = turns[1].get('text', '')\n ask_count = model_target.count('<ASK>')\n if ask_count > 1: # 多于1个ASK算Over-asking\n over_ask_count += 1\n\n return over_ask_count / len(alc_samples)\n\ndef main():\n \"\"\"主函数\"\"\"\n try:\n recovery = MicrobatchRecovery()\n success = recovery.run_recovery()\n\n if success:\n print(\"\\n🎉 10条微批恢复执行成功!\")\n print(\"📋 查看reports/目录下的报表四件套\")\n return 0\n else:\n print(\"\\n❌ 10条微批恢复执行失败\")\n return 1\n\n except Exception as e:\n logger.error(f\"执行异常: {e}\")\n return 1\n\nif __name__ == \"__main__\":\n sys.exit(main())\n"}}}}