""" 测试 _keyword_based_intent 核心意图识别逻辑 不依赖任何外部服务,纯本地关键词匹配测试 """ import sys import os from pathlib import Path # 添加项目路径 sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from services.qwen_service import QwenService service = QwenService() PASS = 0 FAIL = 0 def assert_intent(message, expected_business_type, expected_should_redirect, expected_domain_type, expected_intent_type, label=""): global PASS, FAIL bt, sr, dt, it = service._keyword_based_intent(message) ok = (bt == expected_business_type and sr == expected_should_redirect and dt == expected_domain_type and it == expected_intent_type) if ok: PASS += 1 print(f" ✅ {label or message[:40]}") else: FAIL += 1 print(f" ❌ {label or message[:40]}") print(f" expected: bt={expected_business_type} sr={expected_should_redirect} dt={expected_domain_type} it={expected_intent_type}") print(f" got: bt={bt} sr={sr} dt={dt} it={it}") # ────────────────────────────────────────────────────────────── # 测试集 1: 工具分类 (AI写作/AI考试工坊/安全培训) # ────────────────────────────────────────────────────────────── print("\n" + "=" * 60) print("测试集 1: 工具分类 (AI写作 / AI考试工坊 / 安全培训)") print("=" * 60) # AI写作 (business_type=2, should_redirect=True) assert_intent("写一份安全检查报告", 2, True, "general", "document_writing") assert_intent("帮我起草一份会议纪要", 2, True, "general", "document_writing") assert_intent("撰写隧道施工方案", 2, True, "general", "document_writing") assert_intent("生成一份工作报告", 2, True, "general", "document_writing") assert_intent("写一个关于安全管理的通知", 2, True, "general", "document_writing") assert_intent("帮我写一篇安全培训心得", 2, True, "general", "document_writing") # AI写作 不被考试关键词误判 assert_intent("写一份考题", 3, True, "general", "exam_generation", "写+考题 → 应走考试工坊") assert_intent("帮我写一份考试试卷", 3, True, "general", "exam_generation", "写+试卷 → 应走考试工坊") # AI写作 不被培训关键词误判 assert_intent("写一份培训心得", 2, True, "general", "document_writing", "写+培训(无生成词) → 应走AI写作" if True else "") assert_intent("帮我生成一份安全培训PPT", 1, True, "general", "ppt_training", "生成+培训+ppt → 应走安全培训") # 安全培训 (business_type=1, should_redirect=True) assert_intent("帮我生成一份桥梁施工安全培训PPT", 1, True, "general", "ppt_training") assert_intent("制作安全培训课件", 1, True, "general", "ppt_training") assert_intent("给我做一个安全培训大纲", 1, True, "general", "ppt_training") # 安全培训 - 不带生成词的不应该触发 assert_intent("什么是安全培训", 0, False, "professional", "professional_qa", "仅含培训词无生成词 → 应走AI问答") # 考试工坊 (business_type=3, should_redirect=True) assert_intent("生成10道安全知识考题", 3, True, "general", "exam_generation") assert_intent("帮我出一份施工安全试卷", 3, True, "general", "exam_generation") assert_intent("我要做练习题", 3, True, "general", "exam_generation") assert_intent("给我一些测试题", 3, True, "general", "exam_generation") # ────────────────────────────────────────────────────────────── # 测试集 2: 专业领域识别 (五大场景) # ────────────────────────────────────────────────────────────── print("\n" + "=" * 60) print("测试集 2: 专业领域识别 (五大场景)") print("=" * 60) assert_intent("高速公路安全防护措施有哪些", 0, False, "professional", "professional_qa", "高速公路 → professional") assert_intent("桥梁工程施工质量控制要点", 0, False, "professional", "professional_qa", "桥梁工程 → professional") assert_intent("隧道施工通风系统如何设计", 0, False, "professional", "professional_qa", "隧道工程 → professional") assert_intent("加油站安全管理要求", 0, False, "professional", "professional_qa", "加油站 → professional") assert_intent("特种设备检验标准是什么", 0, False, "professional", "professional_qa", "特种设备 → professional") # ────────────────────────────────────────────────────────────── # 测试集 3: 专业领域识别 (十大领域) # ────────────────────────────────────────────────────────────── print("\n" + "=" * 60) print("测试集 3: 专业领域识别 (十大领域)") print("=" * 60) assert_intent("公路工程建设标准有哪些", 0, False, "professional", "professional_qa", "工程建设 → professional") assert_intent("公路工程营运管理流程", 0, False, "professional", "professional_qa", "营运 → professional") assert_intent("防汛减灾预案怎么编制", 0, False, "professional", "professional_qa", "防汛 → professional") assert_intent("森林草原防灭火措施有哪些", 0, False, "professional", "professional_qa", "防灭火 → professional") assert_intent("动火作业审批流程", 0, False, "professional", "professional_qa", "动火 → professional") assert_intent("有限空间作业安全规范", 0, False, "professional", "professional_qa", "有限空间 → professional") assert_intent("高处作业安全技术规范", 0, False, "professional", "professional_qa", "高处作业 → professional") assert_intent("施工现场临时用电要求", 0, False, "professional", "professional_qa", "临时用电 → professional") assert_intent("消防安全检查要点", 0, False, "professional", "professional_qa", "消防 → professional") assert_intent("起重吊装操作规程", 0, False, "professional", "professional_qa", "起重吊装 → professional") # ────────────────────────────────────────────────────────────── # 测试集 4: 问候/FAQ/通用聊天 # ────────────────────────────────────────────────────────────── print("\n" + "=" * 60) print("测试集 4: 问候 / FAQ / 通用聊天") print("=" * 60) assert_intent("你好", 0, False, "general", "greeting") assert_intent("您好", 0, False, "general", "greeting") assert_intent("在吗", 0, False, "general", "greeting") assert_intent("谢谢", 0, False, "general", "greeting") assert_intent("你是谁", 0, False, "general", "faq") assert_intent("你能做什么", 0, False, "general", "faq") assert_intent("怎么用", 0, False, "general", "faq") assert_intent("今天天气怎么样", 0, False, "general", "general_chat", "天气 → general_chat") assert_intent("给我讲个笑话", 0, False, "general", "general_chat", "笑话 → general_chat") assert_intent("推荐一部电影", 0, False, "general", "general_chat", "电影 → general_chat") # ────────────────────────────────────────────────────────────── # 测试集 5: 专业关键词兜底 (enhanced_intent.py 中的 fallback) # ────────────────────────────────────────────────────────────── print("\n" + "=" * 60) print("测试集 5: PROFESSIONAL_DOMAINS 枚举完整性") print("=" * 60) # 验证 PROFESSIONAL_DOMAINS 定义 sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "shudao-aichat")) try: from app.api.intent import PROFESSIONAL_DOMAINS, TOOL_CATEGORIES # 验证五大场景 scene_keys = ["HIGHWAY", "BRIDGE_ENGINEERING", "TUNNEL_ENGINEERING", "GAS_STATION", "SPECIAL_EQUIPMENT"] for sk in scene_keys: if sk in PROFESSIONAL_DOMAINS: PASS += 1 print(f" ✅ 五大场景: {sk} → {PROFESSIONAL_DOMAINS[sk]}") else: FAIL += 1 print(f" ❌ 五大场景: {sk} MISSING") # 验证十大领域 domain_keys = ["HIGHWAY_CONSTRUCTION", "HIGHWAY_OPERATION", "FLOOD_PREVENTION", "FOREST_FIRE_PREVENTION", "HOT_WORK", "CONFINED_SPACE", "WORKING_AT_HEIGHT", "TEMPORARY_ELECTRICITY", "FIRE_SAFETY", "LIFTING_OPERATION"] for dk in domain_keys: if dk in PROFESSIONAL_DOMAINS: PASS += 1 print(f" ✅ 十大领域: {dk} → {PROFESSIONAL_DOMAINS[dk]}") else: FAIL += 1 print(f" ❌ 十大领域: {dk} MISSING") # 验证补充领域 extra_keys = ["SAFETY_MANAGEMENT", "ENVIRONMENTAL_PROTECTION", "OTHER_PROFESSIONAL"] for ek in extra_keys: if ek in PROFESSIONAL_DOMAINS: PASS += 1 print(f" ✅ 补充: {ek} → {PROFESSIONAL_DOMAINS[ek]}") else: FAIL += 1 print(f" ❌ 补充: {ek} MISSING") # 验证工具分类 tool_keys = ["AI_QUESTION_ANSWERING", "AI_WRITING", "AI_EXAM_WORKSHOP"] for tk in tool_keys: if tk in TOOL_CATEGORIES: PASS += 1 print(f" ✅ 工具: {tk}") else: FAIL += 1 print(f" ❌ 工具: {tk} MISSING") # 验证枚举值总计 total_domains = len(PROFESSIONAL_DOMAINS) print(f" 📊 PROFESSIONAL_DOMAINS 总数: {total_domains} (期望 ≥ 18)") if total_domains >= 18: PASS += 1 else: FAIL += 1 print(f" ❌ 领域数量不足: {total_domains} < 18") except ImportError as e: print(f" ⚠️ 无法导入 aichat 模块: {e}") # ────────────────────────────────────────────────────────────── # 汇总 # ────────────────────────────────────────────────────────────── print("\n" + "=" * 60) print(f"测试结果: 通过={PASS}, 失败={FAIL}, 总计={PASS+FAIL}") print("=" * 60) if FAIL > 0: sys.exit(1) else: print("🎉 全部测试通过!") sys.exit(0)