Quellcode durchsuchen

dev:优化目录分类的提示词构建逻辑;

ChenJiSheng vor 2 Monaten
Ursprung
Commit
9e613afa65

+ 2 - 0
core/construction_review/component/doc_worker/__init__.py

@@ -42,3 +42,5 @@ __all__ = [
 
 
 
+
+

+ 39 - 13
core/construction_review/component/doc_worker/classification/hierarchy_classifier.py

@@ -28,6 +28,9 @@ class HierarchyClassifier(IHierarchyClassifier):
         # 初始化LLM客户端和提示词加载器
         self.llm_client = LLMClient(config_provider=self._cfg)
         self.prompt_loader = PromptLoader()
+        
+        # 获取标准类别列表(从CSV动态加载)
+        self.standard_categories = self.prompt_loader.get_standard_categories()
 
     def classify(
         self, toc_items: List[Dict[str, Any]], target_level: int = 1
@@ -135,23 +138,46 @@ class HierarchyClassifier(IHierarchyClassifier):
             
             # 解析LLM返回结果
             if llm_result and isinstance(llm_result, dict):
-                category_cn = llm_result.get("category_cn", "非规范项")
-                category_code = llm_result.get("category_code", "non_standard")
+                category_cn = llm_result.get("category_cn", "")
+                category_code = llm_result.get("category_code", "")
                 confidence = llm_result.get("confidence", 0.0)
                 
-                # 验证类别是否在映射表中,如果不在则使用兜底类别"非规范项"
-                if category_cn not in self.category_mapping:
-                    print(f"  警告: LLM返回的类别 '{category_cn}' 不在标准类别中,使用兜底类别'非规范项'")
-                    category_cn = "非规范项"
-                    category_code = "non_standard"
+                # 强制移除"非规范项",必须从标准类别中选择
+                # 注意:"其他资料"是标准类别之一,不应该被移除
+                if category_cn in ["非规范项", "非规范", "其他项"] or category_code == "non_standard":
+                    category_cn = ""
+                    category_code = ""
+                
+                # 验证类别是否在标准类别列表中
+                if not category_cn or category_cn not in self.standard_categories:
+                    # 如果不在标准类别中,强制使用标准类别"其他资料"作为兜底
+                    if self.standard_categories:
+                        if category_cn:
+                            print(f"  警告: LLM返回的类别 '{category_cn}' 不在标准类别中,强制使用标准类别'其他资料'")
+                        else:
+                            print(f"  警告: LLM返回的类别为空或无效,强制使用标准类别'其他资料'")
+                        category_cn = "其他资料"
+                        category_code = self.category_mapping.get("其他资料", "other")
+                    else:
+                        # 如果标准类别列表为空,使用第一个映射的类别
+                        if self.category_mapping:
+                            category_cn = list(self.category_mapping.keys())[0]
+                            category_code = list(self.category_mapping.values())[0]
+                            print(f"  警告: 标准类别列表为空,使用第一个标准类别 '{category_cn}'")
+                        else:
+                            category_cn = "其他资料"
+                            category_code = "other"
+                            print(f"  警告: 无法确定标准类别,使用'其他资料'")
                 
-                # 确保category_code与mapping一致
-                category_code = self.category_mapping.get(category_cn, "non_standard")
+                # 确保category_code与mapping一致,且category_cn在标准类别中
+                if category_cn not in self.standard_categories:
+                    category_cn = "其他资料"
+                category_code = self.category_mapping.get(category_cn, category_code)
             else:
-                # LLM调用失败,使用兜底类别"非规范项"
-                print(f"  警告: 一级目录 '{level1_item['title']}' 的LLM分类失败,使用兜底类别'非规范项'")
-                category_cn = "非规范项"
-                category_code = "non_standard"
+                # LLM调用失败,使用标准类别"其他资料"作为兜底
+                print(f"  警告: 一级目录 '{level1_item['title']}' 的LLM分类失败,使用标准类别'其他资料'")
+                category_cn = "其他资料"
+                category_code = self.category_mapping.get("其他资料", "other")
                 confidence = 0.0
             
             classified_items.append(

+ 50 - 0
core/construction_review/component/doc_worker/config/Construction_Plan_Content_Specification.csv

@@ -0,0 +1,50 @@
+一级目录	二级目录	三级内容
+编制依据	法律法规	法律法规包括国家、工程所在地省级政府发布的法律法规、规章制度等;
+编制依据	标准规范	标准规范包括行业标准、技术规程等;
+编制依据	文件制度	文件制度包括四川路桥、路桥集团、桥梁公司、建设单位下发的文件制度和管理程序文件等;
+编制依据	编制原则	编制原则应认真贯彻执行国家方针、政策、标准和设计文件,严格执行基本建设程序,实现工程项目的全部功能;
+编制依据	编制范围	编制范围应填写完整,涵盖本方案包含的所有工程,部分工程可简要说明采取的施工工艺。
+工程概况	设计概况	设计概况包含工程简介、主要技术标准两个方面。
+工程概况	工程地质与水文气象	工程地质与水文气象主要包括与该工程有关的水文状况、气候条件等。
+工程概况	周边环境	周边环境主要包括与该工程有关的主要建(构)筑物、山体、边坡、河谷、深基坑、道路、高压电、地下管线的位置关系、结构尺寸等情况
+工程概况	施工平面及立面布置	施工平面及立面布置包括本项目拌和站、钢筋加工场、材料(临时)堆码区域的位置和与该工程的距离,施工作业平台(场站)的尺寸、地面形式以及施工便道的长度、宽度、路面形式、最小弯曲半径,临时用水的来源、管线布置、距离,变压器、配电箱的位置、大小,线路走向,敷设方式等。
+工程概况	施工要求和技术保证条件	施工要求和技术保证条件包含工期目标、质量目标、安全目标、环境目标。工期目标包括本项目的总体工期和本工程的工期,仅需说明起止时间和持续时间。质量目标、安全目标和环境目标应根据施工合同和业主要求填写。
+工程概况	风险辨识与分级	风险辨识与分级包含在施工过程中所有的危险源,并按照法律法规的要求对其进行分级,并说明其应对措施。
+工程概况	参建各方责任主体单位	参建各方责任主体单位主要描述该项目的建设单位、设计单位、监理单位、施工单位、监控单位、专业分包单位的名称。
+施工计划	施工进度计划	施工进度计划包括主要工序作业时间分析、关键工程(工序)节点安排、施工进度计划横道图等。
+施工计划	施工材料计划	施工材料计划包含方案实施过程中需要使用的所有施工措施材料,明确材料名称、规格、数量、重量、来源。
+施工计划	施工设备计划	施工设备计划包含方案实施过程中需要使用的主要机械设备,应明确设备名称、规格、数量、来 源。
+施工计划	劳动力计划	劳动力计划包含各阶段(周、旬、月或季度)不同工种的作业人员投入情况。
+施工计划	安全生产费用使用计划	安全生产费用使用计划包含实施本方案拟投入的安全费用类别、费用名称、单 项投入金额和安全生产费用总额。
+施工工艺技术	主要施工方法概述	主要施工方法概述应简要说明采取的主要施工工艺和施工方法,以及模板等重 要材料的配置数量。
+施工工艺技术	技术参数	技术参数包含主要使用材料的类型、规格,以及主要设备的名称、型号、出厂 时间、性能参数、自重等。
+施工工艺技术	工艺流程	施工准备包含测量放样、临时用水、临时用电、场地、人员、设备、安全防护 措施和人员上下通道等内容。
+施工工艺技术	施工准备	工艺流程包含整个方案的主要施工工序,按照施工的先后顺序
+施工工艺技术	施工方法及操作要求	施工方法及操作要求根据工艺流程中主要的施工工序依次进行描述其操作方法, 并说明施工要点,常见问题及预防、处理措施。
+施工工艺技术	检查要求	检查要求包含所用的材料,构配件进场质量检查、抽查,以及施工过程中各道 工序检查内容及标准。
+安全保证措施	安全保证体系	
+安全保证措施	组织保证措施	组织保证措施包含安全管理组织机构、人员安全职责。
+安全保证措施	技术保证措施	技术保证措施应按总体安全措施,主要工序的安全保证措施进行梳理和说明
+安全保证措施	监测监控措施	监测监控措施包括监测组织机构、监测范围、监测项目、监测点的设置、监测 仪器设备、监测方法、监测频率、预警值及控制值、信息反馈等内容。
+安全保证措施	应急处置措施	应急处置措施包含应急处置程序、应急处置措施、应急物资及设备保障、交通 疏导与医疗救援、后期处置等六个方面。
+质量保证措施	质量保证体系	
+质量保证措施	质量目标	
+质量保证措施	工程创优规划	工程创优规划包含制定工程创优总体计划,做好技术准备工作,加强过程控制,重视细部处理,创建精品工程,推广应用新技术,申报资料、工程资料
+的收集与整理等内容
+质量保证措施	质量控制程序与具体措施	质量控制程序与具体措施包含原材料、实体工程质量检查验收程序和要求,主 要工序的质量通病、预防措施,以及季节性(冬期、高温、雨期)施工的质量保证 措施。
+环境保证措施	环境保证体系	
+环境保证措施	环境保护组织机构	环境保护组织机构包含管理人员姓名、职务、职责。
+环境保证措施	环境保护及文明施工措施	环境保护及文明施工措施包含办公、生活区环境卫生保证措施,施工区域水土 保持保证措施、噪声污染防治措施、水污染防治措施、大气污染防治措施。
+施工管理及作业人员配备与分工	施工管理人员	施工管理人员以表格的形式说明管理人员名单及岗位职责
+施工管理及作业人员配备与分工	专职安全生产管理人员	
+施工管理及作业人员配备与分工	特种作业人员	
+施工管理及作业人员配备与分工	其他作业人员	其他作业人员包含专业分包单位(协作队伍)管理人员数量,不同工种(班组、 区域)的作业人员数量等。
+验收要求	验收标准	验收标准包含国家和行业的标准、规范、操作规程、四川路桥、路桥集团和桥 梁公司的管理办法等。
+验收要求	验收程序	验收程序包括进场验收、过程验收、阶段验收、完工验收等时间节点的具体验 收程序。
+验收要求	验收内容	
+验收要求	验收时间	
+验收要求	验收人员	验收人员应包括建设、设计、施工、 监理、监测等单位相关人员,并明确验收人员姓名。
+其他资料	计算书	
+其他资料	相关施工图纸	
+其他资料	附图附表	
+其他资料	编制及审核人员情况	

+ 0 - 220
core/construction_review/component/doc_worker/config/config.yaml

@@ -32,226 +32,6 @@ categories:
     施工管理及作业人员配备与分工: management
     验收要求: acceptance
     其他资料: other
-    非规范项: non_standard
-  
-  
-  # 基于二级目录关键词的分类依据(来自分类要求标准.csv)
-  # 通过匹配一级目录下的二级目录关键词来判断一级目录的分类
-  keywords:
-    编制依据:
-      # 本章包含法律法规、标准规范、文件制度、编制原则、编制范围等五个方面
-      patterns:
-        - '法律.*法规'
-        - '标准.*规范'
-        - '规范.*标准'
-        - '文件.*制度'
-        - '编制.*原则'
-        - '编制.*范围'
-      keywords:
-        - '法律法规'
-        - '标准规范'
-        - '文件制度'
-        - '编制原则'
-        - '编制范围'
-        - '编制依据'
-        - '编制说明'
-        - '设计文件'
-        - '相关法律'
-        - '规范标准'
-    
-    工程概况:
-      # 本章包含设计概况、工程地质与水文气象、周边环境、施工平面及立面布置、施工要求和技术保证条件、风险辨识与分级、参建各方责任主体单位等七个方面
-      patterns:
-        - '设计.*概况'
-        - '工程.*地质'
-        - '水文.*气象'
-        - '周边.*环境'
-        - '施工.*平面'
-        - '立面.*布置'
-        - '技术.*保证.*条件'
-        - '风险.*辨识'
-        - '风险.*分级'
-        - '责任.*主体'
-      keywords:
-        - '设计概况'
-        - '工程地质'
-        - '水文气象'
-        - '周边环境'
-        - '施工平面'
-        - '立面布置'
-        - '施工要求'
-        - '技术保证条件'
-        - '风险辨识'
-        - '风险分级'
-        - '参建各方'
-        - '责任主体'
-        - '项目概况'
-        - '工程概况'
-        - '项目背景'
-        - '建设概况'
-        - '工程特点'
-    
-    施工计划:
-      # 本章包含施工进度计划、施工材料计划、施工设备计划、劳动力计划、安全生产费用使用计划等五个方面
-      patterns:
-        - '进度.*计划'
-        - '材料.*计划'
-        - '设备.*计划'
-        - '劳动力.*计划'
-        - '费用.*计划'
-        - '安全.*生产.*费用'
-      keywords:
-        - '施工进度计划'
-        - '施工材料计划'
-        - '施工设备计划'
-        - '劳动力计划'
-        - '安全生产费用'
-        - '施工计划'
-        - '施工部署'
-        - '施工准备'
-        - '总体安排'
-        - '进度安排'
-    
-    施工工艺技术:
-      # 本章包含主要施工方法概述、技术参数、工艺流程、施工准备、施工方法及操作要求、检查要求等六个方面
-      patterns:
-        - '施工.*方法'
-        - '技术.*参数'
-        - '工艺.*流程'
-        - '施工.*准备'
-        - '操作.*要求'
-        - '检查.*要求'
-      keywords:
-        - '施工方法'
-        - '技术参数'
-        - '工艺流程'
-        - '施工准备'
-        - '操作要求'
-        - '检查要求'
-        - '施工工艺'
-        - '技术方案'
-        - '施工计算'
-        - '工艺技术'
-    
-    安全保证措施:
-      # 本章包含安全保证体系、组织保证措施、技术保证措施、监测监控措施、应急处置措施等五个方面
-      patterns:
-        - '安全.*保证.*体系'
-        - '组织.*保证'
-        - '技术.*保证'
-        - '监测.*监控'
-        - '应急.*处置'
-      keywords:
-        - '安全保证体系'
-        - '组织保证措施'
-        - '技术保证措施'
-        - '监测监控措施'
-        - '应急处置措施'
-        - '安全保证'
-        - '安全管理'
-        - '安全施工'
-        - '安全防护'
-        - '安全生产'
-    
-    质量保证措施:
-      # 本章包含质量保证体系、质量目标、工程创优规划、质量控制程序与具体措施等四个方面
-      patterns:
-        - '质量.*保证.*体系'
-        - '质量.*目标'
-        - '工程.*创优'
-        - '质量.*控制'
-        - '质量.*措施'
-      keywords:
-        - '质量保证体系'
-        - '质量目标'
-        - '工程创优规划'
-        - '质量控制程序'
-        - '质量保证'
-        - '质量管理'
-        - '质量控制'
-        - '质量检验'
-        - '质量标准'
-    
-    环境保证措施:
-      # 本章包含环境保证体系、环境保护组织机构、环境保护及文明施工措施等三个方面
-      patterns:
-        - '环境.*保证.*体系'
-        - '环境.*保护.*组织'
-        - '环境.*保护.*措施'
-        - '文明.*施工'
-      keywords:
-        - '环境保证体系'
-        - '环境保护组织机构'
-        - '环境保护措施'
-        - '文明施工措施'
-        - '环境保护'
-        - '环保施工'
-        - '水土保持'
-        - '文明施工'
-        - '环境管理'
-    
-    施工管理及作业人员配备与分工:
-      # 本章包含施工管理人员、专职安全生产管理人员、特种作业人员、其他作业人员等四个方面
-      patterns:
-        - '施工.*管理.*人员'
-        - '安全.*生产.*管理.*人员'
-        - '特种.*作业.*人员'
-        - '作业.*人员'
-        - '人员.*配备'
-        - '人员.*分工'
-      keywords:
-        - '施工管理人员'
-        - '专职安全生产管理人员'
-        - '特种作业人员'
-        - '其他作业人员'
-        - '人员配备'
-        - '人员分工'
-        - '人员配置'
-        - '组织机构'
-        - '劳动力安排'
-        - '管理体系'
-    
-    验收要求:
-      # 本章包含验收标准、验收程序、验收内容、验收时间、验收人员等五个方面
-      patterns:
-        - '验收.*标准'
-        - '验收.*程序'
-        - '验收.*内容'
-        - '验收.*时间'
-        - '验收.*人员'
-      keywords:
-        - '验收标准'
-        - '验收程序'
-        - '验收内容'
-        - '验收时间'
-        - '验收人员'
-        - '验收要求'
-        - '交工验收'
-        - '竣工验收'
-    
-    其他资料:
-      # 本章包含计算书、相关施工图纸、附图附表、编制及审核人员情况等四个方面
-      patterns:
-        - '计算.*书'
-        - '施工.*图纸'
-        - '附图.*附表'
-        - '编制.*审核.*人员'
-      keywords:
-        - '计算书'
-        - '施工图纸'
-        - '附图附表'
-        - '编制人员'
-        - '审核人员'
-        - '其他说明'
-        - '附录'
-        - '附件'
-    
-    非规范项:
-      # 本类别用于收集所有不符合上述10个标准类别的目录项
-      # 这是一个兜底类别,不需要配置具体的patterns和keywords
-      # 分类逻辑会自动将未匹配到其他类别的目录项归入此类
-      patterns: []
-      keywords: []
 
 # 输出配置
 output:

+ 2 - 2
core/construction_review/component/doc_worker/config/llm_api.yaml

@@ -16,8 +16,8 @@ doubao:
   DOUBAO_API_KEY: YOUR_DOUBAO_API_KEY_FOR_RAG_EVAL
 
 qwen:
-  QWEN_SERVER_URL: http://192.168.91.253:9002/v1/
-  QWEN_MODEL_ID: Qwen3-8B
+  QWEN_SERVER_URL: https://aqai.shudaodsj.com:22000/v1/
+  QWEN_MODEL_ID: Qwen/Qwen3-30B-A3B-Instruct-2507
   QWEN_API_KEY: ms-9ad4a379-d592-4acd-b92c-8bac08a4a045
 
 keywords:

+ 11 - 16
core/construction_review/component/doc_worker/config/prompt.yaml

@@ -1,29 +1,24 @@
 toc_classification:
   system: |
     你是一名工程与施工领域的专业文档分类专家,负责对施工方案文档的目录进行分类识别。
-    - 根据一级目录标题及其下属二级目录的内容,准确判断该一级目录应属于哪个标准类别;
-    - 严格依据提供的分类标准进行分类,不能随意创建新类别;
-    - 如果目录项明显不属于任何标准类别,应分类为"其他资料"。
+    - 根据一级目录标题名称本身及其下属二级目录的内容,准确判断该一级目录应属于哪个标准类别;
+    - 一级目录标题可能包含编号前缀,需要忽略这些前缀,提取核心标题内容进行匹配;
+    - 一级目录名称本身是重要的分类依据,即使没有二级目录,也要根据一级目录名称进行分类;
+    - 必须从提供的标准类别中选择一个,所有标准类别都是平等的,没有偏好,不能创建新类别;
+    - 如果待分类的目录与多个标准类别都相关,选择最匹配的一个;
+
     - /no_think
   user_template: |
     任务:对施工方案文档的目录项进行分类识别。
 
-    一级目录标题:{{ level1_title }}
+    待分类的一级目录标题:{{ level1_title }}
 
-    二级目录列表:
+    该一级目录下的二级目录列表:
     {{ level2_titles }}
 
-    分类标准(一级标题及对应说明):
-    - 一、编制依据:本章包含法律法规、标准规范、文件制度、编制原则、编制范围等五个方面。
-    - 二、工程概况:本章包含设计概况、工程地质与水文气象、周边环境、施工平面及立面布置、施工要求和技术保证条件、风险辨识与分级、参建各方责任主体单位等七个方面。
-    - 三、施工计划:本章包含施工进度计划、施工材料计划、施工设备计划、劳动力计划、安全生产费用使用计划等五个方面。
-    - 四、施工工艺技术:本章包含主要施工方法概述、技术参数、工艺流程、施工准备、施工方法及操作要求、检查要求等六个方面。
-    - 五、安全保证措施:本章包含安全保证体系、组织保证措施、技术保证措施、监测监控措施、应急处置措施等五个方面。
-    - 六、质量保证措施:本章包含质量保证体系、质量目标、工程创优规划、质量控制程序与具体措施等四个方面。
-    - 七、环境保证措施:本章包含环境保证体系、环境保护组织机构、环境保护及文明施工措施等三个方面。
-    - 八、施工管理及作业人员配备与分工:本章包含施工管理人员、专职安全生产管理人员、特种作业人员、其他作业人员等四个方面。
-    - 九、验收要求:本章包含验收标准、验收程序、验收内容、验收时间、验收人员等五个方面。
-    - 十、其他资料:本章包含计算书、相关施工图纸、附图附表、编制及审核人员情况等四个方面。
+    分类标准(一级目录名称及其包含的二级目录集合):
+    {{ classification_standards }}
+    
 
     输出要求(只输出 JSON):
     {

+ 2 - 0
core/construction_review/component/doc_worker/config/provider.py

@@ -54,3 +54,5 @@ default_config_provider = YamlConfigProvider()
 
 
 
+
+

+ 2 - 0
core/construction_review/component/doc_worker/interfaces.py

@@ -229,3 +229,5 @@ class FileParseFacade(ABC):
 
 
 
+
+

+ 2 - 2
core/construction_review/component/doc_worker/pdf_worker/adapter.py

@@ -13,7 +13,7 @@ from typing import List, Optional
 
 from ..config.provider import default_config_provider
 from ..interfaces import DocumentPipeline, FileParseFacade, ResultWriter
-from .classifier import PdfHierarchyClassifier
+from ..classification.hierarchy_classifier import HierarchyClassifier
 from .fulltext_extractor import PdfFullTextExtractor
 from .json_writer import PdfJsonResultWriter
 from .text_splitter import PdfTextSplitter
@@ -47,7 +47,7 @@ def build_pdf_facade(config: Optional[PdfWorkerConfig] = None) -> FileParseFacad
     components = PipelineComponents(
         config=default_config_provider,
         toc_extractor=PdfTOCExtractor(),
-        classifier=PdfHierarchyClassifier(),
+        classifier=HierarchyClassifier(),
         fulltext_extractor=PdfFullTextExtractor(),
         splitter=PdfTextSplitter(),
         writers=writers,

+ 33 - 100
core/construction_review/component/doc_worker/pdf_worker/classifier.py

@@ -1,121 +1,54 @@
 """
-PDF 目录分类实现(基于二级目录+一级目录关键词)
+PDF 目录分类实现(已废弃,使用基于LLM的分类器)
+
+注意:此文件已废弃,不再使用基于关键词和正则的分类逻辑。
+现在统一使用 file_parse/classification/hierarchy_classifier.py 中的基于LLM的分类器。
 """
 
+# 此文件已废弃,不再使用
+# 现在统一使用 file_parse/classification/hierarchy_classifier.py 中的 HierarchyClassifier
+
 from __future__ import annotations
 
-from collections import Counter
 from typing import Any, Dict, List
 
 from ..config.provider import default_config_provider
 from ..interfaces import HierarchyClassifier
+from ..classification.hierarchy_classifier import HierarchyClassifier as LLMHierarchyClassifier
 
 
 class PdfHierarchyClassifier(HierarchyClassifier):
-    """基于层级结构和关键词的目录分类器。"""
+    """
+    基于层级结构和关键词的目录分类器(已废弃)。
+    
+    注意:此类已废弃,请使用 file_parse/classification/hierarchy_classifier.py 
+    中的 HierarchyClassifier(基于LLM的分类器)。
+    """
 
     def __init__(self) -> None:
+        # 已废弃:不再使用基于关键词的分类
+        # 现在直接使用基于LLM的分类器
+        import warnings
+        warnings.warn(
+            "PdfHierarchyClassifier 已废弃,请使用 HierarchyClassifier(基于LLM)",
+            DeprecationWarning,
+            stacklevel=2
+        )
+        
+        # 为了向后兼容,内部使用LLM分类器
+        self._llm_classifier = LLMHierarchyClassifier()
+        
         self._cfg = default_config_provider
         self._category_mapping: Dict[str, str] = self._cfg.get("categories.mapping", {})
-        self._category_keywords: Dict[str, Dict[str, Any]] = self._cfg.get("categories.keywords", {})
 
     def classify(self, toc_items: List[Dict[str, Any]], target_level: int) -> Dict[str, Any]:
-        # 只处理指定层级(通常为 1 级目录)
-        level_items = [it for it in toc_items if int(it.get("level", 1)) == target_level]
-        if not level_items:
-            return {"items": [], "total_count": 0, "target_level": target_level}
-
-        # 构建一级目录及其二级子目录列表
-        level_with_children: List[Dict[str, Any]] = []
-        for i, level_item in enumerate(level_items):
-            idx = toc_items.index(level_item)
-            if i < len(level_items) - 1:
-                next_idx = toc_items.index(level_items[i + 1])
-            else:
-                next_idx = len(toc_items)
-            children = [
-                x
-                for x in toc_items[idx + 1 : next_idx]
-                if int(x.get("level", 1)) == target_level + 1
-            ]
-            level_with_children.append({"parent": level_item, "children": children})
-
-        classified: List[Dict[str, Any]] = []
-        for group in level_with_children:
-            level_item = group["parent"]
-            children = group["children"]
-            category_cn = self._classify_by_titles(level_item["title"], [c["title"] for c in children])
-            category_en = self._category_mapping.get(category_cn, "other")
-            classified.append(
-                {
-                    "title": level_item["title"],
-                    "page": level_item.get("page", ""),
-                    "level": level_item.get("level", target_level),
-                    "category": category_cn,
-                    "category_code": category_en,
-                    "original": level_item.get("original", ""),
-                    "level2_count": len(children),
-                    "level2_titles": [c["title"] for c in children],
-                }
-            )
-
-        return {
-            "items": classified,
-            "total_count": len(classified),
-            "target_level": target_level,
-        }
-
-    # -------- 内部方法 --------
-
-    def _classify_by_titles(self, level1_title: str, level2_titles: List[str]) -> str:
-        """综合一级标题和其子标题进行投票分类。"""
-        votes: Counter[str] = Counter()
-
-        # 一级标题先投一票(避免没有二级时无法分类)
-        cat1 = self._match_category(level1_title)
-        if cat1 != "非规范项":
-            votes[cat1] += 1
-
-        # 二级标题参与投票
-        for t in level2_titles:
-            c = self._match_category(t)
-            if c != "非规范项":
-                votes[c] += 1
-
-        if votes:
-            return votes.most_common(1)[0][0]
-        return "非规范项"
-
-    def _match_category(self, title: str) -> str:
-        title_clean = self._remove_number_prefix(title)
-
-        # patterns 优先
-        for category, rules in self._category_keywords.items():
-            patterns = rules.get("patterns", [])
-            for pat in patterns:
-                import re
-
-                if re.search(pat, title) or re.search(pat, title_clean):
-                    return category
-
-        # keywords 次之
-        for category, rules in self._category_keywords.items():
-            keywords = rules.get("keywords", [])
-            for kw in keywords:
-                if kw in title or kw in title_clean:
-                    return category
-
-        return "非规范项"
-
-    def _remove_number_prefix(self, title: str) -> str:
-        """去除常见编号前缀。"""
-        import re
-
-        t = re.sub(r"^[\d一二三四五六七八九十]+[、\.\s]+", "", title)
-        t = re.sub(r"^第[一二三四五六七八九十\d]+[章节条款]\s*", "", t)
-        t = re.sub(r"^【\d+】\s*", "", t)
-        t = re.sub(r"^〖\d+(?:\.\d+)*〗\s*", "", t)
-        return t
+        """
+        分类方法(已废弃,内部委托给LLM分类器)。
+        
+        注意:此方法已废弃,现在直接使用基于LLM的分类器。
+        """
+        # 委托给LLM分类器
+        return self._llm_classifier.classify(toc_items, target_level)
 
 
 

+ 102 - 2
core/construction_review/component/doc_worker/utils/prompt_loader.py

@@ -5,27 +5,38 @@
 
 from __future__ import annotations
 
+import csv
 import re
 from pathlib import Path
-from typing import Dict, Any
+from typing import Dict, Any, List
+from collections import OrderedDict
 import yaml
 
 
 class PromptLoader:
     """提示词模板加载器"""
 
-    def __init__(self, prompt_file: Path | None = None):
+    def __init__(self, prompt_file: Path | None = None, csv_file: Path | None = None):
         """
         初始化提示词加载器
         
         参数:
             prompt_file: 提示词文件路径,如果为None则使用默认路径
+            csv_file: CSV分类标准文件路径,如果为None则使用默认路径
         """
         if prompt_file is None:
             prompt_file = Path(__file__).parent.parent / "config" / "prompt.yaml"
         self._prompt_file = Path(prompt_file)
+        
+        if csv_file is None:
+            csv_file = Path(__file__).parent.parent / "config" / "Construction_Plan_Content_Specification.csv"
+        self._csv_file = Path(csv_file)
+        
         self._prompts: Dict[str, Any] = {}
+        self._classification_standards: str = ""
+        self._standard_categories: List[str] = []  # 标准类别列表
         self._load()
+        self._load_classification_standards()
 
     def _load(self):
         """加载提示词文件"""
@@ -34,6 +45,89 @@ class PromptLoader:
         with self._prompt_file.open("r", encoding="utf-8") as f:
             self._prompts = yaml.safe_load(f) or {}
 
+    def _load_classification_standards(self):
+        """从CSV文件加载分类标准"""
+        if not self._csv_file.exists():
+            raise FileNotFoundError(f"分类标准CSV文件不存在: {self._csv_file}")
+        
+        # 使用OrderedDict保持一级目录的顺序
+        level1_to_level2: Dict[str, List[str]] = OrderedDict()
+        
+        # 已知的标准一级目录列表(用于过滤无效数据)
+        valid_level1_keywords = [
+            "编制依据", "工程概况", "施工计划", "施工工艺技术", 
+            "安全保证措施", "质量保证措施", "环境保证措施",
+            "施工管理及作业人员配备与分工", "验收要求", "其他资料"
+        ]
+        
+        with self._csv_file.open("r", encoding="utf-8-sig") as f:  # 使用 utf-8-sig 自动处理 BOM
+            reader = csv.DictReader(f, delimiter="\t")
+            for row in reader:
+                # 处理可能的 BOM 问题,查找包含"一级目录"的键
+                level1_key = next((k for k in row.keys() if "一级目录" in k), "一级目录")
+                
+                level1 = (row.get(level1_key) or "").strip()
+                level2 = (row.get("二级目录") or "").strip()
+                
+                # 跳过空的一级目录
+                if not level1:
+                    continue
+                
+                # 跳过明显不是一级目录的行:
+                # 1. 一级目录名称不在已知标准列表中
+                # 2. 且没有二级目录
+                # 3. 或一级目录名称很短(可能是数据错误)
+                is_valid_level1 = any(keyword in level1 for keyword in valid_level1_keywords)
+                if not is_valid_level1 and (not level2 or len(level1) < 5):
+                    continue
+                
+                if level1 not in level1_to_level2:
+                    level1_to_level2[level1] = []
+                
+                # 只添加非空的二级目录
+                if level2:
+                    level1_to_level2[level1].append(level2)
+        
+        # 生成分类标准文本
+        # 中文数字映射
+        chinese_numbers = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"]
+        
+        standards_lines = []
+        for idx, (level1, level2_list) in enumerate(level1_to_level2.items(), start=0):
+            if idx < len(chinese_numbers):
+                number_prefix = chinese_numbers[idx]
+            else:
+                number_prefix = str(idx + 1)
+            
+            # 统计二级目录数量
+            level2_count = len(level2_list)
+            level2_text = "、".join(level2_list)
+            
+            # 将一级目录名称和二级目录集合都包含在分类标准中
+            # 强调:匹配时只看核心标题名称,忽略编号前缀
+            if level2_count > 0:
+                standards_lines.append(
+                    f"    - {number_prefix}、{level1}(核心标题名称:{level1};包含的二级目录:{level2_text}等{level2_count}个方面):匹配核心标题「{level1}」,包含{level2_text}等{level2_count}个方面。"
+                )
+            else:
+                standards_lines.append(
+                    f"    - {number_prefix}、{level1}(核心标题名称:{level1}):匹配核心标题「{level1}」。"
+                )
+        
+        self._classification_standards = "\n".join(standards_lines)
+        
+        # 保存标准类别列表(从CSV中提取的一级目录)
+        self._standard_categories = list(level1_to_level2.keys())
+
+    def get_standard_categories(self) -> List[str]:
+        """
+        获取标准类别列表
+        
+        返回:
+            标准类别名称列表
+        """
+        return self._standard_categories.copy()
+    
     def get_template(self, template_name: str) -> Dict[str, str]:
         """
         获取提示词模板
@@ -66,6 +160,10 @@ class PromptLoader:
         # 渲染user模板
         user_content = template["user_template"]
         
+        # 如果模板中包含 classification_standards 占位符,自动注入分类标准
+        if "{{ classification_standards }}" in user_content or "{{classification_standards}}" in user_content:
+            kwargs.setdefault("classification_standards", self._classification_standards)
+        
         # 替换模板变量 {{ variable }}
         def replace_var(match):
             var_name = match.group(1).strip()
@@ -78,3 +176,5 @@ class PromptLoader:
             "user": user_content
         }
 
+
+

+ 2 - 0
core/construction_review/component/doc_worker/命令

@@ -6,4 +6,6 @@ python -m file_parse.pdf_worker.cli ".\路桥\47_四川川交路桥有限责任
 python -m file_parse.pdf_worker.cli "Z:\施工方案及编制依据案例库(第一阶段)1205\施工方案文档列表\44_四川公路桥梁建设集团有限公司镇巴(川陕界)至广安高速公路通广段C合同段C4项目经理部.pdf" -l 1 --max-size 3000 --min-size 50 -o ./output
 
 
+    - 例如:"第七章 环境保证措施"的核心标题是"环境保证措施",应该匹配到"环境保证措施"类别;
+    - 如果目录项明显不属于任何标准类别,应分类为"其他资料"。