test_keyword_intent.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. """
  2. 测试 _keyword_based_intent 核心意图识别逻辑
  3. 不依赖任何外部服务,纯本地关键词匹配测试
  4. """
  5. import sys
  6. import os
  7. from pathlib import Path
  8. # 添加项目路径
  9. sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
  10. from services.qwen_service import QwenService
  11. service = QwenService()
  12. PASS = 0
  13. FAIL = 0
  14. def assert_intent(message, expected_business_type, expected_should_redirect,
  15. expected_domain_type, expected_intent_type, label=""):
  16. global PASS, FAIL
  17. bt, sr, dt, it = service._keyword_based_intent(message)
  18. ok = (bt == expected_business_type and
  19. sr == expected_should_redirect and
  20. dt == expected_domain_type and
  21. it == expected_intent_type)
  22. if ok:
  23. PASS += 1
  24. print(f" ✅ {label or message[:40]}")
  25. else:
  26. FAIL += 1
  27. print(f" ❌ {label or message[:40]}")
  28. print(f" expected: bt={expected_business_type} sr={expected_should_redirect} dt={expected_domain_type} it={expected_intent_type}")
  29. print(f" got: bt={bt} sr={sr} dt={dt} it={it}")
  30. # ──────────────────────────────────────────────────────────────
  31. # 测试集 1: 工具分类 (AI写作/AI考试工坊/安全培训)
  32. # ──────────────────────────────────────────────────────────────
  33. print("\n" + "=" * 60)
  34. print("测试集 1: 工具分类 (AI写作 / AI考试工坊 / 安全培训)")
  35. print("=" * 60)
  36. # AI写作 (business_type=2, should_redirect=True)
  37. assert_intent("写一份安全检查报告", 2, True, "general", "document_writing")
  38. assert_intent("帮我起草一份会议纪要", 2, True, "general", "document_writing")
  39. assert_intent("撰写隧道施工方案", 2, True, "general", "document_writing")
  40. assert_intent("生成一份工作报告", 2, True, "general", "document_writing")
  41. assert_intent("写一个关于安全管理的通知", 2, True, "general", "document_writing")
  42. assert_intent("帮我写一篇安全培训心得", 2, True, "general", "document_writing")
  43. # AI写作 不被考试关键词误判
  44. assert_intent("写一份考题", 3, True, "general", "exam_generation",
  45. "写+考题 → 应走考试工坊")
  46. assert_intent("帮我写一份考试试卷", 3, True, "general", "exam_generation",
  47. "写+试卷 → 应走考试工坊")
  48. # AI写作 不被培训关键词误判
  49. assert_intent("写一份培训心得", 2, True, "general", "document_writing",
  50. "写+培训(无生成词) → 应走AI写作" if True else "")
  51. assert_intent("帮我生成一份安全培训PPT", 1, True, "general", "ppt_training",
  52. "生成+培训+ppt → 应走安全培训")
  53. # 安全培训 (business_type=1, should_redirect=True)
  54. assert_intent("帮我生成一份桥梁施工安全培训PPT", 1, True, "general", "ppt_training")
  55. assert_intent("制作安全培训课件", 1, True, "general", "ppt_training")
  56. assert_intent("给我做一个安全培训大纲", 1, True, "general", "ppt_training")
  57. # 安全培训 - 不带生成词的不应该触发
  58. assert_intent("什么是安全培训", 0, False, "professional", "professional_qa",
  59. "仅含培训词无生成词 → 应走AI问答")
  60. # 考试工坊 (business_type=3, should_redirect=True)
  61. assert_intent("生成10道安全知识考题", 3, True, "general", "exam_generation")
  62. assert_intent("帮我出一份施工安全试卷", 3, True, "general", "exam_generation")
  63. assert_intent("我要做练习题", 3, True, "general", "exam_generation")
  64. assert_intent("给我一些测试题", 3, True, "general", "exam_generation")
  65. # ──────────────────────────────────────────────────────────────
  66. # 测试集 2: 专业领域识别 (五大场景)
  67. # ──────────────────────────────────────────────────────────────
  68. print("\n" + "=" * 60)
  69. print("测试集 2: 专业领域识别 (五大场景)")
  70. print("=" * 60)
  71. assert_intent("高速公路安全防护措施有哪些", 0, False, "professional", "professional_qa",
  72. "高速公路 → professional")
  73. assert_intent("桥梁工程施工质量控制要点", 0, False, "professional", "professional_qa",
  74. "桥梁工程 → professional")
  75. assert_intent("隧道施工通风系统如何设计", 0, False, "professional", "professional_qa",
  76. "隧道工程 → professional")
  77. assert_intent("加油站安全管理要求", 0, False, "professional", "professional_qa",
  78. "加油站 → professional")
  79. assert_intent("特种设备检验标准是什么", 0, False, "professional", "professional_qa",
  80. "特种设备 → professional")
  81. # ──────────────────────────────────────────────────────────────
  82. # 测试集 3: 专业领域识别 (十大领域)
  83. # ──────────────────────────────────────────────────────────────
  84. print("\n" + "=" * 60)
  85. print("测试集 3: 专业领域识别 (十大领域)")
  86. print("=" * 60)
  87. assert_intent("公路工程建设标准有哪些", 0, False, "professional", "professional_qa",
  88. "工程建设 → professional")
  89. assert_intent("公路工程营运管理流程", 0, False, "professional", "professional_qa",
  90. "营运 → professional")
  91. assert_intent("防汛减灾预案怎么编制", 0, False, "professional", "professional_qa",
  92. "防汛 → professional")
  93. assert_intent("森林草原防灭火措施有哪些", 0, False, "professional", "professional_qa",
  94. "防灭火 → professional")
  95. assert_intent("动火作业审批流程", 0, False, "professional", "professional_qa",
  96. "动火 → professional")
  97. assert_intent("有限空间作业安全规范", 0, False, "professional", "professional_qa",
  98. "有限空间 → professional")
  99. assert_intent("高处作业安全技术规范", 0, False, "professional", "professional_qa",
  100. "高处作业 → professional")
  101. assert_intent("施工现场临时用电要求", 0, False, "professional", "professional_qa",
  102. "临时用电 → professional")
  103. assert_intent("消防安全检查要点", 0, False, "professional", "professional_qa",
  104. "消防 → professional")
  105. assert_intent("起重吊装操作规程", 0, False, "professional", "professional_qa",
  106. "起重吊装 → professional")
  107. # ──────────────────────────────────────────────────────────────
  108. # 测试集 4: 问候/FAQ/通用聊天
  109. # ──────────────────────────────────────────────────────────────
  110. print("\n" + "=" * 60)
  111. print("测试集 4: 问候 / FAQ / 通用聊天")
  112. print("=" * 60)
  113. assert_intent("你好", 0, False, "general", "greeting")
  114. assert_intent("您好", 0, False, "general", "greeting")
  115. assert_intent("在吗", 0, False, "general", "greeting")
  116. assert_intent("谢谢", 0, False, "general", "greeting")
  117. assert_intent("你是谁", 0, False, "general", "faq")
  118. assert_intent("你能做什么", 0, False, "general", "faq")
  119. assert_intent("怎么用", 0, False, "general", "faq")
  120. assert_intent("今天天气怎么样", 0, False, "general", "general_chat",
  121. "天气 → general_chat")
  122. assert_intent("给我讲个笑话", 0, False, "general", "general_chat",
  123. "笑话 → general_chat")
  124. assert_intent("推荐一部电影", 0, False, "general", "general_chat",
  125. "电影 → general_chat")
  126. # ──────────────────────────────────────────────────────────────
  127. # 测试集 5: 专业关键词兜底 (enhanced_intent.py 中的 fallback)
  128. # ──────────────────────────────────────────────────────────────
  129. print("\n" + "=" * 60)
  130. print("测试集 5: PROFESSIONAL_DOMAINS 枚举完整性")
  131. print("=" * 60)
  132. # 验证 PROFESSIONAL_DOMAINS 定义
  133. sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "shudao-aichat"))
  134. try:
  135. from app.api.intent import PROFESSIONAL_DOMAINS, TOOL_CATEGORIES
  136. # 验证五大场景
  137. scene_keys = ["HIGHWAY", "BRIDGE_ENGINEERING", "TUNNEL_ENGINEERING",
  138. "GAS_STATION", "SPECIAL_EQUIPMENT"]
  139. for sk in scene_keys:
  140. if sk in PROFESSIONAL_DOMAINS:
  141. PASS += 1
  142. print(f" ✅ 五大场景: {sk} → {PROFESSIONAL_DOMAINS[sk]}")
  143. else:
  144. FAIL += 1
  145. print(f" ❌ 五大场景: {sk} MISSING")
  146. # 验证十大领域
  147. domain_keys = ["HIGHWAY_CONSTRUCTION", "HIGHWAY_OPERATION",
  148. "FLOOD_PREVENTION", "FOREST_FIRE_PREVENTION",
  149. "HOT_WORK", "CONFINED_SPACE", "WORKING_AT_HEIGHT",
  150. "TEMPORARY_ELECTRICITY", "FIRE_SAFETY", "LIFTING_OPERATION"]
  151. for dk in domain_keys:
  152. if dk in PROFESSIONAL_DOMAINS:
  153. PASS += 1
  154. print(f" ✅ 十大领域: {dk} → {PROFESSIONAL_DOMAINS[dk]}")
  155. else:
  156. FAIL += 1
  157. print(f" ❌ 十大领域: {dk} MISSING")
  158. # 验证补充领域
  159. extra_keys = ["SAFETY_MANAGEMENT", "ENVIRONMENTAL_PROTECTION", "OTHER_PROFESSIONAL"]
  160. for ek in extra_keys:
  161. if ek in PROFESSIONAL_DOMAINS:
  162. PASS += 1
  163. print(f" ✅ 补充: {ek} → {PROFESSIONAL_DOMAINS[ek]}")
  164. else:
  165. FAIL += 1
  166. print(f" ❌ 补充: {ek} MISSING")
  167. # 验证工具分类
  168. tool_keys = ["AI_QUESTION_ANSWERING", "AI_WRITING", "AI_EXAM_WORKSHOP"]
  169. for tk in tool_keys:
  170. if tk in TOOL_CATEGORIES:
  171. PASS += 1
  172. print(f" ✅ 工具: {tk}")
  173. else:
  174. FAIL += 1
  175. print(f" ❌ 工具: {tk} MISSING")
  176. # 验证枚举值总计
  177. total_domains = len(PROFESSIONAL_DOMAINS)
  178. print(f" 📊 PROFESSIONAL_DOMAINS 总数: {total_domains} (期望 ≥ 18)")
  179. if total_domains >= 18:
  180. PASS += 1
  181. else:
  182. FAIL += 1
  183. print(f" ❌ 领域数量不足: {total_domains} < 18")
  184. except ImportError as e:
  185. print(f" ⚠️ 无法导入 aichat 模块: {e}")
  186. # ──────────────────────────────────────────────────────────────
  187. # 汇总
  188. # ──────────────────────────────────────────────────────────────
  189. print("\n" + "=" * 60)
  190. print(f"测试结果: 通过={PASS}, 失败={FAIL}, 总计={PASS+FAIL}")
  191. print("=" * 60)
  192. if FAIL > 0:
  193. sys.exit(1)
  194. else:
  195. print("🎉 全部测试通过!")
  196. sys.exit(0)