Explorar o código

Merge branch 'dev' of http://192.168.0.3:3000/CRBC-MaaS-Platform-Project/LQAgentPlatform into dev

ZengChao hai 1 mes
pai
achega
07b617226a

+ 0 - 1
.gitignore

@@ -69,7 +69,6 @@ todo.md
 .R&D
 .RaD
 temp/
-*.json
 test_rawdata/
 temp/AI审查结果.json
 mineru_temp/

+ 20 - 0
.vscode/launch.json

@@ -0,0 +1,20 @@
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Python 调试程序: 当前文件(lqagentplatform)",
+            "type": "debugpy",
+            "request": "launch",
+            "program": "${file}",
+            "console": "integratedTerminal",
+            // 关键:指定 lqagentplatform 环境的 Python 解释器路径
+            "python": "D:\\Program Files\\Anaconda\\envs\\lqagentplatform\\python.exe",
+            // 可选:添加环境变量增强兼容性(避免依赖找不到)
+            "env": {
+                "PATH": "${env:PATH};D:\\Program Files\\Anaconda\\envs\\lqagentplatform\\Scripts"
+            },
+            // 自动激活 Conda 环境(无需手动在终端激活)
+            "preLaunchTask": "activate_lqagentplatform"
+        }
+    ]
+}

+ 5 - 0
.vscode/settings.json

@@ -0,0 +1,5 @@
+{
+    "liveServer.settings.port": 5501,
+    "python-envs.defaultEnvManager": "ms-python.python:conda",
+    "python-envs.defaultPackageManager": "ms-python.python:conda"
+}

+ 15 - 0
.vscode/tasks.json

@@ -0,0 +1,15 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "activate_lqagentplatform", // 必须和 launch.json 里的 preLaunchTask 名称一致
+            "type": "shell",
+            "command": "conda activate lqagentplatform", // 激活 Conda 环境的命令
+            "args": [],
+            "presentation": {
+                "reveal": "silent" // 执行时不弹窗(可选)
+            },
+            "problemMatcher": []
+        }
+    ]
+}

+ 38 - 0
core/base/workflow_manager.py

@@ -10,6 +10,7 @@
 import asyncio
 import time
 import json
+import os
 from typing import Dict, Optional, Any
 from datetime import datetime
 from langgraph.graph import StateGraph, END
@@ -496,9 +497,46 @@ class WorkflowManager:
         # 编译工作流图
         compiled_graph = workflow.compile()
 
+        # 保存工作流图到 temp/construction_review 目录
+        self._save_workflow_graph(compiled_graph, "temp/construction_review/task_chain_workflow.png")
+
         logger.info("LangGraph 任务链工作流图构建完成")
         return compiled_graph
 
+    def _save_workflow_graph(self, compiled_graph: StateGraph, output_path: str):
+        """
+        保存 LangGraph 工作流图为 PNG 图片
+
+        Args:
+            compiled_graph: 编译后的 LangGraph 工作流图
+            output_path: 输出文件路径
+        """
+        try:
+            # 确保输出目录存在
+            output_dir = os.path.dirname(output_path)
+            if output_dir and not os.path.exists(output_dir):
+                os.makedirs(output_dir, exist_ok=True)
+                logger.info(f"创建输出目录:{output_dir}")
+
+            # 使用 graphviz 保存图片
+            # 需要安装 graphviz 和 graphviz Python 包
+            try:
+                graph = compiled_graph.get_graph()
+                graph_image = graph.draw_mermaid_png()
+                with open(output_path, "wb") as f:
+                    f.write(graph_image)
+                logger.info(f"工作流图已保存到:{output_path}")
+            except Exception as graphviz_error:
+                logger.warning(f"Graphviz 保存失败:{str(graphviz_error)}, 尝试使用 JSON 格式保存")
+                # 备用方案:保存为 JSON 格式
+                json_path = output_path.replace(".png", ".json")
+                with open(json_path, "w", encoding="utf-8") as f:
+                    json.dump(compiled_graph.get_graph().to_json(), f, indent=2, ensure_ascii=False)
+                logger.info(f"工作流图已保存到 (JSON 格式): {json_path}")
+
+        except Exception as e:
+            logger.warning(f"保存工作流图失败:{str(e)}")
+
     async def _start_chain_node(self, state: TaskChainState) -> TaskChainState:
         """
         任务链开始节点

+ 2 - 4
core/construction_review/component/document_processor.py

@@ -14,7 +14,7 @@ from datetime import datetime
 import asyncio
 
 from foundation.observability.logger.loggering import review_logger as logger
-
+from foundation.observability.cachefiles import cache, CacheBaseDir
 # 引入doc_worker核心组件
 try:
     from .doc_worker.interfaces import DocumentSource, TOCExtractor, FullTextExtractor, TextSplitter
@@ -91,9 +91,7 @@ class DocumentProcessor:
 
             # 结构化内容
             structured_result = self.structure_content(result)
-
-
-
+            cache.document_temp(structured_result, base_cache_dir=CacheBaseDir.CONSTRUCTION_REVIEW)
             return structured_result
 
         except Exception as e:

+ 82 - 63
core/construction_review/component/report_generator.py

@@ -1,6 +1,6 @@
 """
 报告生成器
-负责基于AI审查结果生成审查报告摘要
+负责基于 AI 审查结果生成审查报告摘要
 """
 
 import asyncio
@@ -32,7 +32,7 @@ class FinalReport:
     generated_at: datetime
 
 class ReportGenerator:
-    """报告生成器 - 基于高中风险问题使用LLM生成摘要"""
+    """报告生成器 - 基于高中风险问题使用 LLM 生成摘要"""
 
     def __init__(self):
         """初始化报告生成器"""
@@ -52,10 +52,10 @@ class ReportGenerator:
 
             # 手动加载 report 类型的 prompt
             self.prompt_loader._load_prompt('report', 'report_summary')
-            logger.info(f"成功加载 report_summary prompt,目录: {prompt_dir}")
+            logger.info(f"成功加载 report_summary prompt,目录{prompt_dir}")
 
         except Exception as e:
-            logger.error(f"加载 report_summary prompt 失败: {str(e)}", exc_info=True)
+            logger.error(f"加载 report_summary prompt 失败{str(e)}", exc_info=True)
         finally:
             # 恢复原始目录
             self.prompt_loader.prompt_config_dir = original_prompt_dir
@@ -68,9 +68,9 @@ class ReportGenerator:
         生成审查报告(基于高中风险问题)
 
         Args:
-            file_id: 文件ID
+            file_id: 文件 ID
             file_name: 文件名称
-            review_results: AI审查结果(包含issues列表)
+            review_results: AI 审查结果(包含 issues 列表)
             progress_callback: 进度回调函数
 
         Returns:
@@ -79,7 +79,7 @@ class ReportGenerator:
         start_time = time.time()
 
         try:
-            logger.info(f"开始生成报告,文件ID: {file_id}, 文件名: {file_name}")
+            logger.info(f"开始生成报告,文件 ID: {file_id}, 文件名:{file_name}")
 
             if progress_callback:
                 progress_callback(20, "提取高中风险问题")
@@ -88,12 +88,12 @@ class ReportGenerator:
             high_risk_issues, medium_risk_issues, low_risk_count = await self._extract_high_medium_risk_issues(review_results)
             total_issues = len(high_risk_issues) + len(medium_risk_issues) + low_risk_count
 
-            logger.info(f"问题统计 - 高风险: {len(high_risk_issues)}, 中风险: {len(medium_risk_issues)}, 低风险: {low_risk_count}, 总计: {total_issues}")
+            logger.info(f"问题统计 - 高风险:{len(high_risk_issues)}, 中风险:{len(medium_risk_issues)}, 低风险:{low_risk_count}, 总计:{total_issues}")
 
             if progress_callback:
-                progress_callback(50, "调用LLM生成报告摘要")
+                progress_callback(50, "调用 LLM 生成报告摘要")
 
-            # 2. 调用LLM生成摘要
+            # 2. 调用 LLM 生成摘要
             llm_summary = await self._call_llm_for_summary(
                 file_name=file_name,
                 high_risk_issues=high_risk_issues,
@@ -103,9 +103,9 @@ class ReportGenerator:
             )
 
             if progress_callback:
-                progress_callback(80, "解析LLM响应")
+                progress_callback(80, "解析 LLM 响应")
 
-            # 3. 解析LLM响应
+            # 3. 解析 LLM 响应
             parsed_summary = self._parse_llm_response(llm_summary)
 
             if progress_callback:
@@ -128,12 +128,12 @@ class ReportGenerator:
             )
 
             execution_time = time.time() - start_time
-            logger.info(f"报告生成完成,文件ID: {file_id}, 耗时: {execution_time:.2f}秒")
+            logger.info(f"报告生成完成,文件 ID: {file_id}, 耗时:{execution_time:.2f}秒")
 
             return final_report
 
         except Exception as e:
-            logger.error(f"报告生成失败: {str(e)}", exc_info=True)
+            logger.error(f"报告生成失败{str(e)}", exc_info=True)
             raise
 
     async def _extract_high_medium_risk_issues(self, review_results: Dict[str, Any]) -> tuple:
@@ -141,7 +141,7 @@ class ReportGenerator:
         从审查结果中提取高中风险问题
 
         Args:
-            review_results: AI审查结果
+            review_results: AI 审查结果
 
         Returns:
             tuple: (high_risk_issues, medium_risk_issues, low_risk_count)
@@ -150,15 +150,15 @@ class ReportGenerator:
         medium_risk_issues = []
         low_risk_count = 0
 
-        # 获取issues列表(键名为 'review_results')
+        # 获取 issues 列表(键名为 'review_results')
         issues = review_results.get('review_results', [])
 
-        logger.info(f"开始提取风险问题,issues数量: {len(issues)}")
+        logger.info(f"开始提取风险问题,issues 数量:{len(issues)}")
 
         for issue_wrapper in issues:
-            # issue_wrapper是一个字典,key是问题ID,value是问题详情
+            # issue_wrapper 是一个字典,key 是问题 ID,value 是问题详情
             for issue_id, issue_detail in issue_wrapper.items():
-                # 获取review_lists
+                # 获取 review_lists
                 review_lists = issue_detail.get('review_lists', [])
 
                 # 获取元数据
@@ -166,7 +166,7 @@ class ReportGenerator:
                 location = metadata.get('review_location_label', '未知位置')
 
                 for review_item in review_lists:
-                    # 只处理exist_issue=True的项
+                    # 只处理 exist_issue=True 的项
                     if not review_item.get('exist_issue', False):
                         continue
 
@@ -190,56 +190,77 @@ class ReportGenerator:
                     elif '低' in risk_level_raw or 'low' in risk_level_raw:
                         risk_level = 'low'
                     else:
-                        # 默认按risk_info判断
+                        # 默认按 risk_info 判断
                         risk_info = review_item.get('risk_info', {})
                         if isinstance(risk_info, dict):
                             risk_level = risk_info.get('risk_level', 'low')
                         else:
                             risk_level = 'low'
 
-                    # 获取检查项类型
+                    # 获取检查项类型和章节代码
                     check_item = review_item.get('check_item', 'unknown')
                     check_item_code = review_item.get('check_item_code', '')
 
-                    # 构建问题对象(包含检查项信息)
+                    # 从 check_item_code 中提取 chapter_code (格式:chapter_code_check_item)
+                    chapter_code = check_item_code.rsplit('_', 1)[0] if '_' in check_item_code else 'unknown'
+
+                    # 构建问题对象(只包含分析结果,不包含原文材料)
+                    # 按照指定格式组织数据结构
                     issue_obj = {
                         'check_item': check_item,
+                        'chapter_code': chapter_code,
                         'check_item_code': check_item_code,
-                        'location': location,
-                        'issue_point': check_result.get('issue_point', '') if isinstance(check_result, dict) else str(check_result),
-                        'suggestion': check_result.get('suggestion', '') if isinstance(check_result, dict) else '',
-                        'reason': check_result.get('reason', '') if isinstance(check_result, dict) else '',
-                        'reference_source': check_result.get('reference_source', '') if isinstance(check_result, dict) else ''
+                        'check_result': {
+                            'issue_point': check_result.get('issue_point', '') if isinstance(check_result, dict) else str(check_result),
+                            'location': check_result.get('location', location),
+                            'suggestion': check_result.get('suggestion', ''),
+                            'reason': check_result.get('reason', ''),
+                            'risk_level': check_result.get('risk_level', risk_level)
+                        }
+                        # 注意:不包含 reference_source(原文材料),只传入分析结果
                     }
 
-                    # 按风险级别分类
+                    # 按风险级别分类(只处理高风险和中风险)
                     if risk_level == 'high':
                         high_risk_issues.append(issue_obj)
                     elif risk_level == 'medium':
                         medium_risk_issues.append(issue_obj)
-                    else:
+                    elif risk_level == 'low':
                         low_risk_count += 1
 
-        logger.info(f"风险问题提取完成 - 高风险: {len(high_risk_issues)}, 中风险: {len(medium_risk_issues)}, 低风险: {low_risk_count}")
+        logger.info(f"风险问题提取完成 - 高风险:{len(high_risk_issues)}, 中风险:{len(medium_risk_issues)}, 低风险:{low_risk_count}")
 
         return high_risk_issues, medium_risk_issues, low_risk_count
 
     async def _call_llm_for_summary(self, file_name: str, high_risk_issues: List[Dict],
                                    medium_risk_issues: List[Dict], total_issues: int, trace_id: str) -> str:
         """
-        调用LLM生成报告摘要
+        调用 LLM 生成报告摘要(只处理高中风险问题,不传入原文材料)
 
         Args:
             file_name: 文件名称
             high_risk_issues: 高风险问题列表
             medium_risk_issues: 中风险问题列表
             total_issues: 总问题数
-            trace_id: 追踪ID
+            trace_id: 追踪 ID
 
         Returns:
-            str: LLM生成的摘要文本(JSON格式)
+            str: LLM 生成的摘要文本(JSON 格式)
         """
         try:
+            # 限制问题数量,避免 prompt 过长导致超时
+            # 高风险问题最多取 10 个,中风险问题最多取 15 个
+            MAX_HIGH_RISK = 10
+            MAX_MEDIUM_RISK = 15
+
+            if len(high_risk_issues) > MAX_HIGH_RISK:
+                logger.warning(f"高风险问题数量过多 ({len(high_risk_issues)}),仅取前{MAX_HIGH_RISK}个")
+                high_risk_issues = high_risk_issues[:MAX_HIGH_RISK]
+
+            if len(medium_risk_issues) > MAX_MEDIUM_RISK:
+                logger.warning(f"中风险问题数量过多 ({len(medium_risk_issues)}),仅取前{MAX_MEDIUM_RISK}个")
+                medium_risk_issues = medium_risk_issues[:MAX_MEDIUM_RISK]
+
             # 构建问题清单文本
             high_risk_text = self._format_issues_text(high_risk_issues)
             medium_risk_text = self._format_issues_text(medium_risk_issues)
@@ -260,30 +281,30 @@ class ReportGenerator:
                 "task_name": "报告摘要生成"
             }
 
-            logger.debug(f"开始调用LLM生成报告摘要")
+            logger.debug(f"开始调用 LLM 生成报告摘要")
 
-            # 调用模型(参考base_reviewer.py的实现)
+            # 调用模型 - 增加超时阈值到 180 秒(3 分钟),因为报告生成需要更多时间
             model_response = await self.model_client.get_model_generate_invoke(
                 trace_id=trace_id,
                 task_prompt_info=task_prompt_info,
-                timeout=60,
+                timeout=180,
                 model_name="qwen3_30b"
             )
 
-            logger.info(f"LLM摘要生成成功,响应长度: {len(model_response)} 字符")
+            logger.info(f"LLM 摘要生成成功,响应长度:{len(model_response)} 字符")
 
             return model_response
 
         except Exception as e:
-            logger.error(f"调用LLM生成摘要失败: {str(e)}", exc_info=True)
+            logger.error(f"调用 LLM 生成摘要失败:{str(e)}", exc_info=True)
             raise
 
     def _format_issues_text(self, issues: List[Dict]) -> str:
         """
-        格式化问题列表为文本(按 check_item 分组)
+        格式化问题列表为文本(按 check_item 分组,只包含分析结果
 
         Args:
-            issues: 问题列表
+            issues: 问题列表(每个问题包含 check_item, chapter_code, check_item_code, check_result)
 
         Returns:
             str: 格式化后的问题文本
@@ -308,7 +329,7 @@ class ReportGenerator:
             'mandatory_standards_check': '强制性标准审查',
             'technical_parameters_check': '技术参数审查',
             'design_values_check': '设计值审查',
-            'rag_enhanced_review': 'RAG增强审查',
+            'rag_enhanced_review': 'RAG 增强审查',
             'professional_suggestion': '专业建议',
             'unknown': '其他审查'
         }
@@ -320,36 +341,34 @@ class ReportGenerator:
             result.append(f"## 【{check_item_name}】({len(item_issues)}个问题)")
             result.append("")
 
-            # 添加该组的所有问题
+            # 添加该组的所有问题(只传入分析结果,不包含原文材料)
             for idx, issue in enumerate(item_issues, 1):
+                check_result = issue.get('check_result', {})
                 result.append(f"### 问题 {idx}")
-                result.append(f"- 位置: {issue.get('location', '未知')}")
-                result.append(f"- 问题点: {issue.get('issue_point', '未知')}")
-                result.append(f"- 建议: {issue.get('suggestion', '无')}")
-                result.append(f"- 依据: {issue.get('reason', '无')}")
-
-                reference_source = issue.get('reference_source', '无')
-                if reference_source and reference_source != '无':
-                    result.append(f"- 参考来源: {reference_source}")
+                result.append(f"- 章节:{issue.get('chapter_code', '未知')}")
+                result.append(f"- 位置:{check_result.get('location', '未知')}")
+                result.append(f"- 问题点:{check_result.get('issue_point', '未知')}")
+                result.append(f"- 建议:{check_result.get('suggestion', '无')}")
+                result.append(f"- 依据:{check_result.get('reason', '无')}")
+                # 注意:不包含 reference_source(原文材料)
+                result.append("")
 
-                result.append("")  # 空行分隔
-
-            result.append("")  # 分组之间额外空行
+            result.append("")
 
         return "\n".join(result)
 
     def _parse_llm_response(self, llm_response: str) -> Dict[str, Any]:
         """
-        解析LLM响应
+        解析 LLM 响应
 
         Args:
-            llm_response: LLM返回的JSON字符串
+            llm_response: LLM 返回的 JSON 字符串
 
         Returns:
             Dict: 解析后的摘要字典
         """
         try:
-            # 移除可能的markdown代码块标记
+            # 移除可能的 markdown 代码块标记
             cleaned_response = llm_response.strip()
             if cleaned_response.startswith('```json'):
                 cleaned_response = cleaned_response[7:]
@@ -360,7 +379,7 @@ class ReportGenerator:
 
             cleaned_response = cleaned_response.strip()
 
-            # 解析JSON
+            # 解析 JSON
             parsed = json.loads(cleaned_response)
 
             # 验证必需字段
@@ -374,18 +393,18 @@ class ReportGenerator:
 
             for field in required_fields:
                 if field not in parsed:
-                    logger.warning(f"LLM响应缺少必需字段: {field},使用默认值")
+                    logger.warning(f"LLM 响应缺少必需字段:{field},使用默认值")
                     if field == "overall_assessment":
                         parsed[field] = "无法生成总体评价"
                     else:
                         parsed[field] = []
 
-            logger.info("LLM响应解析成功")
+            logger.info("LLM 响应解析成功")
             return parsed
 
         except json.JSONDecodeError as e:
-            logger.error(f"解析LLM响应失败: {str(e)}")
-            logger.error(f"原始响应: {llm_response[:500]}...")  # 打印前500字符用于调试
+            logger.error(f"解析 LLM 响应失败:{str(e)}")
+            logger.error(f"原始响应:{llm_response[:500]}...")
 
             # 返回默认结构
             return {
@@ -396,5 +415,5 @@ class ReportGenerator:
                 "risk_alerts": []
             }
         except Exception as e:
-            logger.error(f"解析LLM响应时发生未知错误: {str(e)}", exc_info=True)
+            logger.error(f"解析 LLM 响应时发生未知错误:{str(e)}", exc_info=True)
             raise

+ 244 - 242
core/construction_review/workflows/ai_review_workflow.py

@@ -137,7 +137,7 @@ class AIReviewWorkflow:
         workflow = StateGraph(AIReviewState)
         workflow.add_node("start", self._start_node)
         workflow.add_node("initialize_progress", self._initialize_progress_node)
-        workflow.add_node("ai_review", self._ai_review_node)
+        #workflow.add_node("ai_review", self._ai_review_node)
         workflow.add_node("ai_review_check_item",self._ai_review_node_check_item)
         workflow.add_node("save_results", self._save_results_node)  # 添加保存结果节点
         workflow.add_node("complete", self._complete_node)
@@ -152,20 +152,20 @@ class AIReviewWorkflow:
             self._should_check_item_or_dimensions,
             {
                 "activate_ai_review_check_item": "ai_review_check_item",  # 使用 review_item_config
-                "activate_ai_review": "ai_review"                 # 使用 review_config
+                # "activate_ai_review": "ai_review"                 # 使用 review_config
             }
         )
 
-        # 添加条件边(错误处理 + 终止检查)
-        workflow.add_conditional_edges(
-            "ai_review",
-            self._should_terminate_or_error,
-            {
-                "terminate": "terminate",  # 终止路径
-                "success": "save_results",  # 成功后先保存结果
-                "error": "error_handler"  # 错误处理
-            }
-        )
+        # # 添加条件边(错误处理 + 终止检查)
+        # workflow.add_conditional_edges(
+        #     "ai_review",
+        #     self._should_terminate_or_error,
+        #     {
+        #         "terminate": "terminate",  # 终止路径
+        #         "success": "save_results",  # 成功后先保存结果
+        #         "error": "error_handler"  # 错误处理
+        #     }
+        # )
 
                 # 添加条件边(错误处理 + 终止检查)
         workflow.add_conditional_edges(
@@ -397,7 +397,8 @@ class AIReviewWorkflow:
                 all_check_items.extend(check_list)  # 把每个分类的检查项加入总列表
 
             # 统计所有 filtered_chunks 作为总块数(与实际处理的块数保持一致)
-            total_chunks = len(filtered_chunks)
+            # 注意:+1 为目录审查单元(系统强制添加,不在用户配置的 review_item_config 中)
+            total_chunks = len(filtered_chunks) + 1
 
             # 初始化issues列表
             all_issues = []
@@ -452,6 +453,7 @@ class AIReviewWorkflow:
                 logger.info(f"章节 {chapter_code} 处理完成")
 
             # 主流程完成后,串行处理 catalogue(目录审查)
+            # 注意:catalogue 是系统强制添加的审查单元,已计入 total_chunks
             logger.info("开始处理目录审查(catalogue)")
             chunks_completed, all_issues = await self.core_fun._process_chapter_item(
                 "catalogue",                 # chapter_code
@@ -510,237 +512,237 @@ class AIReviewWorkflow:
                 "messages": [AIMessage(content=f"AI审查项检查失败: {str(e)}")]
             }
 
-    async def _ai_review_node(self, state: AIReviewState) -> AIReviewState:
-        """
-        AI审查节点
-
-        Args:
-            state: AI审查状态
-
-        Returns:
-            AIReviewState: 更新后的审查状态
-        """
-        try:
-            logger.info(f"AI审查节点开始执行,任务ID: {self.task_info.callback_task_id}")
-
-            # ⚠️ 检查终止信号(执行前)
-            if await self.workflow_manager.check_terminate_signal(state["callback_task_id"]):
-                logger.warning(f"AI审查节点检测到终止信号,任务ID: {state['callback_task_id']}")
-                return {
-                    "status": "terminated",
-                    "current_stage": "ai_review",
-                    "messages": [AIMessage(content="检测到终止信号")]
-                }
-
-            test_designation_chunk_flag = self.task_info.get_test_designation_chunk_flag()
-            logger.debug(f"测试定位标志: {test_designation_chunk_flag}")
-
-            # 1. 准备审查单元数据
-            review_chunks, total_units = await self.core_fun._prepare_review_units(state, test_designation_chunk_flag)
-
-            # 检查指定测试章节是否未找到
-            if test_designation_chunk_flag is not None and not review_chunks:
-                error_msg = f"AI审查测试失败:未找到指定审查标志「{test_designation_chunk_flag}」。请修改指定审查标识字段串,建议去除前后符号等(如书名号《》、括号()等),使用更简洁的关键词重新尝试。"
-                logger.error(f"🔴 {error_msg}")
-                return {
-                    "current_stage": "ai_review",
-                    "error_message": error_msg,
-                    "status": "failed",
-                    "messages": [AIMessage(content=error_msg)]
-                }
-
-            logger.info(f"准备审查单元完成,总单元数: {total_units}, 实际审查: {len(review_chunks)}")
-
-            if not review_chunks:
-                logger.warning(f"没有可审查的单元,任务ID: {state['callback_task_id']}")
-                return {
-                    "current_stage": "ai_review",
-                    "error_message": "没有可审查的单元",
-                    "status": "failed",
-                    "messages": [AIMessage(content=f"没有可审查的单元,任务ID: {state['callback_task_id']}")]
-                }
-
-            logger.info(f"开始核心审查,任务ID: {state['callback_task_id']}")
-            await self.core_fun._send_start_review_progress(state, total_units,'core_review')
-            # 2. 执行基础并发审查(内部会检测终止信号)
-            logger.info(f"开始执行并发审查,任务ID: {state['callback_task_id']}")
-            successful_results = await self.core_fun._execute_concurrent_reviews(
-                review_chunks, total_units, state, check_terminate=True
-            )
-            logger.info(f"并发审查完成,成功结果: {len(successful_results)}, 任务ID: {state['callback_task_id']}")
-
-            # ⚠️ 再次检查终止信号(并发审查后)
-            if await self.workflow_manager.check_terminate_signal(state["callback_task_id"]):
-                logger.warning(f"AI审查节点并发审查后检测到终止信号,任务ID: {state['callback_task_id']}")
-                return {
-                    "status": "terminated",
-                    "current_stage": "ai_review",
-                    "messages": [AIMessage(content="检测到终止信号")]
-                }
-
-            # 开始条文完整性审查
+    # async def _ai_review_node(self, state: AIReviewState) -> AIReviewState:
+    #     """
+    #     AI审查节点
+
+    #     Args:
+    #         state: AI审查状态
+
+    #     Returns:
+    #         AIReviewState: 更新后的审查状态
+    #     """
+    #     try:
+    #         logger.info(f"AI审查节点开始执行,任务ID: {self.task_info.callback_task_id}")
+
+    #         # ⚠️ 检查终止信号(执行前)
+    #         if await self.workflow_manager.check_terminate_signal(state["callback_task_id"]):
+    #             logger.warning(f"AI审查节点检测到终止信号,任务ID: {state['callback_task_id']}")
+    #             return {
+    #                 "status": "terminated",
+    #                 "current_stage": "ai_review",
+    #                 "messages": [AIMessage(content="检测到终止信号")]
+    #             }
+
+    #         test_designation_chunk_flag = self.task_info.get_test_designation_chunk_flag()
+    #         logger.debug(f"测试定位标志: {test_designation_chunk_flag}")
+
+    #         # 1. 准备审查单元数据
+    #         review_chunks, total_units = await self.core_fun._prepare_review_units(state, test_designation_chunk_flag)
+
+    #         # 检查指定测试章节是否未找到
+    #         if test_designation_chunk_flag is not None and not review_chunks:
+    #             error_msg = f"AI审查测试失败:未找到指定审查标志「{test_designation_chunk_flag}」。请修改指定审查标识字段串,建议去除前后符号等(如书名号《》、括号()等),使用更简洁的关键词重新尝试。"
+    #             logger.error(f"🔴 {error_msg}")
+    #             return {
+    #                 "current_stage": "ai_review",
+    #                 "error_message": error_msg,
+    #                 "status": "failed",
+    #                 "messages": [AIMessage(content=error_msg)]
+    #             }
+
+    #         logger.info(f"准备审查单元完成,总单元数: {total_units}, 实际审查: {len(review_chunks)}")
+
+    #         if not review_chunks:
+    #             logger.warning(f"没有可审查的单元,任务ID: {state['callback_task_id']}")
+    #             return {
+    #                 "current_stage": "ai_review",
+    #                 "error_message": "没有可审查的单元",
+    #                 "status": "failed",
+    #                 "messages": [AIMessage(content=f"没有可审查的单元,任务ID: {state['callback_task_id']}")]
+    #             }
+
+    #         logger.info(f"开始核心审查,任务ID: {state['callback_task_id']}")
+    #         await self.core_fun._send_start_review_progress(state, total_units,'core_review')
+    #         # 2. 执行基础并发审查(内部会检测终止信号)
+    #         logger.info(f"开始执行并发审查,任务ID: {state['callback_task_id']}")
+    #         successful_results = await self.core_fun._execute_concurrent_reviews(
+    #             review_chunks, total_units, state, check_terminate=True
+    #         )
+    #         logger.info(f"并发审查完成,成功结果: {len(successful_results)}, 任务ID: {state['callback_task_id']}")
+
+    #         # ⚠️ 再次检查终止信号(并发审查后)
+    #         if await self.workflow_manager.check_terminate_signal(state["callback_task_id"]):
+    #             logger.warning(f"AI审查节点并发审查后检测到终止信号,任务ID: {state['callback_task_id']}")
+    #             return {
+    #                 "status": "terminated",
+    #                 "current_stage": "ai_review",
+    #                 "messages": [AIMessage(content="检测到终止信号")]
+    #             }
+
+    #         # 开始条文完整性审查
             
 
-            # 开始大纲审查
-            await self.core_fun._send_start_review_progress(state, total_units,'outline')
-            completeness_check = "completeness_check" in  self.task_info.get_review_config_list()
-            if not completeness_check:
-                logger.info(f"跳过执行大纲审查")
-            else:
-            # 3. 执行大纲审查
-                logger.info(f"开始执行大纲审查")
-
-
-
-
-                check_completeness_result = await self.ai_review_engine.check_completeness(
-                    trace_id_idx = state["callback_task_id"],
-                    review_content = state["structured_content"]["chunks"],
-                    state = state,
-                    stage_name = state.get("stage_name", "完整性审查")
-                )
-                outline_review_result = {} 
-
-
-
-            # # 4. 执行编制依据审查
-            # #await self.core_fun._send_start_review_progress(state, total_units,'prpe_basis')
-            reference_check = "reference_check" in self.task_info.get_review_config_list()
-            timeliness_check = "timeliness_check" in self.task_info.get_review_config_list()
-            reference_check_result = None
-            timeliness_check_result = None
-
-            # 统一提取一次编制依据内容(任一审查开启时才提取)
-            basis_content = ""
-            basis_items = None
-            if reference_check or timeliness_check:
-                prep_basis_content = self._extract_prep_basis_content(state["structured_content"])
-                if prep_basis_content:
-                    try:
-                        basis_items = await extract_basis_with_langchain_qwen(
-                            progress_manager=state.get("progress_manager"),
-                            callback_task_id=state.get("callback_task_id"),
-                            text=prep_basis_content,
-                        )
-                        basis_content = "\n".join(
-                            [
-                                item.raw
-                                for item in getattr(basis_items, "items", [])
-                                if getattr(item, "raw", None)
-                            ]
-                        ).strip()
-                        if not basis_content:
-                            basis_content = prep_basis_content
-                        logger.info(
-                            f"编制依据AI提取完成,条数: {len(getattr(basis_items, 'items', []))}"
-                        )
-                    except Exception as e:
-                        logger.error(f"编制依据AI提取失败,回退原文: {e}", exc_info=True)
-                        basis_content = prep_basis_content
-                else:
-                    logger.warning(f"未找到编制依据内容,跳过编制依据审查准备")
-
-            logger.info(f"执行编制依据审查")
-            if not reference_check:
-                logger.info(f"跳过执行编制依据审查")
-            else:
-                if basis_content:
-                    logger.info(f"开始执行编制依据审查")
-
-                    prep_basis_review_data = {
-                        'content': basis_content,
-                        'basis_items': basis_items,
-                        'max_concurrent': self.max_concurrent
-                    }
-
-                    reference_check_result = await self.ai_review_engine.reference_basis_reviewer(
-                        review_data=prep_basis_review_data,
-                        trace_id=state["callback_task_id"],
-                        state=state,
-                        stage_name="编制依据审查"
-                    )
-                else:
-                    logger.warning(f"未找到编制依据内容,跳过编制依据审查")
-
-            logger.info(f"执行编制依据审查(时效性)")
-            if not timeliness_check:
-                logger.info(f"跳过执行编制依据审查(时效性)")
-            else:
-                if basis_content:
-                    logger.info(f"开始执行编制依据审查(时效性)")
-
-                    timeliness_check_data = {
-                        'content': basis_content,
-                        'basis_items': basis_items,
-                        'max_concurrent': self.max_concurrent
-                    }
-
-                    timeliness_check_result = await self.ai_review_engine.timeliness_basis_reviewer(
-                        review_data=timeliness_check_data,
-                        trace_id=state["callback_task_id"],
-                        state=state,
-                        stage_name="编制依据审查"
-                    )
-                else:
-                    logger.warning(f"未找到编制依据内容,跳过编制依据审查(时效性)")
-
-
-            # 6. 汇总结果
-            summary = self.inter_tool._aggregate_results(successful_results)
-
-            # 将所有单元的issues合并成一个列表
-            all_issues = []
-            if completeness_check:
-                all_issues.append(outline_review_result)
-                all_issues.append(check_completeness_result)
-            if reference_check and reference_check_result:
-                all_issues.append(reference_check_result)
-            if timeliness_check and timeliness_check_result:
-                all_issues.append(timeliness_check_result)
-            for unit_issues in successful_results:
-                if unit_issues and isinstance(unit_issues, list):
-                    all_issues.extend(unit_issues)
-
-            # 构建符合格式的review_results(兼容 execute() 方法的期望格式)
-            review_results = {
-                # 兼容旧版格式的字段
-                "total_units": total_units,
-                "successful_units": len(successful_results),
-                "failed_units": max(0, total_units - len(successful_results)),
-                "review_results": all_issues,  # 审查结果列表
-                "summary": summary,
-
-                # 额外的元信息
-                "callback_task_id": state["callback_task_id"],
-                "file_name": state.get("file_name", ""),
-                "user_id": state["user_id"],
-                "current": 100,
-                "stage_name": "完整审查结果",
-                "status": "full_review_result",
-                "message": f"审查完成,共发现{summary.get('total_issues', 0)}个问题",
-                "updated_at": int(time.time())
-            }
-
-            logger.info(f"AI审查节点执行成功,任务ID: {state['callback_task_id']}, 总单元数: {total_units}, 成功: {len(successful_results)}")
-
-            # 返回新的状态,避免原地修改导致的LangGraph冲突
-            return {
-                "current_stage": "ai_review_completed",
-                "review_results": review_results,
-                "status": "completed",
-                "messages": [AIMessage(content="AI审查完成")]
-            }
-
-        except Exception as e:
-            logger.error(f"AI审查节点执行失败,任务ID: {state['callback_task_id']}, 错误: {str(e)}", exc_info=True)
-
-            # 返回错误状态
-            return {
-                "current_stage": "ai_review_failed",
-                "error_message": str(e),
-                "status": "failed",
-                "messages": [AIMessage(content=f"AI审查失败: {str(e)}")]
-            }
+    #         # 开始大纲审查
+    #         await self.core_fun._send_start_review_progress(state, total_units,'outline')
+    #         completeness_check = "completeness_check" in  self.task_info.get_review_config_list()
+    #         if not completeness_check:
+    #             logger.info(f"跳过执行大纲审查")
+    #         else:
+    #         # 3. 执行大纲审查
+    #             logger.info(f"开始执行大纲审查")
+
+
+
+
+    #             check_completeness_result = await self.ai_review_engine.check_completeness(
+    #                 trace_id_idx = state["callback_task_id"],
+    #                 review_content = state["structured_content"]["chunks"],
+    #                 state = state,
+    #                 stage_name = state.get("stage_name", "完整性审查")
+    #             )
+    #             outline_review_result = {} 
+
+
+
+    #         # # 4. 执行编制依据审查
+    #         # #await self.core_fun._send_start_review_progress(state, total_units,'prpe_basis')
+    #         reference_check = "reference_check" in self.task_info.get_review_config_list()
+    #         timeliness_check = "timeliness_check" in self.task_info.get_review_config_list()
+    #         reference_check_result = None
+    #         timeliness_check_result = None
+
+    #         # 统一提取一次编制依据内容(任一审查开启时才提取)
+    #         basis_content = ""
+    #         basis_items = None
+    #         if reference_check or timeliness_check:
+    #             prep_basis_content = self._extract_prep_basis_content(state["structured_content"])
+    #             if prep_basis_content:
+    #                 try:
+    #                     basis_items = await extract_basis_with_langchain_qwen(
+    #                         progress_manager=state.get("progress_manager"),
+    #                         callback_task_id=state.get("callback_task_id"),
+    #                         text=prep_basis_content,
+    #                     )
+    #                     basis_content = "\n".join(
+    #                         [
+    #                             item.raw
+    #                             for item in getattr(basis_items, "items", [])
+    #                             if getattr(item, "raw", None)
+    #                         ]
+    #                     ).strip()
+    #                     if not basis_content:
+    #                         basis_content = prep_basis_content
+    #                     logger.info(
+    #                         f"编制依据AI提取完成,条数: {len(getattr(basis_items, 'items', []))}"
+    #                     )
+    #                 except Exception as e:
+    #                     logger.error(f"编制依据AI提取失败,回退原文: {e}", exc_info=True)
+    #                     basis_content = prep_basis_content
+    #             else:
+    #                 logger.warning(f"未找到编制依据内容,跳过编制依据审查准备")
+
+    #         logger.info(f"执行编制依据审查")
+    #         if not reference_check:
+    #             logger.info(f"跳过执行编制依据审查")
+    #         else:
+    #             if basis_content:
+    #                 logger.info(f"开始执行编制依据审查")
+
+    #                 prep_basis_review_data = {
+    #                     'content': basis_content,
+    #                     'basis_items': basis_items,
+    #                     'max_concurrent': self.max_concurrent
+    #                 }
+
+    #                 reference_check_result = await self.ai_review_engine.reference_basis_reviewer(
+    #                     review_data=prep_basis_review_data,
+    #                     trace_id=state["callback_task_id"],
+    #                     state=state,
+    #                     stage_name="编制依据审查"
+    #                 )
+    #             else:
+    #                 logger.warning(f"未找到编制依据内容,跳过编制依据审查")
+
+    #         logger.info(f"执行编制依据审查(时效性)")
+    #         if not timeliness_check:
+    #             logger.info(f"跳过执行编制依据审查(时效性)")
+    #         else:
+    #             if basis_content:
+    #                 logger.info(f"开始执行编制依据审查(时效性)")
+
+    #                 timeliness_check_data = {
+    #                     'content': basis_content,
+    #                     'basis_items': basis_items,
+    #                     'max_concurrent': self.max_concurrent
+    #                 }
+
+    #                 timeliness_check_result = await self.ai_review_engine.timeliness_basis_reviewer(
+    #                     review_data=timeliness_check_data,
+    #                     trace_id=state["callback_task_id"],
+    #                     state=state,
+    #                     stage_name="编制依据审查"
+    #                 )
+    #             else:
+    #                 logger.warning(f"未找到编制依据内容,跳过编制依据审查(时效性)")
+
+
+    #         # 6. 汇总结果
+    #         summary = self.inter_tool._aggregate_results(successful_results)
+
+    #         # 将所有单元的issues合并成一个列表
+    #         all_issues = []
+    #         if completeness_check:
+    #             all_issues.append(outline_review_result)
+    #             all_issues.append(check_completeness_result)
+    #         if reference_check and reference_check_result:
+    #             all_issues.append(reference_check_result)
+    #         if timeliness_check and timeliness_check_result:
+    #             all_issues.append(timeliness_check_result)
+    #         for unit_issues in successful_results:
+    #             if unit_issues and isinstance(unit_issues, list):
+    #                 all_issues.extend(unit_issues)
+
+    #         # 构建符合格式的review_results(兼容 execute() 方法的期望格式)
+    #         review_results = {
+    #             # 兼容旧版格式的字段
+    #             "total_units": total_units,
+    #             "successful_units": len(successful_results),
+    #             "failed_units": max(0, total_units - len(successful_results)),
+    #             "review_results": all_issues,  # 审查结果列表
+    #             "summary": summary,
+
+    #             # 额外的元信息
+    #             "callback_task_id": state["callback_task_id"],
+    #             "file_name": state.get("file_name", ""),
+    #             "user_id": state["user_id"],
+    #             "current": 100,
+    #             "stage_name": "完整审查结果",
+    #             "status": "full_review_result",
+    #             "message": f"审查完成,共发现{summary.get('total_issues', 0)}个问题",
+    #             "updated_at": int(time.time())
+    #         }
+
+    #         logger.info(f"AI审查节点执行成功,任务ID: {state['callback_task_id']}, 总单元数: {total_units}, 成功: {len(successful_results)}")
+
+    #         # 返回新的状态,避免原地修改导致的LangGraph冲突
+    #         return {
+    #             "current_stage": "ai_review_completed",
+    #             "review_results": review_results,
+    #             "status": "completed",
+    #             "messages": [AIMessage(content="AI审查完成")]
+    #         }
+
+    #     except Exception as e:
+    #         logger.error(f"AI审查节点执行失败,任务ID: {state['callback_task_id']}, 错误: {str(e)}", exc_info=True)
+
+    #         # 返回错误状态
+    #         return {
+    #             "current_stage": "ai_review_failed",
+    #             "error_message": str(e),
+    #             "status": "failed",
+    #             "messages": [AIMessage(content=f"AI审查失败: {str(e)}")]
+    #         }
 
     async def _save_results_node(self, state: AIReviewState) -> AIReviewState:
         """

+ 518 - 0
core/construction_write/component/prompt/keyword_rules_3.json

@@ -0,0 +1,518 @@
+[
+  {
+    "basis_LawsAndRegulations_NationalLawsAndRegulations": "国家级、法律、法规、规章、强制力、普遍适用、基础框架、顶层设计、行业准则、合规性、统一标准、权威性、强制性条文、基本要求。"
+  },
+  {
+    "basis_LawsAndRegulations_ProvincialLawsAndRegulationsOfProjectLocation": "地方性、区域性、细化补充、因地制宜、执行细则、地方特色、适应性要求、属地管理、动态调整、配套政策、本地化实施。"
+  },
+  {
+    "basis_StandardsAndSpecifications_IndustryStandards": "需符合国家/行业强制或推荐性标准(如GB/T、JTG等),时效性强(需跟踪最新版)、覆盖全生命周期(设计→施工→运维),是定义工程项目的最低技术要求、质量验收准则、安全红线。"
+  },
+  {
+    "basis_StandardsAndSpecifications_TechnicalRegulations": "操作流程标准化,工艺参数,量化风险管控,节点设备使用,规范施工验收细则,人员资质要求,应急预案模板,数字化交付标准,BIM协同规则,绿色施工指标,强制性条款需100%执行(如安全操作规范),包含可视化元素(图表、流程图、三维模型指引),与BIM技术深度融合(4D进度模拟、5D成本控制)。"
+  },
+  {
+    "basis_DocumentSystems_SichuanRoadAndBridgeDocumentSystemsAndManagementProcedures": "需包含集团级BIM实施标准、EPC总承包管理模式细则,强制要求下属单位接入集团统一的数字化管理平台(如PM系统),设置科技创新成果转化的量化考核指标。"
+  },
+  {
+    "basis_DocumentSystems_RoadAndBridgeGroupDocumentSystemsAndManagementProcedures": "区域化管理细则,属地化政策适配,项目分级管控,应急响应机制,分包商信用评价,农民工工资支付,保障绿色施工区域,标准智慧工地建设指南,隐蔽工程验收流程,工程变更索赔指引。"
+  },
+  {
+    "basis_DocumentSystems_BridgeCompanyDocumentSystemsAndManagementProcedures": "专业技术标准,工艺工法创新,特种设备管理,试验检测规程,安全生产责任制,班前安全教育工程,质量三检制技术交底,标准化竣工资料归档,规范创优工程培育计划。"
+  },
+  {
+    "basis_DocumentSystems_ConstructionUnitDocumentSystemsAndManagementProcedures": "项目合同履约,工程款支付管理,设计变更审批,竣工验收标准,运营移交协议,保修期责任划分,参建单位考核评价,档案管理实施细则,信息沟通机制,争议解决程序。"
+  },
+  {
+    "basis_CompilationPrinciples_NationalPoliciesStandardsAndDesignDocument": "需动态更新(如新版《公路工程技术标准》实施后同步调整),涉及多部门联合审查(发改委、住建部、生态环境部)。\n**重点** focus:\n盖国家战略导向,法规强制性,设计文件权威性,技术基准统一合规性,底线政策更新,跟踪跨部门协同依据。"
+  },
+  {
+    "basis_CompilationPrinciples_BasicConstructionProcedures": "法定程序刚性,四阶段闭环管理,审批链条完整性,阶段成果验收,逆程序风险管控,数字化流程跟踪。\n**重点** focus:\n\n- 不同类型项目(房建/市政/交通)存在程序差异(如公路需行业主管部门专项审批) \n- 重大变更需重新履行审批程序(如超概算10%以上)"
+  },
+  {
+    "basis_CompilationPrinciples_ProjectFunctionImplementation": "需求匹配度,全功能交付,使用效能保障,用户需求反演,系统集成测试,缺陷责任期追溯\n**重点** focus:\n\n- 需编制《功能需求说明书》作为验收依据 \n- 涉及多方利益相关者(业主、监理、最终用户)的功能确认"
+  },
+  {
+    "basis_CompilationPrinciples_ContractPerformance": "契约精神,权利义务对等,支付节点刚性,变更索赔闭环,信用评价联动,争议解决机制\n**重点** focus:\n\n- 需同步签订《廉政协议》作为合同附件 \n- 履约评价结果直接影响后续项目投标资格"
+  },
+  {
+    "basis_CompilationPrinciples_ConstructionForceConcentration": "资源集约化,专业化,班组机械配置标准化,劳动力调度,算法工序穿插优化,进度风险预警"
+  },
+  {
+    "basis_CompilationPrinciples_ProcessControl": "工序逻辑链,工艺标准化,交接检验制度化,关键线路动态监测,平行检验机制,隐蔽工程追溯"
+  },
+  {
+    "basis_CompilationScope_ProjectCoverage": "项目范围完整性,子项划分颗粒度,工程量清单闭合性,专业界面划分,变更管理阈值,风险识别矩阵价,值工程分析,可施工性评审,全生命周期覆盖,涉密工程隔离。"
+  },
+  {
+    "basis_CompilationScope_ConstructionTechnology": "工艺标准化体系,工法创新等级,质量控制关键点,机械化作业率,绿色施工技术,BIM协同设计,装配式构件应用,智能监测覆盖率,特殊环境适应性,非遗工艺传承。"
+  },
+  {
+    "overview_DesignSummary_ProjectIntroduction": "工程名称、工程类型(如住宅、桥梁、隧道)、建设规模(如建筑面积、长度、高度)、工程地址、投资额、工程性质(新建/改建/扩建)、设计单位、设计依据(如合同编号)、工程范围(如施工边界坐标)。\n**重点** focus:\n关注名称类,具体数值类,量化单位类。"
+  },
+  {
+    "overview_DesignSummary_MainTechnicalStandards": "技术规范编号(如GB50021-2001《岩土工程勘察规范》)、设计使用年限、荷载标准(如活荷载、恒荷载)、抗震设防烈度、防火等级、环保标准(如绿色建筑认证)、材料标准(如混凝土强度等级C30)、施工工艺标准。\n**重点** focus:\n技术标准需引用国家或行业规范,关注标准号数字类,各类年限、等级数值、量化单位。"
+  },
+  {
+    "overview_GeologyWeather_HydrologicalConditions": "地下水位(历史最高水位、当前水位)、含水层类型(孔隙水、裂隙水、承压水)、隔水层厚度、渗透系数(K值)、给水度、水质腐蚀性(如pH值、氯离子含量)、补径排条件(补给源、径流方向)、水文地质参数(如越流系数)、地下水动态监测数据。\n**重点** focus:\n关注地名类,具体水位数值类,量化单位类。"
+  },
+  {
+    "overview_GeologyWeather_ClimaticConditions": "气候类型(如亚热带季风气候)、年平均气温、极端气温、年降水量、降雨强度(如小时最大降雨量)、蒸发量、湿度、主导风向、风速、冰冻期、台风频率、气象数据来源(如当地气象站)。\n**重点** focus:\n关注记录降雨量、水位、气温等数值量化单位类。"
+  },
+  {
+    "overview_Surroundings_PositionalRelationship": "相邻建(构)筑物(如住宅楼、桥梁)、距离(米)、方位角、山体坡度(°)、边坡稳定性(如安全系数)、河谷宽度、深基坑深度(米)、道路等级(如城市主干道)、高压电电压(kV)、地下管线类型(给水、燃气、电缆)、埋深(米)、保护距离。\n**重点** focus:\n周边环境需分析地形地貌名词、建筑分布名词及交通状况道路名词、相关量化单位,相关数字数值。"
+  },
+  {
+    "overview_Surroundings_StructuralDimensions": "建筑物高度/层数、山体海拔、边坡坡比(如1:1.5)、河谷断面尺寸、深基坑支护结构(如桩径、墙厚)、道路宽度(米)、高压电塔高度、地下管线段径(如DN100)。\n**重点** focus:\n各类专业性名词,建筑物名词,米或毫米等单位类。"
+  },
+  {
+    "overview_LayoutPlan_TemporaryFacilityLocation": "拌和站坐标(如X,Y)、钢筋加工场距工程距离(米)、材料堆码区域面积(㎡)、临时占地红线、与工程最近点距离、场地利用率(%)。\n**重点** focus:\n场地名词,数值类,量化单位类。"
+  },
+  {
+    "overview_LayoutPlan_ConstructionWorkPlatform": "作业平台尺寸(长×宽,米)、地面形式(混凝土硬化、砂石铺垫)、施工便道长度(米)、宽度(米)、路面形式(沥青、碎石)、最小弯曲半径(米)、坡度(%)、承载力(kPa)。\n**重点** focus:\n场地名词,数值类,量化单位类。"
+  },
+  {
+    "overview_LayoutPlan_TemporaryWaterAndElectricityArrangement": "临时用水源(市政管网、地下水井)、管径(如DN100)、管线布置图(走向、节点距离)、供水压力(MPa)、变压器容量(kVA)、配电箱位置、线路走向(架空/埋地)、敷设方式(直埋、穿管)、电缆规格(如YJV22)。\n**重点** focus:\n名称类,数值类,量化单位类。"
+  },
+  {
+    "overview_RequirementsTech_DurationTarget": "开工日期(年月日)、竣工日期、总工期(天)、关键节点工期(如基础完工期)、进度计划(甘特图编号)、工期保证措施(如资源调配)。\n**重点** focus:\n名称类,日期类。"
+  },
+  {
+    "overview_RequirementsTech_QualityTarget": "质量目标(如合格率100%、鲁班奖)、合同条款编号、业主具体要求(如绿色施工认证)。\n**重点** focus:\n名称类,量化单位类,数值类。"
+  },
+  {
+    "overview_RequirementsTech_SecurityGoals": "安全目标(如零死亡事故、隐患整改率)、合同条款编号、业主具体要求(如绿色施工认证)。\n**重点** focus:\n名称类,量化单位类,数值类。"
+  },
+  {
+    "overview_RequirementsTech_EnvironmentalGoals": "环境目标(如扬尘控制、噪声限值)、合同条款编号、业主具体要求(如绿色施工认证)。\n**重点** focus:\n名称类,量化单位类,数值类。"
+  },
+  {
+    "overview_RiskLevel_DangerSource": "地质灾害(地面沉降、滑坡)、水文风险(管涌、流砂)、施工风险(坍塌、触电)、环境风险(污染、火灾)、机械伤害(塔吊倾覆)、法律法规依据(如《安全生产法》)。\n**重点** focus:\n危害隐患性词汇类,法规名称类、标准编号类。"
+  },
+  {
+    "overview_RiskLevel_ClassificationAndResponseMeasures": "风险等级(重大、较大、一般)、分级标准(如LEC法)、应对措施(监测、支护、疏散)、应急预案编号、责任部门、监控频率。\n**重点** focus:\n风险等级相关专业性词汇、属于、标准编号或其他编号,部门名称类、数值类,量化单位类。"
+  },
+  {
+    "overview_Stakeholders_UnitType": "建设单位(业主)、设计单位、监理单位、施工单位(总包)、监控单位(监测机构)、专业分包单位(如桩基分包)、统一社会信用代码、项目负责人。\n**重点** focus:\n名称类,数值类。"
+  },
+  {
+    "plan_Schedule_ProcessOperationTimeAnalysis": "需明确各工序的持续时间、逻辑关系及资源需求,是进度计划的基础;"
+  },
+  {
+    "plan_Schedule_KeyProjectNodeArrangement": "主要工程(工序)节点的起止时间和持续时间,聚焦影响总工期的关键工序(如基础浇筑、主体封顶),是进度控制的核心;"
+  },
+  {
+    "plan_Schedule_ConstructionScheduleGanttChart": "直观展示进度安排的标准工具,需包含主要工序名称、起始时间、截止时间、持续时间、时间横道、责任人等信息;"
+  },
+  {
+    "plan_Materials_ListOfConstructionMeasuresAndMaterials": "排除主题工程材料,施工措施材料应包含如临时支撑结构材料、辅助施工材料、非主体工程的挡防措施、作业平台处理、模板配置、人员上下通道、安全防护措施和安全防护用品等,详细列出材料名称、规格、数量、重量及来源(如厂家、经销商),是材料计划的核心输出\n**重点** focus:\n名称类、规格类、数值类、数值单位类"
+  },
+  {
+    "plan_Equipment_MainConstructionMachineryAndEquipment": "列出关键设备(如起重吊装设备、混凝土浇筑设备、张拉压浆设备、人员升降设备、钻孔设备、隧道专用设备、监测\n监控设备、质量检查验收设备等),明确其设备名称、规格(如额定功率)、数量及来源(自有或租赁);\n**重点** focus:\n设备名称类、规格类、数值类、数值单位类、时间日期类"
+  },
+  {
+    "plan_Workforce_WorkforceAllocationPlan": "明确工种投入(如木工、钢筋工等)情况,按施工阶段(如基础、主体、装饰)列出各工种(如模板工、混凝土工)的投入数量,确保劳动力与进度匹配;"
+  },
+  {
+    "plan_Workforce_StageLaborDemand": "明确周/旬/月的劳动力峰值及低谷,优化人员调度;"
+  },
+  {
+    "plan_SafetyCost_CategoryOfSafetyProductionExpenses": "符合《企业安全生产费用提取和使用管理办法》(财资〔2022〕136号)及地方规定(如广东省水利厅2025年办法),如安全防护设施、应急救援等;"
+  },
+  {
+    "plan_SafetyCost_SecurityFeeName": "具体(如“施工现场临时用电系统改造”“应急救援器材采购”),避免模糊表述;"
+  },
+  {
+    "plan_SafetyCost_SingleInvestmentAmount": "明确每项费用的具体数值(如“临时防护栏杆采购:5万元”),确保费用可量化;"
+  },
+  {
+    "plan_SafetyCost_TotalSafetyProductionExpenses": "根据工程规模、风险等级计算,确保足额投入"
+  },
+  {
+    "technology_MethodsOverview_ConstructionTechnologySelection": "需明确工程采用的核心工艺(如“现浇混凝土框架工艺”“装配式构件安装工艺”),是施工方法概述的基础;"
+  },
+  {
+    "technology_MethodsOverview_MainConstructionMethods": "需概括各分部分项工程的关键做法(如“基础采用旋挖钻孔灌注桩施工”“主体采用铝模板体系施工”);"
+  },
+  {
+    "technology_MethodsOverview_TemplateConfigurationQuantity": "需根据施工进度和构件尺寸计算(如“柱模板配置20套”“梁模板配置15套”),是模板管理的关键指标;"
+  },
+  {
+    "technology_TechParams_MaterialType": "需明确主要材料的类别(如“钢筋”“混凝土”“防水卷材”),是技术参数的基础;"
+  },
+  {
+    "technology_TechParams_MaterialSpecifications": "需细化材料的尺寸、型号(如“钢筋HRB400EΦ16”“混凝土C30P6”),直接影响工程质量;"
+  },
+  {
+    "technology_TechParams_DeviceName": "需列出关键设备的全称(如“挖掘机”“塔式起重机”“混凝土泵车”),是设备管理的核心;"
+  },
+  {
+    "technology_TechParams_DeviceModel": "需明确设备的规格型号(如“徐工XE200挖掘机”“中联重科TC6013塔式起重机”),用于设备的采购和维护;"
+  },
+  {
+    "technology_TechParams_EquipmentPerformanceParameters": "需包含设备的额定功率、工作效率等(如“塔式起重机最大起重量8t”“混凝土泵车输送量60m³/h”),是设备选型的依据;"
+  },
+  {
+    "technology_TechParams_EquipmentManufacturingTime": "需包含设备的出厂时间"
+  },
+  {
+    "technology_TechParams_EquipmentWeight": "需记录设备的自身重量(如“塔式起重机自重50t”),用于基础设计和运输规划。"
+  },
+  {
+    "technology_PrepWork_MeasurementAndStakeout": "需明确测量的基准点、控制网设置(如“建立施工平面控制网”“放出建筑物轴线”),是施工定位的关键;"
+  },
+  {
+    "technology_PrepWork_TemporaryWaterAndElectricityConsumption": "需计算施工期间的用水、用电量(如“临时用水管径DN100”“临时用电容量500kW”),用于临时设施的设计;"
+  },
+  {
+    "technology_PrepWork_TheSiteIsFlat": "需明确平整的范围、标高(如“平整场地至设计标高±0.000”“压实度达到90%”),是施工场地准备的基础;"
+  },
+  {
+    "technology_PrepWork_Staffing": "需列出各岗位的人员数量(如“项目经理1名”“施工员2名”“钢筋工10名”),是劳动力管理的核心;"
+  },
+  {
+    "technology_PrepWork_EquipmentEntry": "需明确设备的进场时间、运输方式(如“塔式起重机进场时间2026年3月1日”“采用平板车运输”),是设备准备的关键;"
+  },
+  {
+    "technology_PrepWork_SafetyProtectionFacilities": "需列出现场的安全设施(如“安全网”“防护栏杆”“消防栓”),是安全保障的基础;"
+  },
+  {
+    "technology_PrepWork_PersonnelAccess": "需明确通道的形式、位置(如“楼梯间通道”“脚手架斜道”),是人员通行的安全保障。"
+  },
+  {
+    "technology_Process_ConstructionProcess": "需列出工程的主要工序(如“地基处理→基础浇筑→主体结构→装饰装修”),是工艺流程的核心;"
+  },
+  {
+    "technology_Process_ProcessSequence": "需明确工序的先后逻辑(如“先绑扎钢筋后支模板”“先浇筑混凝土后养护”),是流程执行的关键;"
+  },
+  {
+    "technology_Process_ProcessFlowDiagram": "需用图形展示工序的衔接(如“地基处理流程图”“主体结构施工流程图”),是流程可视化的工具;"
+  },
+  {
+    "technology_Operations_ConstructionProcessOperations": "需详细描述各工序的操作步骤(如“钢筋绑扎操作流程”“模板安装操作步骤”),是操作指导的核心;"
+  },
+  {
+    "technology_Operations_ConstructionPoints": "需明确工序的关键要求(如“钢筋绑扎需保证间距均匀”“模板安装需保证垂直度”),是质量控制的关键;"
+  },
+  {
+    "technology_Operations_FAQPrevention": "需列出工序的常见问题及预防措施(如“预防混凝土蜂窝麻面:控制混凝土坍落度”“预防模板漏浆:密封模板缝隙”),是风险防控的重点 focus:;"
+  },
+  {
+    "technology_Operations_ProblemSolvingMeasures": "需明确问题的解决方法(如“混凝土蜂窝处理:剔除松散部分,用高一等级混凝土填补”“模板漏浆处理:用海绵条密封缝隙”),是问题解决的指南;"
+  },
+  {
+    "technology_Inspection_MaterialInspectionUponArrival": "需明确材料的检验项目(如“钢筋的屈服强度检验”“混凝土的抗压强度检验”),是材料质量控制的基础;"
+  },
+  {
+    "technology_Inspection_RandomInspectionOfIncomingComponents": "需明确构配件的抽查比例(如“构配件抽查比例为10%”“每批抽查5件”),是构配件质量控制的手段;"
+  },
+  {
+    "technology_Inspection_ProcessInspectionContent": "需列出各工序的检查项目(如“钢筋绑扎的检查内容:间距、数量、锚固长度”“模板安装的检查内容:垂直度、平整度、支撑稳定性”),是工序检查的核心;"
+  },
+  {
+    "technology_Inspection_ProcessInspectionStandards": "需明确检查的合格标准(如“钢筋间距允许偏差±10mm”“模板垂直度允许偏差5mm”),是工序验收的依据;"
+  },
+  {
+    "safety_SafetySystem_SafetyProductionAssuranceSystemFrameworkDiagram": "安全保证体系的视觉化呈现,需明确体系的核心要素(如组织机构、制度流程、资源保障)及逻辑关系,是公司标准体系的具象化载体;"
+  },
+  {
+    "safety_SafetySystem_CompanyStandardSystemReference": "强调安全保证体系需承接公司现有标准(如《公司安全生产管理办法》《公司安全技术规程》),确保体系的一致性与延续性;"
+  },
+  {
+    "safety_Organization_SafetyManagementOrganization": "基于项目经理为组长的安全工作领导小组,关注岗位组织架构名称类,部门名称类,关系结构类名词;"
+  },
+  {
+    "safety_Organization_PersonnelSafetyResponsibilities": "关注岗位名称类,人名类,责任制度名词类,岗位职责名词类,安全制度名词类;"
+  },
+  {
+    "safety_TechMeasures_OverallSecurityMeasures": "包含保证施工过程中主要工序的人员、材料、机械设备安全所采取的技术措施,以及材料运输、吊装,施工作业区域的临边、临空、洞口安全防护设施、安全母绳布\n置,人员上下(横向)通道布置等,是针对项目整体的安全技术规划(如“施工现场临时用电总体方案”“高空作业总体防护措施”),需覆盖所有施工环节;"
+  },
+  {
+    "safety_TechMeasures_SafetyAssuranceMeasuresForKeyProcesses": "是针对关键工序的具体安全要求(如“深基坑开挖支护措施”“模板安装拆除安全规范”),需明确每一步操作的安全要点;"
+  },
+  {
+    "safety_Monitoring_MonitoringOrganization": "监测监控的责任主体,需明确监测人员的资质(如注册安全工程师、监测技术员)及职责(如数据采集、分析、报告),确保监测工作的专业性;"
+  },
+  {
+    "safety_Monitoring_MonitoringRange": "需覆盖施工区域内的所有风险点(如深基坑周边、高支模体系、临时用电线路),避免遗漏;"
+  },
+  {
+    "safety_Monitoring_MonitoringItems": "需明确监测的具体内容(如深基坑的水平位移、高支模的立杆轴力、临时用电的电压电流),是监测的核心;"
+  },
+  {
+    "safety_Monitoring_MonitoringPointSettings": "需根据风险点的分布确定(如深基坑每10米设置一个位移监测点),需符合《建筑基坑支护技术规程》(JGJ 120-2012)等行业标准;"
+  },
+  {
+    "safety_Monitoring_MonitoringInstrumentsAndEquipment": "需明确仪器的名称(如全站仪、测斜仪、应力传感器)、型号(如徕卡TS60全站仪)及精度(如0.5秒级),确保数据的准确性;"
+  },
+  {
+    "safety_Monitoring_MonitoringMethods": "需明确数据采集的方式(如人工读数、自动采集)、及数据处理方法(如统计分析、趋势预测),是监测的关键环节;"
+  },
+  {
+    "safety_Monitoring_MonitoringFrequency": "需明确监测频率,(如深基坑每天一次,高支模每周两次)。"
+  },
+  {
+    "safety_Monitoring_WarningValuesAndControlValues": "需根据设计文件及行业标准确定(如深基坑水平位移预警值为30mm,控制值为50mm),是判断风险的重要依据;"
+  },
+  {
+    "safety_Monitoring_InformationFeedbackMechanism": "监测数据的传递流程(如监测人员→项目安全部→项目经理→公司总部),需明确反馈的时间要求(如实时反馈、每日汇总),确保风险及时处理。"
+  },
+  {
+    "safety_Emergency_EmergencyProcedures": "应采用公司标准应急处理程序图(附件16),应急响应的步骤流程(如“事故报告→现场警戒→人员疏散→救援实施→善后处理”),需明确每一步的责任部门及时间要求,确保响应及时;"
+  },
+  {
+    "safety_Emergency_EmergencyMeasures": "应根据方案实施过程潜在的危险源,判断出可能造成的伤害类型,制定出有针对性的救援措施,保证在事故发生后伤者能得到有效和及时的救治,如触电、有毒有害气体中毒、高处坠落、物体打击、施工现场及驻地火灾等事故,针对不同类型事故的具体处理方法(如“火灾事故使用干粉灭火器扑救”“坍塌事故使用千斤顶支撑”),需明确操作要点(如灭火器的使用方法、千斤顶的支撑位置),确保救援有效;"
+  },
+  {
+    "safety_Emergency_EmergencySuppliesAndEquipmentSupport": "应根据事故的不同,以表格的形式说明救援的物品名称、规格型号、单位、数量、监管人、联系电话等内容,应急处置的物质基础,需明确物资的名称(如灭火器、急救箱、千斤顶)、数量(如每100平方米配备2个灭火器)、存放位置(如施工现场入口处)及维护要求(如每月检查一次灭火器压力),确保物资随时可用;"
+  },
+  {
+    "safety_Emergency_TrafficManagementAndMedicalRescue": "应以表格的形式明确施工工点附近的医疗救援机构名称、联系电话、距离等,并附应急救援线路图;"
+  },
+  {
+    "safety_Emergency_Post-disposal": "包括善后处理、调查与评估、恢复生产等三个方面,事故后的恢复工作,需明确善后处理(如伤亡人员家属安抚、财产损失统计)、事故调查(如原因分析、责任认定评估)及整改措施(如完善安全制度、加强培训),避免事故重复发生;"
+  },
+  {
+    "quality_QualitySystem_QualityAssuranceSystemFramework": "应引用公司标准体系框图,质量体系的视觉化呈现,需明确体系的核心要素(如组织机构、制度流程、资源保障)及逻辑关系,是体系落地的框架基础;"
+  },
+  {
+    "quality_QualitySystem_QualityManagementOrganization": "基于项目经理为组长的工作领导小组,小组中包括项目经理、项目总工、质量总监、工程部门、质检部门、专业分包单位(协作队伍)项目负责人和项目技术负责人等,需明确层级(如公司级、项目级、班组级)及组成部门(如质量部、工程部、技术部),形成“横向到边、纵向到底”的管理网络;"
+  },
+  {
+    "quality_QualitySystem_PersonnelResponsibilities": "需细化每个岗位的质量责任(如项目经理的“第一责任人”职责、质量员的“现场监督”职责),避免职责模糊导致的管理漏洞;"
+  },
+  {
+    "quality_QualityGoals_DecompositionOfQualityObjectives": "根据施工合同和业主要求填写,需将总目标拆解为分部(基础、主体、装饰)、分项工程的具体目标(如“主体结构混凝土强度合格率100%”),是目标落地的关键;\n**重点** focus:\n目标标准词汇类、合同条款类、具体工程名称类、量化数值类、数值单位类。"
+  },
+  {
+    "quality_Excellence_OverallPlanForEngineeringExcellence": "需明确创优的阶段目标(如“基础工程创优”“主体工程创优”)及关键节点,是创优工作的路线图;"
+  },
+  {
+    "quality_Excellence_TechnicalPreparation": "需涵盖BIM技术应用、施工方案优化等,为创优提供技术支撑;"
+  },
+  {
+    "quality_Excellence_ProcessControl": "需聚焦关键工序(如“大体积混凝土浇筑”“钢结构安装”),打造精品工序;"
+  },
+  {
+    "quality_Excellence_DetailedTreatment": "需优化节点做法(如“墙面抹灰阴阳角顺直”“防水卷材搭接严密”),提升工程观感质量;"
+  },
+  {
+    "quality_Excellence_NewTechnologyPromotion": "需应用“四新技术”(新技术、新材料、新工艺、新设备),提升创优的技术含量;"
+  },
+  {
+    "quality_Excellence_PreparationOfApplicationMaterials": "需整理创优所需的资料(如工程质量报告、技术创新成果),是创优申报的核心材料;"
+  },
+  {
+    "quality_Excellence_EngineeringDataArchiving": "需确保资料真实、完整,符合创优评审要求。"
+  },
+  {
+    "quality_QualityControl_RawMaterialInspection": "需执行“三证一检”(合格证、质检报告、生产许可证+进场复检),确保材料质量;"
+  },
+  {
+    "quality_QualityControl_PhysicalProjectQualityAcceptance": "需按分项(如“钢筋绑扎”)、分部工程(如“基础工程”)进行验收,符合规范要求;"
+  },
+  {
+    "quality_QualityControl_PreventionAndControlOfCommonQualityDefectsInProcesses": "需针对常见问题(如“墙面空鼓”“屋面渗漏”)制定专项措施(如“抹灰前基层凿毛”“防水附加层施工”),减少质量缺陷;"
+  },
+  {
+    "quality_QualityControl_SeasonalConstructionQualityAssuranceMeasures": "需针对冬期(混凝土保温)、雨期(防水加强)、高温(混凝土保湿)制定专项措施,确保施工质量;"
+  },
+  {
+    "environment_EnvSystem_EnvironmentalAssuranceSystemFramework": "环境保证体系的视觉化呈现,需明确体系的核心要素(如组织机构、制度流程、资源保障)及逻辑关系,是公司标准体系的具象化载体;"
+  },
+  {
+    "environment_EnvSystem_CompanyStandardSystemReference": "应引用公司标准体系框图,强调环境保证体系需承接公司现有标准(如《公司环境管理体系手册》《公司环境保护管理办法》),确保体系的一致性与延续性;"
+  },
+  {
+    "environment_EnvOrg_EnvironmentalAssuranceSystemFramework": "包含管理人员姓名、职务、职责,环境管理的责任主体,基于项目经理为组长的工作领导小组,小组中包括项目经理、项目副经理、项目总工、工程部门、质检部门、安全环保部门、专业分包单位(协作队伍)项目负责人和项目技术负责人等,需明确机构的层级(如公司级、项目级、班组级)及组成部门(如环境部、工程部、技术部),形成“横向到边、纵向到底”的管理网络;"
+  },
+  {
+    "environment_EnvOrg_EnvironmentalManagementJobResponsibilities": "需明确各岗位的环境责任(如项目经理的“环境第一责任人”职责、环境专员的“现场巡查”职责),是组织保证的基石;"
+  },
+  {
+    "environment_EnvOrg_ResponsibilityAssessmentMechanism": "对环境职责履行情况的评价方式(如月度考核、年度评优),需与环境绩效挂钩(如奖金发放、晋升晋级),强化责任意识。"
+  },
+  {
+    "environment_EnvProtection_EnvironmentalSanitationGuaranteeMeasuresForOfficeAndLiving_areas": "需明确责任分工(如保洁人员配置、卫生区域划分)及管理流程(如每日清扫、每周检查),确保环境整洁;"
+  },
+  {
+    "environment_EnvProtection_SoilAndWaterConservationMeasuresInTheConstructionArea": "需通过“截(截水沟)、排(排水沟)、拦(拦挡坝)、护(边坡防护)”综合措施,减少雨水对裸露土壤的冲刷;"
+  },
+  {
+    "environment_EnvProtection_NoiseEmissionMonitoring": "需按照《建筑施工场界环境噪声排放标准》(GB 12523-2011)要求,在施工现场边界设置监测点,每日监测1次,记录等效声级(Leq)和最大声级(Lmax);"
+  },
+  {
+    "environment_EnvProtection_WaterPollutionPreventionAndControlMeasures": "需在搅拌机、运输车清洗处设置沉淀池,施工废水经沉淀后回用(如洒水降尘),避免直接排入市政管网;"
+  },
+  {
+    "environment_EnvProtection_AirPollutionPreventionAndControlMeasures": "需采取“洒水降尘、裸土覆盖、车辆冲洗、道路硬化”等措施,确保施工现场目测扬尘高度小于1.5m(土方作业阶段)或0.5m(结构施工阶段)。"
+  },
+  {
+    "Management_Managers_ConstructionManagementPersonnelList": "需以表格形式明确项目管理人员(如项目经理、项目书记、项目总工、项目副经理、质量总监、安全总监、各职能部门、主管技术员、测量员、质检员,以及专业分包单位(协作队伍)项目负责人和项目技术负责人等)的姓名、岗位及联系方式,是人员管理的基础台账;"
+  },
+  {
+    "Management_Managers_JobResponsibilitiesList": "需细化每个管理岗位的职责(如项目经理的“项目全面管理”职责、技术负责人的“技术方案审核”职责),避免职责模糊导致的管理漏洞;"
+  },
+  {
+    "Management_SafetyStaff_ListOfFullTimeSafetyProductionManagementPersonnel": "需以表格形式明确专职安全员(如项目安全总监、专职安全员)的姓名、岗位及联系方式,是安全管理的核心台账;"
+  },
+  {
+    "Management_SafetyStaff_SafetyProductionQualificationCertificate": "需明确证书类型(如“建筑施工企业专职安全生产管理人员证书”)、编号及有效期,是上岗的必备资质;"
+  },
+  {
+    "Management_SafetyStaff_SafetyProductionManagementJobResponsibilities": "需细化专职安全员的职责(如“现场安全检查”“隐患整改监督”“安全培训实施”),确保安全管理工作落地;"
+  },
+  {
+    "Management_SpecialWorkers_ListOfSecialOperationsPersonnel": "需以表格形式明确特种作业人员(如建筑电工、建筑架子工、建筑起重机械司机等)的姓名、工种及联系方式,是特种作业管理的基础台账;"
+  },
+  {
+    "Management_SpecialWorkers_SpecialOperationsQualificationCertificate": "需明确证书类型(如“建筑施工特种作业操作资格证书”)、编号及有效期,是上岗的必备资质;"
+  },
+  {
+    "Management_SpecialWorkers_SpecialOperationsJobResponsibilities": "需明确作业人员从事的具体工种(如“塔式起重机司机”“高处作业吊篮安装拆卸工”),细化特种作业人员的职责是工种管理的关键;"
+  },
+  {
+    "Management_OtherWorkers_NumberOfManagementPersonnelInProfessionalSubcontractingUnits": "需明确分包单位(如劳务分包、专业分包)的管理人员(如分包项目经理、技术负责人)数量,是分包管理的基础;"
+  },
+  {
+    "Management_OtherWorkers_NumberOfWorkersInDifferentJobCategories": "需以表格形式明确各工种(如木工、钢筋工、混凝土工、砌筑工等)的作业人员数量,是劳动力调配的依据;"
+  },
+  {
+    "Management_OtherWorkers_WorkersLlog": "需记录作业人员的姓名、工种、身份证号、联系方式等信息,是人员管理的重要档案;"
+  },
+  {
+    "acceptance_Standards_NationalStandardsSpecificationsAndOperatingProcedures": "是验收的基础依据,需明确具体规范名称(如JTG F80/1-2017),避免使用“国家规范”等泛化表述;"
+  },
+  {
+    "acceptance_Standards_IndustryStandardOperatingProcedures": "需指向具体行业的内部文件(如行业标准(如《公路桥涵施工技术规范》JTG_T 3650-2020),体现行业管理要求;"
+  },
+  {
+    "acceptance_Standards_SichuanRoadAndBridgeManagementRegulations": "需关联企业管理办法(如《四川路桥施工验收管理办法》),体现企业特色和企业管理要求;"
+  },
+  {
+    "acceptance_Standards_ManagementRegulationsOfLuqiaoGroup": "需关联集团管理办法(如《路桥集团专项施工方案验收条件》),体现集团特色和集团管理要求;"
+  },
+  {
+    "acceptance_Standards_ManagementRegulationsOfBridgeCompany": "需关联桥梁施工管理办法(如《桥梁施工安全操作规程》),体现桥梁施工重点 focus:和桥梁施工标准管理要求;"
+  },
+  {
+    "acceptance_Procedure_OnsiteAcceptance": "需明确验收对象(如“钢筋进场验收”“塔式起重机进场验收”),是质量控制的第一道防线;"
+  },
+  {
+    "acceptance_Procedure_ProcessAcceptance": "需关联施工工序(如“混凝土浇筑过程验收”“钢筋绑扎过程验收”),强调动态管控;"
+  },
+  {
+    "acceptance_Procedure_StageAcceptance": "需对应工程阶段(如“基础工程阶段验收”“主体结构阶段验收”),是阶段性成果确认的关键;"
+  },
+  {
+    "acceptance_Procedure_CompletionAcceptance": "需明确验收内容(如“工程竣工预验收”“专项施工方案完工验收”),是竣工验收的前提。"
+  },
+  {
+    "acceptance_Content_SafetyProductionConditionAcceptance": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,需细化具体内容(如“安全防护设施验收”包括“安全网张挂验收”“防护栏杆安装验收”),避免“安全生产验收”等泛化表述;"
+  },
+  {
+    "acceptance_Content_ResourceAllocationAcceptance": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,需关联资源类型(如“人员配置验收”包括“特种作业人员资质验收”“管理人员到位验收”),体现资源的针对性;"
+  },
+  {
+    "acceptance_Content_ConstructionProcessAcceptance": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,需明确工艺环节(如“模板安装工艺验收”包括“模板垂直度验收”“模板拼接缝验收”),强调工艺的标准化;"
+  },
+  {
+    "acceptance_Content_AcceptanceOfMechanicalEquipment": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,需指向具体设备(如“塔式起重机验收”包括“设备型号验收”“安全装置验收”),确保设备符合施工要求。"
+  },
+  {
+    "acceptance_Content_TemporarySupportStructure": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,专项施工方案及审批记录、技术交底记录、构配件质量证明文件(合格证/检测报告)、地基承载力报告、搭设过程检查记录、荷载试验报告(高支模/大跨度)、验收记录表(含实测数据/影像资料)、整改复查记录。"
+  },
+  {
+    "acceptance_Content_PersonnelOperationPlatform": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,架体材质(如钢管无裂纹、弯曲,型钢无开焊);架体构造(立杆间距、剪刀撑设置、连墙件固定);稳定性(移动式平台刹车装置、落地式平台基础坚实度);荷载限制(平台荷载不超过设计值,悬挂限载标志);防护栏杆(高度≥1.2m,竖向栏杆间距≤1.5m,底部设挡脚板);平台铺板(满铺、固定,无空隙);登高扶梯(防滑、固定,与平台连接牢固);安全网(平台周边设置密目网或安全平网)。"
+  },
+  {
+    "acceptance_Content_SafetyProtectionFacilities": "验收表格中要明确项目的具体验收标准,验收标准应尽量量化到具体参数或标准,需结合场景需求(如建筑施工中的基坑临边防护、电梯井防护门)、功能定位(如预防事故的防护栏杆、减少事故影响的安全网)、技术要求(如材质、构造、固定方式)。其核心逻辑是“隔离危险、承接冲击、提醒注意”"
+  },
+  {
+    "acceptance_Timing_AcceptanceTimeOfSpecialConstructionPlan": "需关联具体表格(如“《专项施工方案验收条件一览表》预估时间”),体现时间的可追溯性;"
+  },
+  {
+    "acceptance_Timing_AcceptanceTimeAdjustment": "需明确调整依据(如“根据施工进度调整验收时间”),避免“时间调整”等泛化表述;"
+  },
+  {
+    "acceptance_Timing_AcceptanceConditionTriggerTime": "需明确时间节点(如“具备验收条件后15日内组织验收”),强调时效性。"
+  },
+  {
+    "acceptance_Personnel_ConstructionUnitAcceptancePersonnel": "需明确具体角色(如“建设单位项目负责人”),避免“建设单位人员”等泛化表述;由施工作业班组在施工过程中自行对照方案自检,施工完成后由方案编制负责人、项目经理、项目副经理、项目技术负责人、安全环保处、工程处、机料处、合同处、专业分包单位(协作队伍)项目负责人和项目技术负责人等部门人员参加方案验收。"
+  },
+  {
+    "acceptance_Personnel_DesignUnitAcceptancePersonnel": "需明确验收人员姓名,关联专业(如“设计单位专业工程师”),体现设计的专业性;由施工作业班组在施工过程中自行对照方案自检,施工完成后由方案编制负责人、项目经理、项目副经理、项目技术负责人、安全环保处、工程处、机料处、合同处、专业分包单位(协作队伍)项目负责人和项目技术负责人等部门人员参加方案验收。"
+  },
+  {
+    "acceptance_Personnel_ConstructionUnitAcceptancePersonnel": "需明确验收人员姓名,指向管理岗位(如“施工单位项目经理”“施工单位技术负责人”),强调施工单位的主体责任;由施工作业班组在施工过程中自行对照方案自检,施工完成后由方案编制负责人、项目经理、项目副经理、项目技术负责人、安全环保处、工程处、机料处、合同处、专业分包单位(协作队伍)项目负责人和项目技术负责人等部门人员参加方案验收。"
+  },
+  {
+    "acceptance_Personnel_InspectionPersonnelOfTheSupervisionUnit": "需明确验收人员姓名,监理角色(如“总监理工程师”“专业监理工程师”),体现监理的监督职责;由施工作业班组在施工过程中自行对照方案自检,施工完成后由方案编制负责人、项目经理、项目副经理、项目技术负责人、安全环保处、工程处、机料处、合同处、专业分包单位(协作队伍)项目负责人和项目技术负责人等部门人员参加方案验收。"
+  },
+  {
+    "acceptance_Personnel_MonitoringUnitAcceptancePersonnel": "需明确验收人员姓名,关联监测内容(如“监测项目负责人”“监测技术员”),确保监测数据的准确性;由施工作业班组在施工过程中自行对照方案自检,施工完成后由方案编制负责人、项目经理、项目副经理、项目技术负责人、安全环保处、工程处、机料处、合同处、专业分包单位(协作队伍)项目负责人和项目技术负责人等部门人员参加方案验收。"
+  },
+  {
+    "other_Calculations_ContentRequirements": "专项施工方案中包含承重结构、重要临时设施、设备选型、吊绳吊具受力计算;地基承载力等工作内容编制的专项计算书,内容应包含编制依据、工程简况、方案简述、设计参数、主要工况计算、局部计算、结论及建议。"
+  },
+  {
+    "other_Calculations_CalculationOfMainWorkingConditions": "需针对关键施工工况(如“盖梁浇筑工况”“桩基础施工工况”),包含“本工况描述”“应力/变形/反力/屈曲分析结果”,是计算书的核心内容;"
+  },
+  {
+    "other_Calculations_LocalCalculation": "需对于受力集中、结构复杂的局部重要节点进行细部分析(如“钢管桩与横梁连接节点”“模板支撑体系节点”),确保结构安全;"
+  },
+  {
+    "other_Drawings_OverallLayoutPlan": "需展示项目整体布局(如“施工便道”“材料堆放区”“临时设施”),是施工部署的可视化基础;"
+  },
+  {
+    "other_Drawings_ConstructionSiteLayoutPlan": "需围绕“空间规划”“功能实现”“安全文明”三大核心,覆盖从边界界定到具体设施的全流程要素。"
+  },
+  {
+    "other_Drawings_LongitudinalElevationLayoutOfSupportingStructure": "需明确支撑体系(如“钢管桩支架”“满堂脚手架”)的纵向布置(如“桩长”“间距”“标高”),是结构安全的关键依据;"
+  },
+  {
+    "other_Drawings_Cross-sectionalLayoutDiagram": "需围绕“断面类型”“组成要素”“尺寸参数”“坡度设置”“附属设施”五大维度,覆盖道路、桥梁等工程的通用及专业要素。"
+  },
+  {
+    "other_Drawings_FloorPlan": "需围绕“空间布局”“功能分区”“施工支持”三大核心,覆盖从区域划分到具体设施的全流程要素。"
+  },
+  {
+    "other_Drawings_DetailedStructuralDiagram": "需细化关键节点(如“模板拼接节点”“支撑体系连接节点”),标注尺寸、材料及工艺要求,指导现场施工;"
+  },
+  {
+    "other_Drawings_FormworkLayoutDrawing": "需明确模板的平面位置(如“柱模板”“梁模板”)、尺寸及支撑方式,确保模板安装符合设计要求。"
+  },
+  {
+    "other_Drawings_TemplateConstructionDiagram": "需覆盖模板体系组成、构造细节、支撑系统、节点处理及精度控制等全流程要素。"
+  },
+  {
+    "other_Tables_ConstructionScheduleNetworkDiagram": "需用节点表示工序逻辑关系(如“桩基础施工→承台施工→盖梁施工”),是进度控制的核心工具;"
+  },
+  {
+    "other_Tables_ConstructionScheduleGanttChart": "围绕“时间维度”“任务要素”“进度关系”“调整控制”四大核心,覆盖从计划编制到动态监控的全流程。"
+  },
+  {
+    "other_Tables_HazardAnalysisAndResponseMeasuresTable": "需识别施工中的危险源(如“高处坠落”“物体打击”),制定针对性应对措施(如“设置防护栏杆”“佩戴安全带”),是安全保障的关键文档;"
+  },
+  {
+    "other_Tables_ScannedCopyOfTheCertificateOfFulltimSafetyManagementPersonnel": "需包含“安全生产考核合格证书”“证书编号”“有效期”,确保管理人员资质符合要求;"
+  },
+  {
+    "other_Tables_ScannedCopyOfSpecialOperationsPersonnelsCertificate": "需围绕“信息真实性”“管理规范性”“使用便捷性”三大核心,覆盖证件内容、“证书编号”、“有效期”、法规标准四大维度"
+  },
+  {
+    "other_Tables_ScannedCopyOfProfessionalSubcontractorsQualifications": "需包含“营业执照”“资质证书”“安全生产许可证”,确保分包单位具备施工能力。"
+  },
+  {
+    "other_Team": "需明确验收的前提条件(如“计算书完成”“设计图审核通过”),是验收的流程依据;"
+  },
+  {
+    "other_Team_PreparePersonnelInformation": "需包含“姓名”“职务”“职称”(如“张三 技术员 助理工程师”),确保编制人员具备专业能力;"
+  },
+  {
+    "other_Team_ReviewerInformation": "需包含“姓名”“职务”“职称”(如“李四 项目技术负责人 工程师”),确保审核流程的严谨性;"
+  },
+  {
+    "other_Team_ApprovalPersonnelInformation": "需包含“姓名”“职务”“职称”(如“王五 项目经理 高级工程师”),确保方案符合项目整体要求"
+  }
+]

+ 39 - 0
core/construction_write/workflows/outline_workflow.py

@@ -16,6 +16,8 @@ from langgraph.checkpoint.memory import MemorySaver
 from foundation.observability.logger.loggering import write_logger as logger
 from ..component.state_models import OutlineGenerationState
 from ..component.outline_generator import OutlineGenerator
+import os
+import json
 
 
 class OutlineWorkflow:
@@ -198,9 +200,46 @@ class OutlineWorkflow:
         # 编译图,使用内存检查点保存器
         compiled_graph = workflow.compile(checkpointer=self.checkpoint_saver)
 
+        # 保存工作流图到 temp/construction_write 目录
+        self._save_workflow_graph(compiled_graph, "temp/construction_write/outline_workflow.png")
+
         logger.info("大纲生成 LangGraph 工作流图构建完成")
         return compiled_graph
 
+    def _save_workflow_graph(self, compiled_graph: StateGraph, output_path: str):
+        """
+        保存 LangGraph 工作流图为 PNG 图片
+
+        Args:
+            compiled_graph: 编译后的 LangGraph 工作流图
+            output_path: 输出文件路径
+        """
+        try:
+            # 确保输出目录存在
+            output_dir = os.path.dirname(output_path)
+            if output_dir and not os.path.exists(output_dir):
+                os.makedirs(output_dir, exist_ok=True)
+                logger.info(f"创建输出目录:{output_dir}")
+
+            # 使用 graphviz 保存图片
+            # 需要安装 graphviz 和 graphviz Python 包
+            try:
+                graph = compiled_graph.get_graph()
+                graph_image = graph.draw_mermaid_png()
+                with open(output_path, "wb") as f:
+                    f.write(graph_image)
+                logger.info(f"工作流图已保存到:{output_path}")
+            except Exception as graphviz_error:
+                logger.warning(f"Graphviz 保存失败:{str(graphviz_error)}, 尝试使用 JSON 格式保存")
+                # 备用方案:保存为 JSON 格式
+                json_path = output_path.replace(".png", ".json")
+                with open(json_path, "w", encoding="utf-8") as f:
+                    json.dump(compiled_graph.get_graph().to_json(), f, indent=2, ensure_ascii=False)
+                logger.info(f"工作流图已保存到 (JSON 格式): {json_path}")
+
+        except Exception as e:
+            logger.warning(f"保存工作流图失败:{str(e)}")
+
     # ==================== 条件判断函数 ====================
 
     def _check_terminate_or_error(self, state: OutlineGenerationState) -> str:

+ 27 - 0
data_pipeline/sgfa_bz_data/片段结构.json

@@ -0,0 +1,27 @@
+{
+[
+{
+  "oringin_content": "片段1",
+  "chapter_classification":"plan_type",
+  "matedata": {
+    "file_name": "G85G76 重庆(川渝界)至成都高速公路扩容工程施工总承包ZCB5-TJ2标段",
+    "plan_type": "桥梁下部结构专项施工方案",
+    "file_path": "D:/G85G76/G85G76_0.doc",
+    "file_create_time": "2021-09-01 09:09:09"
+  }
+
+},
+{
+  "oringin_content": "片段2",
+  "chapter_classification":"plan_type",
+  "matedata": {
+    "file_name": "G85G76 重庆(川渝界)至成都高速公路扩容工程施工总承包ZCB5-TJ2标段",
+    "plan_type": "桥梁下部结构专项施工方案",
+    "file_path": "D:/G85G76/G85G76_0.doc",
+    "file_create_time": "2021-09-01 09:09:09"
+  }
+
+},
+]
+
+}

+ 8 - 2
foundation/ai/agent/generate/model_generate.py

@@ -222,7 +222,8 @@ class GenerateModelClient:
         system_prompt: Optional[str] = None,
         user_prompt: Optional[str] = None,
         prompt: Optional[str] = None,
-        timeout: Optional[int] = None
+        timeout: Optional[int] = None,
+        model_name: Optional[str] = None
     ):
         """模型流式生成(同步生成器)
 
@@ -240,6 +241,7 @@ class GenerateModelClient:
             user_prompt: 用户提示词字符串
             prompt: 单条用户提示词字符串
             timeout: 超时时间(秒)
+            model_name: 模型名称(可选),支持 doubao/qwen/deepseek/gemini 等
 
         Yields:
             str: 生成的文本块
@@ -251,6 +253,10 @@ class GenerateModelClient:
         current_timeout = timeout or self.default_timeout
 
         try:
+            # 选择模型
+            llm_to_use = self.model_handler.get_model_by_name(model_name) if model_name else self.llm
+            logger.info(f"[模型流式调用] 使用{'指定' if model_name else '默认'}模型:{model_name or 'default'}, trace_id: {trace_id}")
+
             logger.info(f"[模型流式调用] 开始处理 trace_id: {trace_id}, 超时配置: {current_timeout}s")
 
             # 构建消息列表
@@ -262,7 +268,7 @@ class GenerateModelClient:
                 task_prompt_info=task_prompt_info
             )
 
-            response = self.llm.stream(final_messages)
+            response = llm_to_use.stream(final_messages)
 
             chunk_count = 0
             for chunk in response:

+ 285 - 0
foundation/ai/agent/generate/model_generate.py.bak

@@ -0,0 +1,285 @@
+# !/usr/bin/ python
+# -*- coding: utf-8 -*-
+'''
+@Project    : lq-agent-api
+@File       :model_generate.py
+@IDE        :PyCharm
+@Author     :
+@Date       :2025/7/14 14:22
+'''
+
+from langchain_core.prompts import ChatPromptTemplate
+from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage
+from foundation.ai.models.model_handler import model_handler
+from foundation.observability.logger.loggering import review_logger as logger
+import asyncio
+import time
+from typing import Optional, Callable, Any, List, Union
+
+class GenerateModelClient:
+    """
+        主要是生成式模型
+    """
+
+    def __init__(self, default_timeout: int = 60, max_retries: int = 3, backoff_factor: float = 1.0):
+        # 获取默认模型
+        self.llm = model_handler.get_models()
+        self.chat = self.llm  # 当前chat和llm使用相同模型
+
+        # 配置参数
+        self.default_timeout = default_timeout
+        self.max_retries = max_retries
+        self.backoff_factor = backoff_factor
+
+        # 保存model_handler引用,用于动态获取模型
+        self.model_handler = model_handler
+
+    async def _retry_with_backoff(self, func: Callable, *args, timeout: Optional[int] = None, **kwargs):
+        """
+        带指数退避的重试机制,每次重试都有独立的超时控制
+        """
+        current_timeout = timeout or self.default_timeout
+
+        for attempt in range(self.max_retries + 1):
+            try:
+                # 每次重试都有独立的超时时间
+                return await asyncio.wait_for(
+                    func(*args, **kwargs),
+                    timeout=current_timeout
+                )
+            except asyncio.TimeoutError:
+                if attempt == self.max_retries:
+                    logger.error(f"[模型调用] 达到最大重试次数 {self.max_retries},最终超时")
+                    raise TimeoutError(f"模型调用在 {self.max_retries} 次重试后均超时")
+
+                wait_time = self.backoff_factor * (2 ** attempt)
+                logger.warning(f"[模型调用] 第 {attempt + 1} 次超时, {wait_time}秒后重试...")
+                await asyncio.sleep(wait_time)
+            except Exception as e:
+                if attempt == self.max_retries:
+                    logger.error(f"[模型调用] 达到最大重试次数 {self.max_retries},最终失败: {str(e)}")
+                    raise
+
+                wait_time = self.backoff_factor * (2 ** attempt)
+                logger.warning(f"[模型调用] 第 {attempt + 1} 次尝试失败: {str(e)}, {wait_time}秒后重试...")
+                await asyncio.sleep(wait_time)
+
+    async def get_model_generate_invoke(
+        self,
+        trace_id: str,
+        task_prompt_info: Optional[dict] = None,
+        messages: Optional[List[BaseMessage]] = None,
+        system_prompt: Optional[str] = None,
+        user_prompt: Optional[str] = None,
+        prompt: Optional[str] = None,
+        timeout: Optional[int] = None,
+        model_name: Optional[str] = None
+    ) -> str:
+        """模型非流式生成(异步)
+
+        支持多种调用方式(优先级从高到低):
+        1. messages: 直接传入 LangChain Message 对象列表
+        2. system_prompt + user_prompt: 分别传入系统和用户提示词
+        3. prompt: 传入单条用户提示词字符串
+        4. task_prompt_info: 传入包含 ChatPromptTemplate 的字典(兼容旧接口)
+
+        Args:
+            trace_id: 追踪ID
+            task_prompt_info: 任务提示词信息(兼容旧接口),需包含 format_messages() 方法
+            messages: LangChain Message 对象列表(如 [SystemMessage, HumanMessage])
+            system_prompt: 系统提示词字符串
+            user_prompt: 用户提示词字符串
+            prompt: 单条用户提示词字符串(无系统提示时使用)
+            timeout: 超时时间(秒),默认使用构造时的 default_timeout
+            model_name: 模型名称(可选),支持 doubao/qwen/deepseek/gemini 等
+
+        Returns:
+            str: 模型生成的文本内容
+
+        Raises:
+            ValueError: 参数组合错误
+            TimeoutError: 调用超时
+            Exception: 模型调用异常
+
+        Examples:
+            # 方式1: 使用 Message 列表(推荐)
+            messages = [SystemMessage(content="你是专家"), HumanMessage(content="请分析...")]
+            result = await client.get_model_generate_invoke("trace-001", messages=messages)
+
+            # 方式2: 分别传入系统和用户提示词
+            result = await client.get_model_generate_invoke(
+                "trace-001",
+                system_prompt="你是专家",
+                user_prompt="请分析..."
+            )
+
+            # 方式3: 传入单条提示词
+            result = await client.get_model_generate_invoke("trace-001", prompt="请分析...")
+
+            # 方式4: 兼容旧接口(使用 PromptLoader)
+            task_prompt_info = {"task_prompt": chat_template}
+            result = await client.get_model_generate_invoke("trace-001", task_prompt_info=task_prompt_info)
+        """
+        start_time = time.time()
+        current_timeout = timeout or self.default_timeout
+
+        try:
+            # 选择模型
+            llm_to_use = self.model_handler.get_model_by_name(model_name) if model_name else self.llm
+            logger.info(f"[模型调用] 使用{'指定' if model_name else '默认'}模型: {model_name or 'default'}, trace_id: {trace_id}")
+
+            # 构建消息列表(按优先级)
+            final_messages = self._build_messages(
+                messages=messages,
+                system_prompt=system_prompt,
+                user_prompt=user_prompt,
+                prompt=prompt,
+                task_prompt_info=task_prompt_info
+            )
+
+            # 定义模型调用函数,使用原生 ainvoke
+            async def _invoke():
+                return await llm_to_use.ainvoke(final_messages)
+
+            # 调用带重试机制
+            response = await self._retry_with_backoff(_invoke, timeout=current_timeout)
+
+            elapsed_time = time.time() - start_time
+            logger.info(f"[模型调用] 成功 trace_id: {trace_id}, 耗时: {elapsed_time:.2f}s")
+            return response.content
+
+        except asyncio.TimeoutError:
+            elapsed_time = time.time() - start_time
+            logger.error(f"[模型调用] 超时 trace_id: {trace_id}, 耗时: {elapsed_time:.2f}s, 超时阈值: {current_timeout}s")
+            raise TimeoutError(f"模型调用超时,trace_id: {trace_id}")
+
+        except Exception as e:
+            elapsed_time = time.time() - start_time
+            logger.error(f"[模型调用] 异常 trace_id: {trace_id}, 耗时: {elapsed_time:.2f}s, 错误: {type(e).__name__}: {str(e)}")
+            raise
+
+    def _build_messages(
+        self,
+        messages: Optional[List[BaseMessage]] = None,
+        system_prompt: Optional[str] = None,
+        user_prompt: Optional[str] = None,
+        prompt: Optional[str] = None,
+        task_prompt_info: Optional[dict] = None
+    ) -> List[BaseMessage]:
+        """构建消息列表(内部方法)
+
+        优先级:messages > system_prompt+user_prompt > prompt > task_prompt_info
+        """
+        # 方式1: 直接使用传入的 Message 列表
+        if messages is not None:
+            if not isinstance(messages, list):
+                raise ValueError("messages 必须是列表")
+            if len(messages) == 0:
+                raise ValueError("messages 不能为空列表")
+            logger.debug(f"使用传入的 messages 列表,共 {len(messages)} 条消息")
+            return messages
+
+        # 方式2: system_prompt + user_prompt
+        if system_prompt is not None and user_prompt is not None:
+            logger.debug("使用 system_prompt + user_prompt 构建消息")
+            return [SystemMessage(content=system_prompt), HumanMessage(content=user_prompt)]
+
+        # 方式3: 单独 system_prompt(可能是特殊情况)
+        if system_prompt is not None:
+            logger.debug("使用单独的 system_prompt 构建消息")
+            return [SystemMessage(content=system_prompt)]
+
+        # 方式4: 单条 prompt 字符串
+        if prompt is not None:
+            logger.debug("使用单条 prompt 字符串构建消息")
+            return [HumanMessage(content=prompt)]
+
+        # 方式5: 兼容旧接口 task_prompt_info
+        if task_prompt_info is not None:
+            if "task_prompt" not in task_prompt_info:
+                raise ValueError("task_prompt_info 必须包含 'task_prompt' 键")
+            task_prompt = task_prompt_info["task_prompt"]
+            if hasattr(task_prompt, 'format_messages'):
+                logger.debug("使用 task_prompt_info 中的 ChatPromptTemplate 构建消息")
+                return task_prompt.format_messages()
+            elif isinstance(task_prompt, str):
+                logger.debug("使用 task_prompt_info 中的字符串构建消息")
+                return [HumanMessage(content=task_prompt)]
+            else:
+                raise ValueError(f"task_prompt 类型不支持: {type(task_prompt)}")
+
+        # 没有提供任何有效参数
+        raise ValueError(
+            "必须提供以下参数之一: "
+            "messages, system_prompt+user_prompt, prompt, 或 task_prompt_info"
+        )
+
+    def get_model_generate_stream(
+        self,
+        trace_id: str,
+        task_prompt_info: Optional[dict] = None,
+        messages: Optional[List[BaseMessage]] = None,
+        system_prompt: Optional[str] = None,
+        user_prompt: Optional[str] = None,
+        prompt: Optional[str] = None,
+        timeout: Optional[int] = None,
+        model_name: Optional[str] = None
+    ):
+        """模型流式生成(同步生成器)
+
+        支持多种调用方式(优先级从高到低):
+        1. messages: 直接传入 LangChain Message 对象列表
+        2. system_prompt + user_prompt: 分别传入系统和用户提示词
+        3. prompt: 传入单条用户提示词字符串
+        4. task_prompt_info: 传入包含 ChatPromptTemplate 的字典(兼容旧接口)
+
+        Args:
+            trace_id: 追踪ID
+            task_prompt_info: 任务提示词信息(兼容旧接口)
+            messages: LangChain Message 对象列表
+            system_prompt: 系统提示词字符串
+            user_prompt: 用户提示词字符串
+            prompt: 单条用户提示词字符串
+            timeout: 超时时间(秒)
+            model_name: 模型名称(可选),支持 doubao/qwen/deepseek/gemini 等
+
+        Yields:
+            str: 生成的文本块
+
+        Raises:
+            ValueError: 参数组合错误
+        """
+        start_time = time.time()
+        current_timeout = timeout or self.default_timeout
+
+        try:
+            logger.info(f"[模型流式调用] 开始处理 trace_id: {trace_id}, 超时配置: {current_timeout}s")
+
+            # 构建消息列表
+            final_messages = self._build_messages(
+                messages=messages,
+                system_prompt=system_prompt,
+                user_prompt=user_prompt,
+                prompt=prompt,
+                task_prompt_info=task_prompt_info
+            )
+
+            response = llm_to_use.stream(final_messages)
+
+            chunk_count = 0
+            for chunk in response:
+                chunk_count += 1
+                if hasattr(chunk, 'content') and chunk.content:
+                    yield chunk.content
+                elif chunk:
+                    yield chunk
+
+            elapsed_time = time.time() - start_time
+            logger.info(f"[模型流式调用] 成功 trace_id: {trace_id}, 生成块数: {chunk_count}, 耗时: {elapsed_time:.2f}s")
+
+        except Exception as e:
+            elapsed_time = time.time() - start_time
+            logger.error(f"[模型流式调用] 异常 trace_id: {trace_id}, 耗时: {elapsed_time:.2f}s, 错误: {type(e).__name__}: {str(e)}")
+            raise
+
+generate_model_client = GenerateModelClient(default_timeout=15, max_retries=2, backoff_factor=0.5)

+ 0 - 35
gunicorn_config.py

@@ -1,35 +0,0 @@
-# !/usr/bin/python
-# -*- coding: utf-8 -*-
-'''
-@Project    : lq-agent-api
-@File       :gunicorn_config.py
-@IDE        :PyCharm
-@Author     :
-@Date       :2025/7/23 09:07
-'''
-
-
-import multiprocessing
-
-# 基础配置
-bind = "0.0.0.0:8001"
-workers = multiprocessing.cpu_count() + 1  # 推荐公式
-worker_class = "uvicorn.workers.UvicornWorker"
-timeout = 120
-keepalive = 5
-
-# 日志配置
-accesslog = "./gunicorn_log/access_log.log"  # 输出到 stdout
-errorlog = "./gunicorn_log/error_log.log"   # 错误日志到 stderr
-loglevel = "info"
-
-# 性能优化
-max_requests = 1000     # 防止内存泄漏
-max_requests_jitter = 50
-graceful_timeout = 30   # 优雅停机时间
-
-# MCP 特定优化
-preload_app = True  # 减少内存占用,加速启动
-
-# 安全增强
-limit_request_line = 4094  # 防止过大请求头

+ 9 - 0
utils_test/Model_Test/test_rerank_request.json

@@ -0,0 +1,9 @@
+{
+  "model": "bge-reranker-v2-m3",
+  "query": "乔布斯是谁?",
+  "candidates": [
+    "大模型是一类具有大量参数的人工智能模型。",
+    "苹果是一家科技公司",
+    "大模型用于深度学习任务"
+  ]
+}