Jelajahi Sumber

v0.0.4更新了语义逻辑的提示词,使其不过于敏感,不再过多关注方案技术参数细节

Diamond_ore 1 bulan lalu
induk
melakukan
f83af41393

+ 238 - 0
Semantic_Logic_Test/SUMMARY.md

@@ -0,0 +1,238 @@
+# 语义逻辑审查模块 - 测试总结
+
+## ✅ 完成的工作
+
+### 1. 核心功能实现
+- ✅ 创建了 `semantic_logic.py` 模块
+- ✅ 实现了 `SemanticLogicReviewer` 类
+- ✅ 配置了 OpenAI 兼容 API(qwen3-30b 模型)
+- ✅ 集成了提示词模板加载功能
+- ✅ 实现了进度回调通知机制
+- ✅ 返回 `ReviewResult` 类型对象
+
+### 2. 业务逻辑重构
+- ✅ 将 `ai_review_engine.py` 中的 423-482 行业务逻辑移动到 `semantic_logic.py`
+- ✅ 在 `check_semantic_logic` 函数中引用新模块
+- ✅ 保留了原有的进度回调通知(456-477 行逻辑)
+- ✅ 简化了 `ai_review_engine.py` 中的代码
+
+### 3. 测试套件创建
+- ✅ 创建了完整的单元测试文件 `test_semantic_logic.py`
+- ✅ 包含 15 个测试用例,覆盖多种场景
+- ✅ 创建了测试配置文件(pytest.ini, conftest.py)
+- ✅ 创建了测试依赖文件(requirements_test.txt)
+- ✅ 创建了测试数据示例(test_data.py)
+- ✅ 创建了测试运行脚本(run_tests.bat, run_tests.py)
+- ✅ 编写了详细的 README 文档
+
+## 📊 测试覆盖范围
+
+### 基础功能测试(10个)
+1. ✅ 审查器初始化测试
+2. ✅ 全局单例实例测试
+3. ✅ 模型配置验证
+4. ✅ 语义逻辑检查成功场景
+5. ✅ 无状态字典的检查场景
+6. ✅ API 调用失败处理
+7. ✅ 空内容处理
+8. ✅ 带参考信息的检查
+9. ✅ 消息格式转换
+10. ✅ 执行时间跟踪
+
+### 集成测试(1个)
+11. ✅ 完整工作流程测试(需要实际API)
+
+### 边界情况测试(3个)
+12. ✅ 超长内容处理
+13. ✅ 特殊字符处理
+14. ✅ Unicode字符处理
+
+## 📁 文件结构
+
+```
+Semantic_Logic_Test/
+├── test_semantic_logic.py      # 主测试文件(15个测试用例)
+├── test_data.py                # 测试数据示例
+├── conftest.py                 # pytest 配置和 fixtures
+├── pytest.ini                  # pytest 配置文件
+├── requirements_test.txt       # 测试依赖
+├── run_tests.bat              # Windows 测试运行脚本
+├── run_tests.py               # Python 测试运行脚本
+├── README.md                  # 测试文档
+└── SUMMARY.md                 # 本总结文档
+```
+
+## 🚀 快速开始
+
+### 安装测试依赖
+```bash
+pip install -r Semantic_Logic_Test/requirements_test.txt
+```
+
+### 运行所有测试
+```bash
+# 方式1:使用 pytest 直接运行
+pytest Semantic_Logic_Test/test_semantic_logic.py -v
+
+# 方式2:使用 Python 脚本
+python Semantic_Logic_Test/run_tests.py
+
+# 方式3:使用 Windows 批处理脚本
+Semantic_Logic_Test\run_tests.bat
+```
+
+### 查看测试覆盖率
+```bash
+pytest Semantic_Logic_Test/test_semantic_logic.py --cov=core.construction_review.component.reviewers.semantic_logic --cov-report=html
+```
+
+## 🔧 技术实现细节
+
+### 1. OpenAI API 集成
+```python
+# 模型配置
+SEMANTIC_LOGIC_MODEL_CONFIG = {
+    "base_url": "http://192.168.91.253:8003/v1",
+    "api_key": "sk-123456",
+    "model": "qwen3-30b",
+    "temperature": 0.7,
+    "max_tokens": 2000
+}
+
+# 使用 AsyncOpenAI 客户端
+self.client = AsyncOpenAI(
+    base_url=SEMANTIC_LOGIC_MODEL_CONFIG["base_url"],
+    api_key=SEMANTIC_LOGIC_MODEL_CONFIG["api_key"]
+)
+```
+
+### 2. 提示词模板加载
+```python
+# 构造提示词参数
+prompt_kwargs = {
+    "review_content": review_content,
+    "review_references": review_references or ""
+}
+
+# 获取提示词模板
+prompt_template = prompt_loader.get_prompt_template(
+    "basic", 
+    "semantic_logic_check", 
+    **prompt_kwargs
+)
+```
+
+### 3. 进度回调通知
+```python
+# 推送审查完成信息
+if state and state.get("progress_manager"):
+    review_result_data = {
+        'name': 'semantic_check',
+        'success': result.success,
+        'details': result.details,
+        'error_message': result.error_message,
+        'execution_time': result.execution_time,
+        'timestamp': time.time()
+    }
+    
+    asyncio.create_task(
+        state["progress_manager"].update_stage_progress(
+            callback_task_id=state["callback_task_id"],
+            stage_name=stage_name,
+            current=None,
+            status="processing",
+            message=f"semantic_check 审查完成,耗时: {result.execution_time:.2f}s",
+            issues=[review_result_data],
+            event_type="processing"
+        )
+    )
+```
+
+### 4. 返回值类型
+```python
+# 使用 ReviewResult 对象
+result = ReviewResult(
+    success=True,
+    details={
+        "name": "semantic_check",
+        "response": model_response
+    },
+    error_message=None,
+    execution_time=execution_time
+)
+```
+
+## 🧪 测试策略
+
+### Mock 策略
+- 使用 `unittest.mock` 模拟 OpenAI API 调用
+- 使用 `AsyncMock` 模拟异步操作
+- 模拟提示词加载器和进度管理器
+
+### 测试隔离
+- 每个测试独立运行,不依赖其他测试
+- 使用 fixtures 提供测试数据
+- 测试后自动清理
+
+### 异步测试
+- 使用 `@pytest.mark.asyncio` 装饰器
+- 使用 `AsyncMock` 模拟异步函数
+- 测试异步操作的正确性
+
+## 📈 测试结果
+
+预期测试结果:
+- ✅ 14 个测试通过
+- ⏭️ 1 个测试跳过(集成测试)
+- ❌ 0 个测试失败
+
+## 🔍 代码质量
+
+### 代码覆盖率目标
+- 目标覆盖率:> 90%
+- 核心功能覆盖率:100%
+- 异常处理覆盖率:100%
+
+### 代码规范
+- 遵循 PEP 8 规范
+- 使用类型提示
+- 完整的文档字符串
+- 清晰的变量命名
+
+## 🐛 已知问题
+
+1. **集成测试需要实际 API**
+   - 集成测试默认跳过
+   - 需要实际的 API 服务才能运行
+
+2. **网络依赖**
+   - 实际使用时需要网络连接
+   - 测试使用 Mock,不需要网络
+
+## 🔮 未来改进
+
+1. **增加更多测试场景**
+   - 并发测试
+   - 压力测试
+   - 性能测试
+
+2. **改进错误处理**
+   - 更详细的错误信息
+   - 重试机制
+   - 降级策略
+
+3. **优化性能**
+   - 缓存机制
+   - 批量处理
+   - 异步优化
+
+## 📞 联系方式
+
+如有问题或建议,请联系开发团队。
+
+---
+
+**创建日期**: 2025-12-29  
+**版本**: 1.0.0  
+**状态**: ✅ 完成
+

+ 24 - 0
Semantic_Logic_Test/requirements_test.txt

@@ -0,0 +1,24 @@
+# 测试依赖包
+
+# 核心测试框架
+pytest>=7.4.0
+pytest-asyncio>=0.21.0
+pytest-mock>=3.11.0
+pytest-cov>=4.1.0
+
+# HTML 报告生成
+pytest-html>=3.2.0
+
+# 异步测试支持
+asyncio>=3.4.3
+
+# Mock 和测试工具
+unittest-mock>=1.5.0
+
+# 代码覆盖率
+coverage>=7.2.0
+
+# 其他测试工具
+pytest-timeout>=2.1.0
+pytest-xdist>=3.3.0  # 并行测试
+

+ 76 - 0
Semantic_Logic_Test/run_tests.bat

@@ -0,0 +1,76 @@
+@echo off
+REM Windows 批处理脚本 - 快速运行测试
+
+echo ========================================
+echo 语义逻辑审查模块测试套件
+echo ========================================
+echo.
+
+cd /d "%~dp0\.."
+
+echo 当前目录: %CD%
+echo.
+
+REM 检查 Python 是否安装
+python --version >nul 2>&1
+if errorlevel 1 (
+    echo [错误] 未找到 Python,请先安装 Python
+    pause
+    exit /b 1
+)
+
+echo [信息] 检查测试依赖...
+python -c "import pytest" >nul 2>&1
+if errorlevel 1 (
+    echo [警告] 缺少测试依赖,正在安装...
+    pip install -r Semantic_Logic_Test\requirements_test.txt
+)
+
+echo.
+echo ========================================
+echo 请选择要运行的测试:
+echo ========================================
+echo   1. 运行所有测试
+echo   2. 运行所有测试(详细输出)
+echo   3. 运行基础功能测试
+echo   4. 运行边界情况测试
+echo   5. 运行测试并生成覆盖率报告
+echo   6. 运行测试并生成 HTML 报告
+echo   7. 只运行失败的测试
+echo   0. 退出
+echo.
+
+set /p choice="请输入选项 (0-7): "
+
+if "%choice%"=="1" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py -v
+) else if "%choice%"=="2" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py -v -s
+) else if "%choice%"=="3" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py::TestSemanticLogicReviewer -v
+) else if "%choice%"=="4" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py::TestEdgeCases -v
+) else if "%choice%"=="5" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py --cov=core.construction_review.component.reviewers.semantic_logic --cov-report=html --cov-report=term
+    echo.
+    echo [信息] 覆盖率报告已生成到 htmlcov\index.html
+) else if "%choice%"=="6" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py --html=Semantic_Logic_Test\report.html --self-contained-html
+    echo.
+    echo [信息] HTML 报告已生成到 Semantic_Logic_Test\report.html
+) else if "%choice%"=="7" (
+    pytest Semantic_Logic_Test\test_semantic_logic.py --lf -v
+) else if "%choice%"=="0" (
+    echo.
+    echo 再见!
+    exit /b 0
+) else (
+    echo.
+    echo [错误] 无效的选项
+    pause
+    exit /b 1
+)
+
+echo.
+pause
+

+ 130 - 0
Semantic_Logic_Test/run_tests.py

@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+快速运行测试脚本
+提供便捷的测试运行命令
+"""
+
+import sys
+import os
+import subprocess
+from pathlib import Path
+
+
+def run_command(cmd, description):
+    """运行命令并显示结果"""
+    print(f"\n{'='*60}")
+    print(f"🚀 {description}")
+    print(f"{'='*60}\n")
+    
+    result = subprocess.run(cmd, shell=True)
+    
+    if result.returncode == 0:
+        print(f"\n✅ {description} - 成功")
+    else:
+        print(f"\n❌ {description} - 失败")
+    
+    return result.returncode
+
+
+def main():
+    """主函数"""
+    # 切换到项目根目录
+    project_root = Path(__file__).parent.parent
+    os.chdir(project_root)
+    
+    print(f"📁 工作目录: {os.getcwd()}")
+    
+    # 检查是否安装了测试依赖
+    print("\n📦 检查测试依赖...")
+    try:
+        import pytest
+        import pytest_asyncio
+        print("✅ 测试依赖已安装")
+    except ImportError:
+        print("❌ 缺少测试依赖,正在安装...")
+        subprocess.run([
+            sys.executable, "-m", "pip", "install", 
+            "-r", "Semantic_Logic_Test/requirements_test.txt"
+        ])
+    
+    # 显示菜单
+    print("\n" + "="*60)
+    print("🧪 语义逻辑审查模块测试套件")
+    print("="*60)
+    print("\n请选择要运行的测试:")
+    print("  1. 运行所有测试")
+    print("  2. 运行所有测试(详细输出)")
+    print("  3. 运行基础功能测试")
+    print("  4. 运行边界情况测试")
+    print("  5. 运行测试并生成覆盖率报告")
+    print("  6. 运行测试并生成 HTML 报告")
+    print("  7. 只运行失败的测试")
+    print("  8. 运行特定测试(手动输入)")
+    print("  0. 退出")
+    
+    choice = input("\n请输入选项 (0-8): ").strip()
+    
+    test_file = "Semantic_Logic_Test/test_semantic_logic.py"
+    
+    if choice == "1":
+        return run_command(
+            f"pytest {test_file} -v",
+            "运行所有测试"
+        )
+    
+    elif choice == "2":
+        return run_command(
+            f"pytest {test_file} -v -s",
+            "运行所有测试(详细输出)"
+        )
+    
+    elif choice == "3":
+        return run_command(
+            f"pytest {test_file}::TestSemanticLogicReviewer -v",
+            "运行基础功能测试"
+        )
+    
+    elif choice == "4":
+        return run_command(
+            f"pytest {test_file}::TestEdgeCases -v",
+            "运行边界情况测试"
+        )
+    
+    elif choice == "5":
+        return run_command(
+            f"pytest {test_file} --cov=core.construction_review.component.reviewers.semantic_logic --cov-report=html --cov-report=term",
+            "运行测试并生成覆盖率报告"
+        )
+    
+    elif choice == "6":
+        return run_command(
+            f"pytest {test_file} --html=Semantic_Logic_Test/report.html --self-contained-html",
+            "运行测试并生成 HTML 报告"
+        )
+    
+    elif choice == "7":
+        return run_command(
+            f"pytest {test_file} --lf -v",
+            "只运行失败的测试"
+        )
+    
+    elif choice == "8":
+        test_name = input("请输入测试方法名称(例如: test_reviewer_initialization): ").strip()
+        return run_command(
+            f"pytest {test_file}::TestSemanticLogicReviewer::{test_name} -v -s",
+            f"运行测试: {test_name}"
+        )
+    
+    elif choice == "0":
+        print("\n👋 再见!")
+        return 0
+    
+    else:
+        print("\n❌ 无效的选项")
+        return 1
+
+
+if __name__ == "__main__":
+    sys.exit(main())
+

+ 160 - 0
Semantic_Logic_Test/test_data.py

@@ -0,0 +1,160 @@
+"""
+测试数据示例
+提供各种测试场景的示例数据
+"""
+
+# 正常的施工方案内容
+NORMAL_REVIEW_CONTENT = """
+第一章 工程概况
+
+1.1 项目基本信息
+本工程为四川省会理至禄劝高速公路项目,路线全长约120公里,设计速度80km/h,
+路基宽度24.5米,双向四车道。主要工程内容包括路基工程、桥梁工程、隧道工程等。
+
+1.2 施工范围
+本标段起讫桩号为K0+000~K30+000,主要包括:
+- 路基土石方工程约200万立方米
+- 桥梁工程5座,总长约2000米
+- 涵洞工程20道
+- 路面工程约30公里
+
+1.3 工期安排
+计划工期:24个月
+开工日期:2024年3月1日
+竣工日期:2026年2月28日
+"""
+
+# 带有逻辑问题的内容
+LOGIC_ERROR_CONTENT = """
+第二章 施工方案
+
+2.1 施工顺序
+本工程采用先上后下的施工顺序,首先进行桥梁上部结构施工,然后进行桥墩基础施工。
+(注:这里存在逻辑错误,应该先施工基础再施工上部结构)
+
+2.2 工期安排
+本工程计划工期为6个月,但根据施工内容分析,实际需要至少12个月才能完成。
+(注:工期安排不合理)
+"""
+
+# 空内容
+EMPTY_CONTENT = ""
+
+# 超长内容
+VERY_LONG_CONTENT = """
+第三章 施工技术方案
+""" + "\n".join([f"3.{i} 施工工艺详细说明第{i}条,包含大量技术细节和参数..." * 10 for i in range(1, 1001)])
+
+# 特殊字符内容
+SPECIAL_CHARS_CONTENT = """
+特殊字符测试:
+- 符号:@#$%^&*()_+-={}[]|\\:;"'<>,.?/~`
+- 数学符号:±×÷≈≠≤≥∞∑∫√
+- 单位符号:℃、㎡、㎥、㎏、㎜
+- 其他:①②③④⑤⑥⑦⑧⑨⑩
+"""
+
+# Unicode 多语言内容
+UNICODE_CONTENT = """
+多语言测试:
+- 中文:施工方案审查
+- English: Construction Plan Review
+- 日本語:建設計画レビュー
+- 한국어: 건설 계획 검토
+- Русский: Обзор плана строительства
+- العربية: مراجعة خطة البناء
+- Emoji: 🚧🏗️👷‍♂️📋✅❌
+"""
+
+# 参考标准示例
+REFERENCE_STANDARDS = """
+参考标准:
+1. 《公路工程技术标准》JTG B01-2014
+2. 《公路桥涵施工技术规范》JTG/T 3650-2020
+3. 《公路路基施工技术规范》JTG/T 3610-2019
+4. 《公路工程质量检验评定标准》JTG F80/1-2017
+"""
+
+# 审查位置标签示例
+REVIEW_LOCATIONS = [
+    "第一章 工程概况",
+    "第二章 施工方案",
+    "第三章 质量保证措施",
+    "第四章 安全保证措施",
+    "第五章 环境保护措施",
+]
+
+# Trace ID 示例
+TRACE_IDS = [
+    "semantic_check_001",
+    "semantic_check_002",
+    "semantic_check_003",
+]
+
+# 模拟的 API 响应
+MOCK_API_RESPONSES = {
+    "success": "审查结果:内容逻辑清晰,结构合理,符合规范要求。未发现明显问题。",
+    "with_issues": """
+审查结果:发现以下问题:
+1. 施工顺序存在逻辑错误,应先进行基础施工再进行上部结构施工
+2. 工期安排不合理,建议调整为12个月
+3. 缺少安全措施的详细说明
+    """,
+    "empty": "内容为空,无法进行审查。",
+    "error": "审查失败:API 连接超时",
+}
+
+# 状态字典示例
+def create_mock_state():
+    """创建模拟的状态字典"""
+    from unittest.mock import AsyncMock
+    
+    mock_progress_manager = AsyncMock()
+    mock_progress_manager.update_stage_progress = AsyncMock()
+    
+    return {
+        "progress_manager": mock_progress_manager,
+        "callback_task_id": "test_callback_task_123",
+        "session_id": "test_session_456",
+    }
+
+# 测试场景配置
+TEST_SCENARIOS = {
+    "normal": {
+        "content": NORMAL_REVIEW_CONTENT,
+        "references": REFERENCE_STANDARDS,
+        "location": REVIEW_LOCATIONS[0],
+        "expected_success": True,
+    },
+    "logic_error": {
+        "content": LOGIC_ERROR_CONTENT,
+        "references": REFERENCE_STANDARDS,
+        "location": REVIEW_LOCATIONS[1],
+        "expected_success": True,
+    },
+    "empty": {
+        "content": EMPTY_CONTENT,
+        "references": "",
+        "location": REVIEW_LOCATIONS[0],
+        "expected_success": True,
+    },
+    "long": {
+        "content": VERY_LONG_CONTENT,
+        "references": REFERENCE_STANDARDS,
+        "location": REVIEW_LOCATIONS[2],
+        "expected_success": True,
+    },
+    "special_chars": {
+        "content": SPECIAL_CHARS_CONTENT,
+        "references": "",
+        "location": REVIEW_LOCATIONS[3],
+        "expected_success": True,
+    },
+    "unicode": {
+        "content": UNICODE_CONTENT,
+        "references": "",
+        "location": REVIEW_LOCATIONS[4],
+        "expected_success": True,
+    },
+}
+

+ 12 - 9
core/construction_review/component/reviewers/prompt/basic_reviewers.yaml

@@ -81,7 +81,7 @@ semantic_logic_check:
     你的职责是发现真实存在的逻辑错误,而非挑剔文字表达或提出主观性建议。
 
     # 审查范围
-    仅审查以下三类明确的语义逻辑问题:
+    ****审查以下三类明确的语义逻辑问题**仅**审查以下三类明确的语义逻辑问题**仅**审查以下三类明确的语义逻辑问题:
     
     1. **逻辑矛盾** - 同一文档内出现相互冲突的陈述
        示例:前文说"采用A方法",后文说"不采用A方法"
@@ -90,7 +90,7 @@ semantic_logic_check:
        示例:"因为天气晴朗,所以混凝土强度不足"(因果无关)
        
     3. **条件与结论不匹配** - 给定条件无法推导出所述结论
-       示例:"当温度低于5℃时,可正常施工"(违背常识)
+       示例:"当温度低于5℃时,可正常施工"(违背常识)(仅审查违背常识,不要过多的去干预实际的施工参数、施工性能)
 
     # 工作流程 (Workflow)
     
@@ -99,7 +99,6 @@ semantic_logic_check:
     步骤3:检查是否存在上述三类明确的逻辑问题
     步骤4:对于疑似问题,进行二次验证:
            - 是否确实存在逻辑冲突?
-           - 是否可能是专业术语的正常表达?
            - 是否可能是上下文理解不足导致的误判?
     步骤5:仅输出确认无误的问题
 
@@ -114,14 +113,17 @@ semantic_logic_check:
     6. 禁止在没有明确逻辑错误时输出问题
     7. 禁止将"表达不够完美"当作"逻辑错误"
     8. 禁止将"可以优化"当作"必须修改"
-    
+    9. 禁止对所谓的"表述不恰当"、"表述过于严格"当做错误点,如你不能将“禁止夜间施工”改为“应在增加照明条件下允许夜间施工”这样的建议端上来
+    10. **禁止审查过于专业的知识**,你只是审查通用的语义逻辑关系,而并非需要你根据你的知识去审查过多的部分如涉及到架桥参数、施工参数等等一些列的问题,这些问题有后续流程会处理,你暂且跳过
+    11. **禁止对专业知识进行点评**,如技术参数、技术规范、技术条文,你对这方面知识还是较为落后的,你不需要对这方便进行涉猎
+
     必须遵守:
     1. 必须基于客观事实和逻辑规则判断
     2. 必须确保问题的真实性和严重性
-    3. 必须结合建筑施工专业知识理解内容
-    4. 必须区分"逻辑错误"与"表达习惯"
-    5. 必须在不确定时选择"无明显问题"
-    6. 必须保持高标准:宁缺毋滥
+    3. 必须区分"逻辑错误"与"表达习惯"
+    4. 必须在不确定时选择"无明显问题"
+    5. 必须保持高标准:宁缺毋滥
+    6. 给出的上下文可能不完整,你需要注意不同序号下,有些地方可能来源于不同模块,如前面4条是第(2)节内容,后面有明确申明如“(3)xxx规范”这样的那么前后文就没有参考价值,属于前后文不相关
     
     # 风险等级判定标准 (Risk Level)
     
@@ -142,6 +144,8 @@ semantic_logic_check:
     4. **实质审查原则**:关注实质性逻辑错误,忽略形式问题
     5. **严格证据原则**:必须有明确证据证明存在逻辑错误
     6. **勿偏离注意力**:你只能审查语义语法方面的相关问题,如果遇到了技术参数错误、某处未申明技术参数规范等等行为不用作为错误
+    7. **不要钻牛角尖**:不要去钻牛角尖,不要为错找错,如“日最高气温达到39℃以上时,当日应停止作业”不要以为是“停止所有”,以偏概全,过度敏感
+    8. **不审查专业点**:**不要**审查专业知识如施工技术规范、技术参数、技术步骤、技术要点等等,你的知识过于落后,无法满足当前新规范的要求,谢谢
 
     审查参考:
     {review_references}
@@ -157,7 +161,6 @@ semantic_logic_check:
     1. 仅识别明确的逻辑矛盾、因果错误、条件结论不匹配问题
     2. 必须确保问题的真实性,不得对正确内容提出修改
     3. 不确定是否为问题时,必须输出"无明显问题"
-    4. 必须结合建筑施工专业知识和完整语境判断
     
     ## 输出格式: