Selaa lähdekoodia

feat(catalog_reviewer): 目录审查结果添加 page 字段

- toc_detector.py: 在返回的 catalog 中添加 toc_page_range 字段
- catalog_reviewer.py: JSON示例添加page字段,review()接收toc_page_range参数
- ai_review_engine.py: 提取并传递 toc_page_range
WangXuMing 4 päivää sitten
vanhempi
sitoutus
fc7507323b

+ 6 - 3
core/construction_review/component/ai_review_engine.py

@@ -896,14 +896,16 @@ class AIReviewEngine(BaseReviewer):
         logger.info(f"[{name}] 开始LLM目录完整性检查")
 
         try:
-            # 获取 catalog 的标准格式文本
+            # 获取 catalog 的标准格式文本和目录页页码
             formatted_text = ""
+            toc_page_range = None
 
-            # 优先从 catalog.formatted_text 获取
+            # 优先从 catalog 获取
             if outline_data and isinstance(outline_data, dict):
                 catalog_raw = outline_data.get('catalog')
                 if catalog_raw and isinstance(catalog_raw, dict):
                     formatted_text = catalog_raw.get('formatted_text', '')
+                    toc_page_range = catalog_raw.get('toc_page_range')
 
             # 回退到从 state 获取
             if not formatted_text and state and isinstance(state, dict):
@@ -911,6 +913,7 @@ class AIReviewEngine(BaseReviewer):
                 catalog_raw = structured.get('catalog')
                 if catalog_raw and isinstance(catalog_raw, dict):
                     formatted_text = catalog_raw.get('formatted_text', '')
+                    toc_page_range = catalog_raw.get('toc_page_range')
 
             # 如果没有标准格式,从 chapters 构建
             if not formatted_text:
@@ -971,7 +974,7 @@ class AIReviewEngine(BaseReviewer):
 
             # 使用 CatalogReviewer 进行审查
             reviewer = CatalogReviewer()
-            result = await reviewer.review(formatted_text, trace_id_idx)
+            result = await reviewer.review(formatted_text, trace_id_idx, toc_page_range)
 
             logger.info(f"[DEBUG][{name}] 检查完成,返回结果")
             logger.info(f"[DEBUG][{name}] result type: {type(result)}")

+ 45 - 3
core/construction_review/component/minimal_pipeline/catalog_reviewer.py

@@ -32,6 +32,7 @@ class CatalogReviewer:
         "check_result": {
           "issue_point": "【一级缺失】第四章 施工工艺技术",
           "location": "目录页",
+          "page": 3,
           "suggestion": "建议补充'第四章 施工工艺技术'章节",
           "reason": "目录页缺少该章节",
           "risk_level": "高风险"
@@ -46,6 +47,7 @@ class CatalogReviewer:
         "check_result": {
           "issue_point": "【一级缺失】第十章 其他资料",
           "location": "目录页",
+          "page": 3,
           "suggestion": "建议补充'第十章 其他资料'章节",
           "reason": "目录页缺少该章节",
           "risk_level": "高风险"
@@ -60,6 +62,7 @@ class CatalogReviewer:
         "check_result": {
           "issue_point": "【二级缺失】第一章 编制依据 - 四、编制原则",
           "location": "第一章",
+          "page": 3,
           "suggestion": "建议补充'四、编制原则'",
           "reason": "第一章缺少该二级目录",
           "risk_level": "中风险"
@@ -157,13 +160,15 @@ class CatalogReviewer:
 三、附图附表
 四、编制及审核人员情况"""
 
-    async def review(self, actual_catalog_text: str, trace_id_idx: str = "") -> Dict[str, Any]:
+    async def review(self, actual_catalog_text: str, trace_id_idx: str = "",
+                      toc_page_range: Dict[str, int] = None) -> Dict[str, Any]:
         """
         审查目录完整性
 
         Args:
             actual_catalog_text: 实际目录文本(标准格式)
             trace_id_idx: 追踪ID索引
+            toc_page_range: 目录页页码范围,如 {"start": 3, "end": 4}
 
         Returns:
             对齐 completeness_check 格式的结果字典
@@ -174,7 +179,7 @@ class CatalogReviewer:
         try:
             from foundation.ai.agent.generate.model_generate import generate_model_client
 
-            prompt = self._build_prompt(actual_catalog_text)
+            prompt = self._build_prompt(actual_catalog_text, toc_page_range)
 
             # 重试机制:最多3次
             max_retries = 3
@@ -251,10 +256,21 @@ class CatalogReviewer:
                 "execution_time": execution_time
             }
 
-    def _build_prompt(self, actual_catalog_text: str) -> str:
+    def _build_prompt(self, actual_catalog_text: str,
+                       toc_page_range: Dict[str, int] = None) -> str:
         """构建审查Prompt"""
         json_example = self._JSON_EXAMPLE_TEMPLATE
 
+        # 构建页码信息说明
+        page_info = ""
+        if toc_page_range:
+            start_page = toc_page_range.get('start', 3)
+            end_page = toc_page_range.get('end', 3)
+            if start_page == end_page:
+                page_info = f"目录页位于第 {start_page} 页"
+            else:
+                page_info = f"目录页位于第 {start_page}-{end_page} 页"
+
         # 基础 JSON 模板(使用单引号字符串避免 f-string 转义问题)
         base_template = '''{
   "details": {
@@ -267,6 +283,7 @@ class CatalogReviewer:
         "check_result": {
           "issue_point": "【一级缺失】xxx",
           "location": "目录页",
+          "page": 3,
           "suggestion": "建议补充'xxx'章节",
           "reason": "简要说明",
           "risk_level": "高风险"
@@ -281,6 +298,29 @@ class CatalogReviewer:
   "success": true
 }'''
 
+        page_instruction = f"""
+## 页码信息
+{page_info if page_info else "目录页页码未知,统一使用 page=3"}
+
+## 输出格式要求
+check_result 中必须包含以下字段:
+- issue_point: 问题描述
+- location: 问题定位(一级缺失填"目录页",二级缺失填对应的一级章节名)
+- page: 页码数字({toc_page_range.get('start', 3) if toc_page_range else 3})
+- suggestion: 补充建议
+- reason: 原因说明
+- risk_level: 风险等级("高风险"或"中风险")
+""" if toc_page_range else """
+## 输出格式要求
+check_result 中必须包含以下字段:
+- issue_point: 问题描述
+- location: 问题定位(一级缺失填"目录页",二级缺失填对应的一级章节名)
+- page: 页码数字(统一使用 3)
+- suggestion: 补充建议
+- reason: 原因说明
+- risk_level: 风险等级("高风险"或"中风险")
+"""
+
         return f"""你是一位施工方案文档审查专家。请对比【实际目录】和【标准目录】,找出缺失项。
 
 ## 审查原则
@@ -329,6 +369,8 @@ class CatalogReviewer:
 - 一级缺失:risk_level 为 "高风险", risk_info.risk_level 为 "high"
 - 二级缺失:risk_level 为 "中风险", risk_info.risk_level 为 "medium"
 - 如无缺失,response 中放一条 "issue_point": "【目录完整】一二级目录结构完整", "exist_issue": false
+
+{page_instruction}
 """
 
     def _extract_json(self, content: str) -> Optional[Dict[str, Any]]:

+ 7 - 0
core/construction_review/component/minimal_pipeline/toc_detector.py

@@ -142,6 +142,13 @@ class TOCCatalogExtractor:
 
             catalog = self._parse_toc_text(toc_text)
 
+            # 添加目录页页码范围(1-based)
+            if toc_pages:
+                catalog["toc_page_range"] = {
+                    "start": toc_pages[0] + 1,  # 转换为1-based页码
+                    "end": toc_pages[-1] + 1
+                }
+
             if progress_callback:
                 progress_callback("目录识别", 100, f"目录提取完成,共{catalog['total_chapters']}章")