Ver código fonte

Merge branch 'dev_sgsc_wxm' of CRBC-MaaS-Platform-Project/LQAgentPlatform into dev

WangXuMing 3 semanas atrás
pai
commit
5ad1b3400f
27 arquivos alterados com 1130 adições e 275 exclusões
  1. 8 0
      core/construction_review/component/ai_review_engine.py
  2. 6 3
      core/construction_review/component/reviewers/prompt/basic_reviewers.yaml
  3. 46 73
      core/construction_review/component/reviewers/reference_basis_reviewer.py
  4. 2 30
      core/construction_review/component/reviewers/sensitive_words/色情词库.txt
  5. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/COVID-19词库.txt
  6. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/GFW补充词库.txt
  7. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/其他词库.txt
  8. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/反动词库.txt
  9. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/广告类型.txt
  10. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/政治类型.txt
  11. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/新思想启蒙.txt
  12. 24 0
      core/construction_review/component/reviewers/sensitive_words_old/施工方案绝对化用语.txt
  13. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/暴恐词库.txt
  14. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/民生词库.txt
  15. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/涉枪涉爆.txt
  16. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/色情类型.txt
  17. 896 0
      core/construction_review/component/reviewers/sensitive_words_old/色情词库.txt
  18. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/补充词库.txt
  19. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/贪腐词库.txt
  20. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/零时-Tencen.txt.bak
  21. 0 0
      core/construction_review/component/reviewers/sensitive_words_old/非法网址.txt
  22. 2 2
      core/construction_review/component/reviewers/utils/__init__.py
  23. 138 94
      core/construction_review/component/reviewers/utils/directory_extraction.py
  24. 5 70
      core/construction_review/component/reviewers/utils/punctuation_result_processor.py
  25. 1 1
      core/construction_review/workflows/ai_review_workflow.py
  26. 1 1
      core/construction_review/workflows/core_functions/ai_review_core_fun.py
  27. 1 1
      utils_test/Sensitive_Test/test_grammar_check_chain.py

+ 8 - 0
core/construction_review/component/ai_review_engine.py

@@ -1139,6 +1139,14 @@ class AIReviewEngine(BaseReviewer):
 
             # 根据章节代码决定提取方式
             if chapter_code == 'basis' and basis_items:
+                # 过滤法律法规(无标准编号,不做格式审查)
+                from core.construction_review.component.reviewers.utils.directory_extraction import is_law_item
+                before_count = len(basis_items.items)
+                basis_items.items = [it for it in basis_items.items if not is_law_item(it)]
+                law_count = before_count - len(basis_items.items)
+                if law_count:
+                    logger.info(f"basis章节过滤法律法规: {before_count} -> {len(basis_items.items)} (过滤 {law_count} 条)")
+
                 # basis章节:使用模型提取的BasisItems
                 basis_list = [item.raw for item in basis_items.items if getattr(item, "raw", None)]
                 logger.info(f"basis章节使用模型提取,条目数: {len(basis_list)}")

+ 6 - 3
core/construction_review/component/reviewers/prompt/basic_reviewers.yaml

@@ -373,23 +373,26 @@ sensitive_word_check:
     - **违法信息**:毒品制作、赌博平台、诈骗方法
     - **分裂言论**:危害国家统一、民族团结的言论
     - 示例:
-      - 原文中出现”打倒共产主义” → **必须报 issue**,这是政治敏感,不可豁免
+      - 原文中出现”打倒*” → **必须报 issue**,这是政治敏感,不可豁免
       - 原文中出现”出售雷管” → **必须报 issue**,这是危险品交易信息
-      - 原文中出现”习近平” → **必须报 issue**,领导人姓名不应出现在施工方案中
       - 原文中出现”硝铵炸药配方” → **必须报 issue**,这是危险品制作信息
 
     ### 第二类:上下文敏感词(需结合语境判断)
     以下类别敏感词需要根据上下文判断是否豁免:
-    - **工程绝对化用语**:”绝对不会出现事故”、”绝对不会有污染”、”百分百安全”等
+    - **工程绝对化用语**:”万无一失”、”绝对安全”、”百分百”等
     - **一般性违禁行为**:赌博、吸毒、酗酒等(当上下文是禁止/防范时放行)
 
     ### 豁免条件(仅适用于第二类上下文敏感词)
     仅当敏感词出现在以下语境中时才可放行:
     - 明确的安全规范/禁止条款(如”严禁赌博”、”禁止酗酒”)
     - 风险防范措施说明(如”制定应急预案防止XX”)
+    - **安全相关语境中的绝对化表述**:在安全管理、安全操作、安全防护等安全相关语境中,使用绝对化用语(如”万无一失””绝对安全””确保零事故”)属于安全工作的严谨要求,应予以放行。仅当绝对化表述出现在非安全语境中(如商业宣传、质量担保承诺等)才应报 issue。
     - 示例:
       - 原文”应禁止工人在宿舍中赌博” → 赌博出现在禁止语境中 → **无明显问题**
       - 原文”工人休息时可以打牌” → 初筛命中”赌博”近义词但上下文无禁止 → **应报 issue**
+      - 原文”经试吊并对存在的问题进行了处理,确认万无一失后才能正式起吊” → 安全操作语境 → **无明显问题**
+      - 原文”吊装作业必须确保绝对安全,严禁违章操作” → 安全防护语境 → **无明显问题**
+      - 原文”本工程采用的吊装方案万无一失,施工安全完全有保障” → 对外承诺性质 → **应报 issue**
 
     ## 风险等级分类
     - **高风险**: 政治敏感、暴力恐怖、色情淫秽、分裂言论 —— 必须删除或彻底改写

+ 46 - 73
core/construction_review/component/reviewers/reference_basis_reviewer.py

@@ -1,7 +1,6 @@
 from __future__ import annotations
 
 import asyncio
-import json
 import re
 import time
 import yaml
@@ -16,7 +15,6 @@ from core.construction_review.component.reviewers.utils.inter_tool import InterT
 from core.construction_review.component.reviewers.utils.prompt_loader import PromptLoader
 from core.construction_review.component.reviewers.utils.punctuation_checker import check_punctuation
 from core.construction_review.component.reviewers.utils.punctuation_result_processor import process_punctuation_results
-from core.construction_review.component.reviewers.utils.reference_matcher import match_reference_files
 from foundation.observability.logger.loggering import review_logger as logger
 from langchain_core.prompts import ChatPromptTemplate
 from foundation.ai.agent.generate.model_generate import generate_model_client
@@ -254,37 +252,52 @@ class BasisReviewService:
         """
         从正文内容中通过正则提取标准引用(用于非basis章节)
 
+        提取规则:
+        - 提取《名称》(编号)格式的引用
+        - 跳过"详见/见/参见/参照/参考"后紧跟的引用(这些是非标准规范的引用说明)
+
         Args:
             content: 正文内容文本
 
         Returns:
-            List[str]: 提取的标准引用列表(原始文本格式:《名称》(编号)
+            List[str]: 提取的标准引用列表(原文原样保留,不做格式修复
         """
         if not content or not content.strip():
             return []
 
+        # "详见/见/参见"等引导词,后跟的引用不提取
+        _SKIP_PATTERNS = re.compile(r'(?:详见|见|参见|参照|参考)\s*$')
+
         references = []
 
-        # 1. 提取完整格式:《名称》(编号)
-        full_matches = self.STANDARD_FULL_PATTERN.findall(content)
-        for name, number in full_matches:
+        # 1. 提取完整格式:《名称》(编号),保留原文
+        for m in self.STANDARD_FULL_PATTERN.finditer(content):
+            name, number = m.group(1), m.group(2)
             if self._is_valid_standard_number(number):
-                original = f"《{name}》({number})"
-                references.append(original)
+                # 检查前文是否有"详见/见/参见"等引导词
+                lookback_start = max(0, m.start() - 10)
+                lookback = content[lookback_start:m.start()]
+                if _SKIP_PATTERNS.search(lookback):
+                    continue
+                references.append(m.group(0))  # 原文原样保留
 
         # 2. 提取孤立的规范编号并尝试推断名称
         number_pattern = re.compile(
             '(' + '|'.join(self.STANDARD_NUMBER_PATTERNS) + ')',
             re.MULTILINE | re.IGNORECASE
         )
-        number_matches = number_pattern.findall(content)
-        for match in number_matches:
-            number = match if isinstance(match, str) else match[0]
+        for m in number_pattern.finditer(content):
+            number = m.group(0) if isinstance(m.group(0), str) else m.group(1)
             if not any(number in ref for ref in references):
-                # 尝试从上下文推断名称
-                name = self._infer_name_from_context(content, number)
-                if name:
-                    references.append(f"《{name}》({number})")
+                # 检查前文是否有"详见/见/参见"等引导词
+                lookback_start = max(0, m.start() - 10)
+                lookback = content[lookback_start:m.start()]
+                if _SKIP_PATTERNS.search(lookback):
+                    continue
+                # 从上下文取原始文本,不做格式修复
+                raw = self._get_raw_text(content, number)
+                if raw:
+                    references.append(raw)
 
         # 去重
         seen = set()
@@ -305,11 +318,19 @@ class BasisReviewService:
                 return True
         return False
 
-    def _infer_name_from_context(self, content: str, number: str) -> str:
-        pattern = re.compile(r'《([^《》]{3,50})》[^《》]{0,30}' + re.escape(number))
+    def _get_raw_text(self, content: str, number: str) -> str:
+        """从正文中找到规范编号所在的原文片段,原样返回,不做任何格式修复"""
+        # 尝试找《name》...number 的完整片段
+        pattern = re.compile(r'《([^《》]{1,60})》[^《》]{0,30}' + re.escape(number))
         match = pattern.search(content)
         if match:
-            return match.group(1)
+            return match.group(0)
+        # 找不到《》则取编号左右各取上下文
+        nmatch = re.search(re.escape(number), content)
+        if nmatch:
+            start = max(0, nmatch.start() - 50)
+            end = min(len(content), nmatch.end() + 10)
+            return content[start:end].strip()
         return ""
 
     async def review_batch(
@@ -351,59 +372,17 @@ class BasisReviewService:
 
         async with self._semaphore:
             try:
-                # 第一步:搜索编制依据并通过match_reference_files过滤
-                search_tasks = []
-                for basis in items_to_check:
-                    task = asyncio.create_task(
-                        self._async_search_basis(basis, collection_name, top_k_each)
-                    )
-                    search_tasks.append(task)
-
-                # 等待所有搜索完成
-                search_results = await asyncio.gather(*search_tasks, return_exceptions=True)
-
-                grouped_candidates = []
-                for i, result in enumerate(search_results):
-                    if isinstance(result, Exception):
-                        logger.error(f"搜索失败 '{items_to_check[i]}': {result}")
-                        grouped_candidates.append([])
-                    else:
-                        # result 是 List[dict],需要遍历
-                        texts = [item["text_content"] for item in result if "text_content" in item]
-                        grouped_candidates.append(texts)
-
-                # 获取match_reference_files的结果并过滤
-                match_result = await match_reference_files(reference_text=grouped_candidates, review_text=items_to_check)
-                # 解析JSON并过滤:same_name_current和exact_match_info都是""的项过滤掉
-                try:
-                    match_data = json.loads(match_result)
-                    # 提取items字段(match_reference_files返回{items: [...]}格式)
-                    items = match_data.get('items', match_data) if isinstance(match_data, dict) else match_data
-                    filtered_data = [item for item in items if not (item.get('same_name_current') == "" and item.get('exact_match_info') == "")]
-                    # 从过滤后的数据中提取review_item用于后续检查
-                    filtered_basis_items = [item.get('review_item') for item in filtered_data if item.get('review_item')]
-                    final_items_to_check = filtered_basis_items if filtered_basis_items else []
-                    logger.info(f"过滤后参与检查的标准: {len(final_items_to_check)}/{len(items_to_check)}")
-                except (json.JSONDecodeError, TypeError) as e:
-                    logger.warning(f"过滤match_reference_files结果时出错: {e}")
-                    # 如果解析失败,使用原始结果
-                    final_items_to_check = []
-
-                # 如果没有过滤出数据,直接返回空结果
-                if not final_items_to_check:
-                    logger.info(f"过滤后没有符合条件的标准,跳过后续检查")
-                    return []
-
-                # 第二步:调用标点符号检查器
-                checker_result = await check_punctuation(final_items_to_check)
+                # 格式审查:直接检查所有提取到的条目,不经过Milvus过滤
+                # 格式检查只依赖文本本身,不需要在标准库中查找
+                checker_result = await check_punctuation(items_to_check)
                 print(checker_result)
 
-                # 第三步:调用结果处理器,生成详细的问题分析报告
+                # 调用结果处理器,生成详细的问题分析报告
                 processor_result = await process_punctuation_results(checker_result)
-                print("\n【第二步】问题分析报告输出:")
+                print("\n【格式检查结果处理后】:")
                 print(processor_result)
 
-                # 第四步:转换为标准格式
+                # 转换为标准格式
                 standardized_result = self.response_processor.process_llm_response(
                     processor_result,
                     "reference_check",
@@ -413,7 +392,7 @@ class BasisReviewService:
 
                 # 统计问题数量
                 issue_count = sum(1 for item in standardized_result if item.get('exist_issue', False))
-                logger.info(f"规范性审查完成({chapter_code}):总计 {len(final_items_to_check)} 项,发现问题 {issue_count} 项")
+                logger.info(f"规范性审查完成({chapter_code}):总计 {len(items_to_check)} 项,发现问题 {issue_count} 项")
 
                 return standardized_result
 
@@ -427,12 +406,6 @@ class BasisReviewService:
                     "exist_issue": True,
                     "risk_info": {"risk_level": "high"}
                 }]
-                    "chapter_code": "basis",
-                    "check_item_code": "basis_reference_check",
-                    "check_result": {"error": str(e), "basis_items": basis_items},
-                    "exist_issue": True,
-                    "risk_info": {"risk_level": "high"}
-                }]
 
     async def _async_search_basis(
         self,

+ 2 - 30
core/construction_review/component/reviewers/sensitive_words/色情词库.txt

@@ -1,4 +1,3 @@
-爱女人
 色青
 爱液
 按摩棒
@@ -66,7 +65,6 @@
 荡妇
 荡女
 盗撮
-多人轮
 发浪
 放尿
 肥逼
@@ -79,7 +77,6 @@
 肛门
 龟头
 裹本
-国产av
 好嫩
 豪乳
 黑逼
@@ -104,7 +101,6 @@
 金鳞岂是池中物
 金麟岂是池中物
 精液
-就去日
 巨屌
 菊花洞
 菊门
@@ -209,7 +205,6 @@
 色欲
 色b
 少年阿宾
-少修正
 射爽
 射颜
 食精
@@ -229,7 +224,6 @@
 丝诱
 松岛枫
 酥痒
-汤加丽
 套弄
 体奸
 舔脚
@@ -323,7 +317,6 @@
 玉穴
 原味内衣
 援助交际
-张筱雨
 招鸡
 招妓
 中年美妇
@@ -332,28 +325,15 @@
 自慰
 作爱
 18禁
-99bb
-a4u
-a4y
-adult
-amateur
-anal
 a片
 fuck
 gay片
 g点
 g片
-hardcore
 h动画
 h动漫
-incest
-porn
-secom
-sexinsex
 sm女王
-xiao77
 xing伴侣
-tokyohot
 yin荡
 贱人
 装b
@@ -436,7 +416,7 @@ sb
 屁股
 下体
-a片
+a片sss
 内裤
 咪咪
 白嫩
@@ -544,11 +524,9 @@ sm
 淫兽学
 淫水
 淫穴
-morphine
 摇头丸
 迷药
 乖乖粉
-narcotic
 麻醉药
 精神药品
 爱女人
@@ -600,7 +578,6 @@ narcotic
 抽一插
 春药
 大波
-大力抽送
 大乳
 荡妇
 荡女
@@ -885,12 +862,7 @@ g片
 hardcore
 h动画
 h动漫
-incest
-porn
-secom
-sexinsex
+
 sm女王
-xiao77
 xing伴侣
-tokyohot
 yin荡

+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/COVID-19词库.txt → core/construction_review/component/reviewers/sensitive_words_old/COVID-19词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/GFW补充词库.txt → core/construction_review/component/reviewers/sensitive_words_old/GFW补充词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/其他词库.txt → core/construction_review/component/reviewers/sensitive_words_old/其他词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/反动词库.txt → core/construction_review/component/reviewers/sensitive_words_old/反动词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/广告类型.txt → core/construction_review/component/reviewers/sensitive_words_old/广告类型.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/政治类型.txt → core/construction_review/component/reviewers/sensitive_words_old/政治类型.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/新思想启蒙.txt → core/construction_review/component/reviewers/sensitive_words_old/新思想启蒙.txt


+ 24 - 0
core/construction_review/component/reviewers/sensitive_words_old/施工方案绝对化用语.txt

@@ -0,0 +1,24 @@
+绝对安全
+不可能发生
+绝不会
+绝对不会
+绝无风险
+完全消除隐患
+万无一失
+不会出现任何问题
+绝对可靠
+百分之百安全
+不存在安全隐患
+不可能发生事故
+确保零事故
+彻底杜绝事故发生
+绝对不会坍塌
+绝对不会失稳
+完全不受外界影响
+在任何情况下都安全
+无需任何防护措施
+无需额外监测
+不存在失败可能
+保证不发生安全事故
+绝对符合所有规范要求
+无需进行风险评估

+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/暴恐词库.txt → core/construction_review/component/reviewers/sensitive_words_old/暴恐词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/民生词库.txt → core/construction_review/component/reviewers/sensitive_words_old/民生词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/涉枪涉爆.txt → core/construction_review/component/reviewers/sensitive_words_old/涉枪涉爆.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/色情类型.txt → core/construction_review/component/reviewers/sensitive_words_old/色情类型.txt


+ 896 - 0
core/construction_review/component/reviewers/sensitive_words_old/色情词库.txt

@@ -0,0 +1,896 @@
+爱女人
+色青
+爱液
+按摩棒
+拔出来
+爆草
+包二奶
+暴干
+暴奸
+暴乳
+爆乳
+暴淫
+屄
+被插
+被操
+被干
+逼奸
+仓井空
+插暴
+操逼
+操黑
+操烂
+肏你
+肏死
+操死
+操我
+厕奴
+插比
+插b
+插逼
+插你
+插我
+插阴
+潮吹
+潮喷
+成人dv
+成人电影
+成人论坛
+成人小说
+成人电
+成人电影
+成人卡通
+成人聊
+成人片
+成人视
+成人图
+成人文
+成人小
+成人电影
+成人论坛
+成人色情
+成人网站
+成人文学
+成人小说
+艳情小说
+成人游戏
+吃精
+赤裸
+抽插
+扌由插
+抽一插
+春药
+大波
+大力抽送
+大乳
+荡妇
+荡女
+盗撮
+多人轮
+发浪
+放尿
+肥逼
+粉穴
+封面女郎
+风月大陆
+干死你
+干穴
+肛交
+肛门
+龟头
+裹本
+国产av
+好嫩
+豪乳
+黑逼
+后庭
+后穴
+虎骑
+花花公子
+换妻俱乐部
+黄片
+几吧
+鸡吧
+鸡巴
+鸡奸
+寂寞男
+寂寞女
+妓女
+激情
+集体淫
+奸情
+叫床
+脚交
+金鳞岂是池中物
+金麟岂是池中物
+精液
+就去日
+巨屌
+菊花洞
+菊门
+巨奶
+巨乳
+菊穴
+开苞
+口爆
+口活
+口射
+口淫
+裤袜
+狂操
+狂插
+浪逼
+浪妇
+浪叫
+浪女
+狼友
+聊性
+流淫
+铃木麻
+凌辱
+漏乳
+露b
+乱交
+乱伦
+轮暴
+轮操
+轮奸
+裸陪
+买春
+美逼
+美少妇
+美乳
+美腿
+美穴
+美幼
+秘唇
+迷奸
+密穴
+蜜穴
+蜜液
+摸奶
+摸胸
+母奸
+奈美
+奶子
+男奴
+内射
+嫩逼
+嫩女
+嫩穴
+捏弄
+女优
+炮友
+砲友
+喷精
+屁眼
+品香堂
+前凸后翘
+强jian
+强奸处女
+情趣用品
+情色
+拳交
+全裸
+群交
+惹火身材
+人妻
+人兽
+日逼
+日烂
+肉棒
+肉逼
+肉唇
+肉洞
+肉缝
+肉棍
+肉茎
+肉具
+揉乳
+肉穴
+肉欲
+乳爆
+乳房
+乳沟
+乳交
+乳头
+三级片
+骚逼
+骚比
+骚女
+骚水
+骚穴
+色逼
+色界
+色猫
+色盟
+色情网站
+色诱
+色欲
+色b
+少年阿宾
+少修正
+射爽
+射颜
+食精
+释欲
+兽奸
+兽交
+手淫
+兽欲
+熟妇
+熟母
+熟女
+爽片
+爽死我了
+双臀
+死逼
+丝袜
+丝诱
+松岛枫
+酥痒
+汤加丽
+套弄
+体奸
+舔脚
+舔阴
+调教
+偷欢
+偷拍
+脱内裤
+文做
+我就色
+舞女
+无修正
+吸精
+夏川纯
+相奸
+小逼
+校鸡
+小穴
+小xue
+写真
+性感妖娆
+性感诱惑
+性虎
+性饥渴
+性技巧
+性奴
+性虐
+性息
+性欲
+胸推
+穴口
+学生妹
+穴图
+亚情
+颜射
+阳具
+杨思敏
+要射了
+夜勤病栋
+一本道
+一夜欢
+一夜情
+一ye情
+阴部
+淫虫
+阴唇
+淫荡
+阴道
+淫电影
+阴阜
+淫妇
+淫河
+阴核
+阴户
+淫贱
+淫叫
+淫教师
+阴茎
+阴精
+淫浪
+淫媚
+淫糜
+淫魔
+淫母
+淫女
+淫虐
+淫妻
+淫情
+淫色
+淫声浪语
+淫兽学园
+淫书
+淫术炼金士
+淫水
+淫娃
+淫威
+淫亵
+淫样
+淫液
+淫照
+阴b
+幼交
+幼男
+幼女
+欲火
+欲女
+玉女心经
+玉蒲团
+玉乳
+欲仙欲死
+玉穴
+原味内衣
+援助交际
+张筱雨
+招鸡
+招妓
+中年美妇
+抓胸
+自拍
+自慰
+作爱
+18禁
+99bb
+a4u
+a4y
+adult
+amateur
+anal
+a片
+fuck
+gay片
+g点
+g片
+hardcore
+h动画
+h动漫
+incest
+porn
+secom
+sexinsex
+sm女王
+xiao77
+xing伴侣
+tokyohot
+yin荡
+贱人
+装b
+大sb
+傻逼
+傻b
+煞逼
+煞笔
+刹笔
+傻比
+沙比
+欠干
+婊子养的
+我日你
+我操
+我草
+卧艹
+卧槽
+爆你菊
+艹你
+cao你
+你他妈
+真他妈
+别他吗
+草你吗
+草你丫
+操你妈
+擦你妈
+操你娘
+操他妈
+日你妈
+干你妈
+干你娘
+娘西皮
+狗操
+狗草
+狗杂种
+狗日的
+操你祖宗
+操你全家
+操你大爷
+妈逼
+你麻痹
+麻痹的
+妈了个逼
+马勒
+狗娘养
+贱比
+贱b
+下贱
+死全家
+全家死光
+全家不得好死
+全家死绝
+白痴
+无耻
+sb
+杀b
+你吗b
+你妈的
+婊子
+贱货
+人渣
+混蛋
+媚外
+性伴侣
+男公关
+火辣
+精子
+射精
+诱奸
+强奸
+做爱
+性爱
+发生关系
+快感
+处男
+猛男
+少妇
+屌
+屁股
+下体
+a片
+内裤
+咪咪
+白嫩
+粉嫩
+兽性
+风骚
+呻吟
+sm
+阉割
+一丝不挂
+脱光
+干你
+干死
+我干
+裙中性运动
+乱奸
+乱伦
+乱伦类
+乱伦小
+伦理大
+伦理电影
+伦理毛
+伦理片
+裸聊
+裸聊网
+裸体写真
+裸舞视
+裸照
+美女裸体
+美女写真
+美女上门
+美艳少妇
+妹按摩
+妹上门
+迷幻药
+迷幻藥
+迷昏口
+迷昏药
+迷昏藥
+迷魂香
+迷魂药
+迷魂藥
+迷奸粉
+迷奸药
+迷情粉
+迷情水
+迷情药
+迷药
+迷藥
+谜奸药
+骚妇
+骚货
+骚浪
+骚女
+骚嘴
+色电影
+色妹妹
+色情表演
+色情电影
+色情服务
+色情图片
+色情
+色情影片
+色情表演
+色情电影
+色情服务
+色情片
+色视频
+色小说
+性伴侣
+性服务
+性福情
+性感少
+性伙伴
+性交视频
+性交图片
+性奴
+性奴集中营
+性虐
+阴唇
+阴道
+阴蒂
+阴户
+阴间来电
+阴茎
+阴茎增大
+阴茎助勃
+阴毛
+陰唇
+陰道
+陰戶
+淫荡
+淫荡美女
+淫荡视频
+淫荡照片
+淫乱
+淫靡
+淫魔
+淫魔舞
+淫女
+淫情女
+淫肉
+淫騷妹
+淫兽
+淫兽学
+淫水
+淫穴
+morphine
+摇头丸
+迷药
+乖乖粉
+narcotic
+麻醉药
+精神药品
+爱女人
+爱液
+按摩棒
+拔出来
+爆草
+包二奶
+暴干
+暴奸
+暴乳
+爆乳
+暴淫
+屄
+被操
+被插
+被干
+逼奸
+仓井空
+插暴
+操逼
+操黑
+操烂
+肏你
+肏死
+操死
+操我
+厕奴
+插比
+插b
+插逼
+插你
+插我
+插阴
+潮吹
+潮喷
+成人电影
+成人论坛
+成人色情
+成人网站
+成人文学
+成人小说
+艳情小说
+成人游戏
+吃精
+赤裸
+抽插
+扌由插
+抽一插
+春药
+大波
+大力抽送
+大乳
+荡妇
+荡女
+盗撮
+多人轮
+发浪
+放尿
+肥逼
+粉穴
+封面女郎
+风月大陆
+干死你
+干穴
+肛交
+肛门
+龟头
+裹本
+国产av
+好嫩
+豪乳
+黑逼
+后庭
+后穴
+虎骑
+花花公子
+换妻俱乐部
+黄片
+几吧
+鸡吧
+鸡巴
+鸡奸
+寂寞男
+寂寞女
+妓女
+激情
+集体淫
+奸情
+叫床
+脚交
+金鳞岂是池中物
+金麟岂是池中物
+精液
+就去日
+巨屌
+菊花洞
+菊门
+巨奶
+巨乳
+菊穴
+开苞
+口爆
+口活
+口射
+口淫
+裤袜
+狂操
+狂插
+浪逼
+浪妇
+浪叫
+浪女
+狼友
+聊性
+流淫
+铃木麻
+凌辱
+漏乳
+露b
+乱交
+乱伦
+轮暴
+轮操
+轮奸
+裸陪
+买春
+美逼
+美少妇
+美乳
+美腿
+美穴
+美幼
+秘唇
+迷奸
+密穴
+蜜穴
+蜜液
+摸奶
+摸胸
+母奸
+奈美
+奶子
+男奴
+内射
+嫩逼
+嫩女
+嫩穴
+捏弄
+女优
+炮友
+砲友
+喷精
+屁眼
+品香堂
+前凸后翘
+强jian
+强奸处女
+情趣用品
+情色
+拳交
+全裸
+群交
+惹火身材
+人妻
+人兽
+日逼
+日烂
+肉棒
+肉逼
+肉唇
+肉洞
+肉缝
+肉棍
+肉茎
+肉具
+揉乳
+肉穴
+肉欲
+乳爆
+乳房
+乳沟
+乳交
+乳头
+三级片
+骚逼
+骚比
+骚女
+骚水
+骚穴
+色逼
+色界
+色猫
+色盟
+色情网站
+色诱
+色欲
+色b
+少年阿宾
+少修正
+射爽
+射颜
+食精
+释欲
+兽奸
+兽交
+手淫
+兽欲
+熟妇
+熟母
+熟女
+爽片
+爽死我了
+双臀
+死逼
+丝袜
+丝诱
+松岛枫
+酥痒
+汤加丽
+套弄
+体奸
+舔脚
+舔阴
+调教
+偷欢
+偷拍
+脱内裤
+文做
+我就色
+舞女
+无修正
+吸精
+夏川纯
+相奸
+小逼
+校鸡
+小穴
+小xue
+写真
+性感妖娆
+性感诱惑
+性虎
+性饥渴
+性技巧
+性奴
+性虐
+性息
+性欲
+胸推
+穴口
+学生妹
+穴图
+亚情
+颜射
+阳具
+杨思敏
+要射了
+夜勤病栋
+一本道
+一夜欢
+一夜情
+一ye情
+阴部
+淫虫
+阴唇
+淫荡
+阴道
+淫电影
+阴阜
+淫妇
+淫河
+阴核
+阴户
+淫贱
+淫叫
+淫教师
+阴茎
+阴精
+淫浪
+淫媚
+淫糜
+淫魔
+淫母
+淫女
+淫虐
+淫妻
+淫情
+淫色
+淫声浪语
+淫兽学园
+淫书
+淫术炼金士
+淫水
+淫娃
+淫威
+淫亵
+淫样
+淫液
+淫照
+阴b
+幼交
+幼男
+幼女
+欲火
+欲女
+玉女心经
+玉蒲团
+玉乳
+欲仙欲死
+玉穴
+原味内衣
+援助交际
+张筱雨
+招鸡
+招妓
+中年美妇
+抓胸
+自拍
+自慰
+作爱
+18禁
+99bb
+a4u
+a4y
+adult
+amateur
+anal
+a片
+fuck
+gay片
+g点
+g片
+hardcore
+h动画
+h动漫
+incest
+porn
+secom
+sexinsex
+sm女王
+xiao77
+xing伴侣
+tokyohot
+yin荡

+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/补充词库.txt → core/construction_review/component/reviewers/sensitive_words_old/补充词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/贪腐词库.txt → core/construction_review/component/reviewers/sensitive_words_old/贪腐词库.txt


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/零时-Tencen.txt.bak → core/construction_review/component/reviewers/sensitive_words_old/零时-Tencen.txt.bak


+ 0 - 0
core/construction_review/component/reviewers/sensitive_words/非法网址.txt → core/construction_review/component/reviewers/sensitive_words_old/非法网址.txt


+ 2 - 2
core/construction_review/component/reviewers/utils/__init__.py

@@ -11,7 +11,7 @@ from .sensitive_word_checker import (
     check_sensitive_words_async,
     format_check_results
 )
-from .directory_extraction import extract_basis_with_langchain_qwen
+from .directory_extraction import extract_basis
 __all__ = [
     'PromptLoader',
     'prompt_loader',
@@ -20,5 +20,5 @@ __all__ = [
     'check_sensitive_words',
     'check_sensitive_words_async',
     'format_check_results',
-    'extract_basis_with_langchain_qwen'
+    'extract_basis'
 ]

+ 138 - 94
core/construction_review/component/reviewers/utils/directory_extraction.py

@@ -11,12 +11,12 @@
 
 from __future__ import annotations
 
-import json  # ✅ 最小修改:新增
+import json
 import re
 import asyncio
 from typing import List
 
-from pydantic import BaseModel, Field, ValidationError  # ✅ 最小修改:新增 ValidationError
+from pydantic import BaseModel, Field, ValidationError
 from langchain_core.prompts import ChatPromptTemplate
 from langchain_core.output_parsers import PydanticOutputParser
 from foundation.ai.agent.generate.model_generate import generate_model_client
@@ -36,15 +36,17 @@ class BasisItems(BaseModel):
     items: List[BasisItem]
 
 
-# --------- 2) Prompt(强约束:只抽《》条目,输出可解析结构)---------
+# --------- 2) Prompt(按章节区分提取规则)---------
 SYSTEM = """
 你是信息抽取助手。请从中文文本中抽取"编制依据/法律法规/规范标准"等条目。
 规则:
-1) 只抽取包含书名号《 》的条目。
-2) 每条条目包括:title(《》内名称,去掉书名号)、suffix(《》后面的版本/日期/修订说明,可为空)、raw(该条目原文)。
-3) 忽略标题行、段落说明、无《》的行。
-4) **重要:title 和 raw 必须保留原文的所有空格和格式,不要修改或去除任何空格。**
+1) 提取所有被书名号《》包裹的条目,**即使格式有错误也要提取**。
+   包含但不限于:《名称》(编号)、《名称》编号、(名称)(编号)、名称》(编号)、《名称(缺结束书名号)、《名称》[编号](方括号)等。
+2) 每条条目包括:title(书名号内名称,去掉书名号)、suffix(后面的编号/版本信息)、raw(该条目原文)。
+3) 忽略标题行、段落说明。
+4) **重要:title 和 raw 必须保留原文的所有空格和标点,不要做任何格式修复。即使原文格式有错误(缺书名号、括号不对、用错括号类型),raw 也必须原样输出。**
 5) 输出必须严格符合格式要求,不要输出任何额外文字。
+{chapter_rules}
 """
 HUMAN ="""
 文本如下:
@@ -54,6 +56,15 @@ HUMAN ="""
 /no_think
 """
 
+_BASIS_RULES = """
+6) **只提取标准、规范、法规、条例类条目**(含标准编号如GB/JGJ/JTG/JT/T/DL/T等,或法律法规名称如XX法/XX条例/XX规程/XX规定)。
+7) **不要提取项目文件类条目**,如施工图设计、施工组织设计、专项施工方案、项目合同等。这些不属于标准规范,不需要审查。
+"""
+
+_NON_BASIS_RULES = """
+6) **不要提取"详见""见""参见""参照""参考"后面紧跟的条目**,这些只是引用说明,不是正文中的标准规范引用。
+"""
+
 prompt = ChatPromptTemplate.from_messages([
     ("system", SYSTEM),
     ("human", HUMAN)
@@ -80,17 +91,26 @@ def fallback_regex(text: str) -> BasisItems:
     
     # 模式1:匹配《名称》(编号)格式
     pattern1 = r'《([^《》]{1,60})》[\s]*[((]([^))]{1,30})[))]'
-    
+
     # 模式2:匹配《名称》编号 格式(编号无括号)
     pattern2 = r'《([^《》]{1,60})》[\s]*([A-Za-z]{0,6}[/-]?[0-9]{2,6}(?:-[0-9]{4})?)'
-    
+
     # 模式3:匹配只有《名称》的格式(在列表结尾或分号前)
     pattern3 = r'《([^《》]{1,60})》(?=[\s]*[;;]|\s*$|\s+[((]\d)'
-    
+
+    # 模式4:《name — 缺少结束书名号
+    pattern4 = r'《([^《》]{1,60})(?=[\s;;、\n]|$)'
+    # 模式5:name》(number) — 缺少开始书名号
+    pattern5 = r'([^《》\s]{2,60})》[\s]*[((]([^))]{1,30})[))]'
+    # 模式6:(name)(number) — 用括号代替书名号
+    pattern6 = r'[((]([^))]{2,60})[))][\s]*[((]([^))]{1,30})[))]'
+    # 模式7:《name》[number] — 用方括号
+    pattern7 = r'《([^《》]{1,60})》[\s]*\[([^\]]{1,30})\]'
+
     # 合并模式,按优先级匹配
     matched_positions = set()
-    
-    for pattern in [pattern1, pattern2, pattern3]:
+
+    for pattern in [pattern1, pattern2, pattern3, pattern4, pattern5, pattern6, pattern7]:
         for match in re.finditer(pattern, text):
             # 检查是否已匹配过此位置
             start_pos = match.start()
@@ -137,18 +157,88 @@ def fallback_regex(text: str) -> BasisItems:
                 # 记录已匹配的位置
                 matched_positions.add(start_pos)
 
+    # 兜底:扫描所有《号,捕获前轮未覆盖的不完整引用
+    for m in re.finditer(r'《([^《》]{1,60})', text):
+        start = m.start()
+        if start in matched_positions:
+            continue
+        # 取《号到下一个《号或100字符之间的文本
+        next_book = text.find('《', start + 1)
+        end = min(next_book, start + 100) if next_book != -1 else start + 100
+        raw = text[start:end].strip()
+        # 去掉末尾的分隔符
+        for delim in [';', ';', '、', '\n', '\r']:
+            idx = raw.find(delim, 1)
+            if idx != -1:
+                raw = raw[:idx].strip()
+        title = m.group(1).strip()
+        if title:
+            items.append(BasisItem(title=title, suffix='', raw=raw))
+            matched_positions.add(start)
+
     logger.info(f"[编制依据提取] 兜底方案提取到 {len(items)} 条")
     return BasisItems(items=items)
 
 
 # --------- 3.5) 根据chapter_code过滤,避免LLM误抽 ---------
+# 标准编号前缀
+_STANDARD_PREFIXES = re.compile(
+    r'GB|JGJ|JTG|JTJ|CJJ|YB|SH|DL|GA|AQ|HG|SY|TB|NB|RB|MH|JG|JC|DB',
+    re.IGNORECASE
+)
+
+# 标准/法规类名称后缀
+_STANDARD_SUFFIXES = re.compile(
+    r'(条例|规程|规范|规定|办法|细则|通则|标准|规则|导则|指南)$'
+)
+
+# 法律类名称后缀(无标准编号,不做格式审查)
+_LAW_SUFFIXES = re.compile(r'(法|法律)$')
+
+
+def is_law_item(item: BasisItem) -> bool:
+    """判断条目是否为法律法规(无标准编号,不做格式审查)"""
+    title = (item.title or "").strip()
+    return bool(_LAW_SUFFIXES.search(title))
+
+# 项目文件关键词(非标准规范)
+_PROJECT_KEYWORDS = re.compile(
+    r'(施工图设计|施工组织设计|专项施工方案|工程可行性|两阶段设计|初步设计|招标文件|合同文件|标段)'
+)
+
+
+def _is_standard_item(item: BasisItem) -> bool:
+    """判断条目是否属于标准规范/法律法规(而非项目文件)"""
+    title = item.title or ""
+    suffix = item.suffix or ""
+
+    # 有标准编号后缀 → 标准
+    if _STANDARD_PREFIXES.search(suffix):
+        return True
+
+    # 标题以法规/标准后缀结尾 → 标准/法规
+    if _STANDARD_SUFFIXES.search(title):
+        return True
+
+    # 标题以法律后缀结尾 → 法律
+    if _LAW_SUFFIXES.search(title):
+        return True
+
+    # 标题包含项目文件关键词 → 非标准
+    if _PROJECT_KEYWORDS.search(title):
+        return False
+
+    # 默认保留(宁多勿漏)
+    return True
+
+
 def _filter_by_chapter_code(items: List[BasisItem], chapter_code: str) -> List[BasisItem]:
     """
     根据章节代码过滤编制依据条目
 
     规则:
-    - 如果 chapter_code == "basis":编制依据章节,不过滤,返回所有条目
-    - 如果 chapter_code != "basis":非编制依据章节,过滤掉raw中没有书名号的条目
+    - basis 章节:过滤空条目 + 过滤非标准规范的项目文件
+    - 非 basis 章节:只过滤空条目
 
     Args:
         items: 待过滤的条目列表
@@ -157,28 +247,22 @@ def _filter_by_chapter_code(items: List[BasisItem], chapter_code: str) -> List[B
     Returns:
         过滤后的条目列表
     """
-    # 编制依据章节,不过滤
+    # 先过滤空条目
+    items = [item for item in items if item.raw.strip()]
+
     if chapter_code == "basis":
-        logger.debug(f"[编制依据提取] 当前为编制依据章节(basis),不过滤,共 {len(items)} 条")
-        return items
-
-    # 非编制依据章节,过滤掉没有书名号的条目(避免LLM误抽)
-    before_count = len(items)
-    filtered_items = [
-        item for item in items
-        if "《" in item.raw and "》" in item.raw
-    ]
-    after_count = len(filtered_items)
-
-    # 如果有过滤,记录日志
-    if before_count != after_count:
-        logger.info(
-            f"[编制依据提取] 非编制依据章节(chapter_code={chapter_code}),"
-            f"过滤掉无书名号条目: {before_count} -> {after_count} "
-            f"(过滤 {before_count - after_count} 条)"
-        )
+        before_count = len(items)
+        items = [item for item in items if _is_standard_item(item)]
+        after_count = len(items)
+        if before_count != after_count:
+            logger.info(
+                f"[编制依据提取] basis章节过滤非标准条目: {before_count} -> {after_count} "
+                f"(过滤 {before_count - after_count} 条项目文件)"
+            )
+        else:
+            logger.debug(f"[编制依据提取] basis章节,共 {len(items)} 条标准规范")
 
-    return filtered_items
+    return items
 
 
 # --------- 4) 最小修改:只做一件事,提取第一个 JSON ---------
@@ -204,77 +288,37 @@ def extract_first_json(text: str) -> dict:
     raise ValueError("JSON 花括号未闭合")
 
 
-# --------- 5) 主函数:使用 LangChain 抽取(最小改动版) ---------
-async def extract_basis_with_langchain_qwen(progress_manager,callback_task_id:str,text: str,chapter_code: str) -> BasisItems:
+# --------- 5) 主函数:非流式调用,底层自动处理 thinking ---------
+async def extract_basis(progress_manager, callback_task_id: str, text: str, chapter_code: str) -> BasisItems:
     """
-    使用 LangChain + LLM 提取编制依据信息(流式输出版本
+    使用 LLM 提取编制依据信息(非流式,thinking 由底层自动处理
     """
-    # 标准化文本(无论是否走LLM,都先做)
     text = text.replace("\r\n", "\n").replace("\r", "\n")
 
     try:
-        # 创建解析器(✅ 保留:仅用于 format_instructions)
         parser = PydanticOutputParser(pydantic_object=BasisItems)
 
-        # 构建消息
+        # 根据章节类型选择提取规则
+        chapter_rules = _BASIS_RULES if chapter_code == "basis" else _NON_BASIS_RULES
+
         messages = prompt.format_messages(
             input_text=text,
-            format_instructions=parser.get_format_instructions()
+            format_instructions=parser.get_format_instructions(),
+            chapter_rules=chapter_rules
         )
 
-        logger.info(f"[编制依据提取] 开始使用 LLM 提取,文本长度: {len(text)}")
-
-        # 推送开始消息(使用独立命名空间,避免与主流程进度冲突)
-        if progress_manager and callback_task_id:
-            try:
-                await progress_manager.update_stage_progress(
-                    callback_task_id=callback_task_id,
-                    stage_name="编制依据提取-子任务",  # 独立命名空间
-                    status="processing",
-                    message=f"开始编制依据提取",
-                    overall_task_status="processing",
-                    event_type="processing"
-                    # 不设置 current,避免覆盖主流程进度
-                )
-            except Exception as e:
-                logger.error(f"SSE推送开始消息失败: {e}")
-
-        # 流式调用模型,每检测到5个}符号推送一次进度
-        raw_out = ""
-        brace_count = 0
-
-        # 使用通用模型底座的流式调用(通过 function_name 从 model_setting.yaml 加载配置)
-        for chunk in generate_model_client.get_model_generate_stream(
+        logger.info(f"[编制依据提取] 开始 LLM 提取,文本长度: {len(text)}")
+
+        # 非流式调用:底层自动处理 thinking 模式,返回干净的 str
+        raw_out = await generate_model_client.get_model_generate_invoke(
             trace_id=callback_task_id or "directory_extract",
             messages=messages,
             function_name="directory_extraction"
-        ):
-            raw_out += chunk
-            
-            # 统计}符号出现次数
-            for char in chunk:
-                if char == "}":
-                    brace_count += 1
-                    
-                    # 每5个}推送一次进度(使用独立命名空间)
-                    if brace_count % 5 == 0:
-                        if progress_manager and callback_task_id:
-                            try:
-                                await progress_manager.update_stage_progress(
-                                    callback_task_id=callback_task_id,
-                                    stage_name="编制依据提取-子任务",  # 独立命名空间
-                                    status="processing",
-                                    message=f"编制依据提取中... (已处理 {brace_count} 个结构)",
-                                    overall_task_status="processing",
-                                    event_type="processing"
-                                    # 不设置 current,避免覆盖主流程进度
-                                )
-                            except Exception as e:
-                                logger.error(f"SSE推送进度失败: {e}")
-        
-        logger.info(f"编制依据提取调试:{raw_out}")
-
-        # ✅ 最小修改:不再 parser.parse / 不再 _parse_with_retry
+        )
+
+        logger.debug(f"[编制依据提取] LLM 返回: {raw_out[:500]}")
+
+        # 解析:模型返回应为纯 JSON,extract_first_json 兜底处理多余文本
         data = extract_first_json(raw_out)
         parsed = BasisItems.model_validate(data)
 
@@ -292,7 +336,6 @@ async def extract_basis_with_langchain_qwen(progress_manager,callback_task_id:st
 
             cleaned.append(BasisItem(title=title, suffix=suffix, raw=raw))
 
-        # ✅ 新增:根据chapter_code过滤,避免LLM在非编制依据章节误抽
         cleaned = _filter_by_chapter_code(cleaned, chapter_code)
 
         if cleaned:
@@ -300,16 +343,17 @@ async def extract_basis_with_langchain_qwen(progress_manager,callback_task_id:st
             return BasisItems(items=cleaned)
 
         logger.warning("[编制依据提取] LLM 未提取到内容,使用兜底方案")
-        # ✅ 修改:兜底方案也要经过过滤
         fallback_result = fallback_regex(text)
         filtered_items = _filter_by_chapter_code(fallback_result.items, chapter_code)
         return BasisItems(items=filtered_items)
 
     except (json.JSONDecodeError, ValidationError, ValueError) as e:
+        logger.error(f"[编制依据提取] LLM 解析失败,降级兜底: {type(e).__name__}: {e}")
         fallback_result = fallback_regex(text)
         filtered_items = _filter_by_chapter_code(fallback_result.items, chapter_code)
         return BasisItems(items=filtered_items)
     except Exception as e:
+        logger.error(f"[编制依据提取] LLM 调用异常,降级兜底: {type(e).__name__}: {e}")
         fallback_result = fallback_regex(text)
         filtered_items = _filter_by_chapter_code(fallback_result.items, chapter_code)
         return BasisItems(items=filtered_items)
@@ -357,7 +401,7 @@ if __name__ == "__main__":
 """
 
     async def _demo_run():
-        result = await extract_basis_with_langchain_qwen(None, None, demo)
+        result = await extract_basis(None, None, demo, "basis")
         print(f"\n提取到 {len(result.items)} 条编制依据:")
         for idx, item in enumerate(result.items, 1):
             print(f"\n{idx}. {item.model_dump()}")

+ 5 - 70
core/construction_review/component/reviewers/utils/punctuation_result_processor.py

@@ -11,23 +11,7 @@ from langchain_core.prompts import ChatPromptTemplate
 from langchain_core.output_parsers import PydanticOutputParser, StrOutputParser
 from langchain_openai import ChatOpenAI
 
-# 导入多模型编号生成器和验证器
-try:
-    from .reference_number_generator import (
-        validate_reference_number,
-        generate_reference_number,
-        ModelVoteResult,
-        ValidationResult,
-        _extract_reference_number
-    )
-except ImportError:
-    from reference_number_generator import (
-        validate_reference_number,
-        generate_reference_number,
-        ModelVoteResult,
-        ValidationResult,
-        _extract_reference_number
-    )
+# 多模型投票已移除,格式建议直接返回基础建议
 
 
 # ===== 1) 定义结构 =====
@@ -269,70 +253,21 @@ def _is_valid_number_format(content: str) -> bool:
     return has_digit and (has_english or has_chinese)
 
 
-# ===== 6.7) 辅助函数:生成建议(新流程) =====
+# ===== 6.7) 辅助函数:生成建议 =====
 async def _generate_suggestion_with_validation(
     original_text: str,
     issue_type: str,
     base_suggestion: str
 ) -> str:
-    """
-    使用新流程生成编号建议:
-    1. 首先验证现有编号是否正确
-    2. 如果验证通过,接受该编号
-    3. 如果验证失败,调用5个模型生成正确编号
-    """
-    try:
-        regulation_name = _extract_regulation_name(original_text)
-        existing_number = _extract_existing_number(original_text)
-        
-        # 第一步:如果存在编号,先验证是否正确
-        if existing_number and existing_number.strip():
-            validation_result = await validate_reference_number(
-                regulation_name=regulation_name,
-                existing_number=existing_number
-            )
-            
-            if validation_result and validation_result.is_valid:
-                # 验证通过,接受该编号(不再计较是否为字母+数字格式)
-                if issue_type == "missing_bracket":
-                    return f"将规范编号用括号包裹,正确格式:《{regulation_name}》({existing_number})"
-                else:
-                    return f"补充规范编号,正确格式:《{regulation_name}》({existing_number})"
-        
-        # 第二步:验证失败或没有编号,调用5个模型生成
-        existing_info = existing_number if existing_number else ""
-        vote_result = await generate_reference_number(
-            regulation_name=regulation_name,
-            existing_info=existing_info
-        )
-        
-        if vote_result and vote_result.confidence >= 0.5:
-            # 有可信的AI生成结果
-            ai_number = vote_result.generated_number
-            
-            if issue_type == "missing_bracket":
-                return f"将规范编号用括号包裹,正确格式:《{regulation_name}》({ai_number})"
-            else:
-                return f"补充规范编号,正确格式:《{regulation_name}》({ai_number})"
-        else:
-            # AI生成失败,返回基础建议
-            return base_suggestion
-            
-    except Exception:
-        # 异常时返回基础建议
-        return base_suggestion
+    """格式建议直接返回基础建议,不再调用多模型投票"""
+    return base_suggestion
 
 
 # ===== 7) 核心方法 =====
 async def process_punctuation_results(check_results: str, enterprise_items: list = None) -> str:
     """
     根据标点符号检查结果生成详细的问题分析报告
-    
-    新流程:
-    1. 首先验证现有编号是否正确(调用模型验证)
-    2. 如果验证通过,接受该编号
-    3. 如果验证失败,调用5个模型生成正确编号
-    
+
     Args:
         check_results: 标点符号检查结果的JSON字符串
         enterprise_items: 企业内部文件列表(在标准库中未找到匹配的文件)

+ 1 - 1
core/construction_review/workflows/ai_review_workflow.py

@@ -48,7 +48,7 @@ import pandas as pd
 from foundation.observability.logger.loggering import review_logger as logger
 from foundation.observability.cachefiles import cache, CacheBaseDir
 from core.construction_review.component.reviewers.utils.directory_extraction import (
-    extract_basis_with_langchain_qwen,
+    extract_basis,
 )
 from ..component.ai_review_engine import AIReviewEngine
 from ..component.reviewers.utils.inter_tool import InterTool

+ 1 - 1
core/construction_review/workflows/core_functions/ai_review_core_fun.py

@@ -273,7 +273,7 @@ class AIReviewCoreFun:
             'timeliness_basis_reviewer' in func_names or 'timeliness_content_reviewer' in func_names) and not is_complete_field:
             logger.debug("开始执行编制依据/时效性预处理")
             # 预处理编制依据/时效性审查所需内容
-            basis_content = await directory_extraction.extract_basis_with_langchain_qwen(
+            basis_content = await directory_extraction.extract_basis(
                 state['progress_manager'],
                 state["callback_task_id"],
                 chunk.get('content', ''),

+ 1 - 1
utils_test/Sensitive_Test/test_grammar_check_chain.py

@@ -40,7 +40,7 @@ sys.path.insert(0, str(project_root))
 _mock_dir_ext = types.ModuleType(
     "core.construction_review.component.reviewers.utils.directory_extraction"
 )
-_mock_dir_ext.extract_basis_with_langchain_qwen = MagicMock()
+_mock_dir_ext.extract_basis = MagicMock()
 _mock_dir_ext.BasisItems = MagicMock()
 _mock_dir_ext.BasisItem = MagicMock()
 sys.modules["core.construction_review.component.reviewers.utils.directory_extraction"] = (