test_pg_evidence_builder.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import unittest
  2. from unittest.mock import patch
  3. from examples.demand.evidence_pack_builder import build_evidence_pack
  4. def _execution():
  5. return {"id": 581, "status": "success"}
  6. def _itemset(**overrides):
  7. data = {
  8. "id": 1607313,
  9. "execution_id": 581,
  10. "mining_config_id": 2081,
  11. "mining_config_execution_id": 581,
  12. "mining_config_scope": "topic",
  13. "scope": "topic",
  14. "item_count": 1,
  15. "support": 0.1,
  16. "absolute_support": 2,
  17. "matched_post_ids": ["p1", "p2"],
  18. }
  19. data.update(overrides)
  20. return data
  21. def _item():
  22. return {
  23. "itemset_item_id": 1,
  24. "itemset_id": 1607313,
  25. "category_id": 10,
  26. "bound_category_id": 10,
  27. "category_found": True,
  28. "category_execution_id": 581,
  29. "category_name": "综合性腐败",
  30. "category_path": "/事件行为/违纪违法/综合性腐败",
  31. "category_full_path": "/事件行为/违纪违法/综合性腐败",
  32. "dimension": "实质",
  33. "point_type": "关键点",
  34. "element_name": None,
  35. }
  36. def _binding():
  37. return {
  38. "itemset_id": 1607313,
  39. "itemset_item_id": 1,
  40. "category_id": 10,
  41. "dimension": "实质",
  42. "point_type": "关键点",
  43. "element_name": None,
  44. "matched_element_count": 1,
  45. "matched_post_count": 1,
  46. "matched_post_ids": ["p1"],
  47. "sample_elements": [{"name": "综合性腐败", "category_path": "/事件行为/违纪违法/综合性腐败"}],
  48. }
  49. def _empty_binding(post_ids=None):
  50. binding = _binding()
  51. binding["matched_element_count"] = 0
  52. binding["matched_post_count"] = 0
  53. binding["matched_post_ids"] = post_ids or []
  54. binding["sample_elements"] = []
  55. return binding
  56. class PgEvidenceBuilderTest(unittest.TestCase):
  57. def _build(self, evidence_refs):
  58. return build_evidence_pack(
  59. 581,
  60. {"element_names": ["综合性腐败"], "evidence_refs": evidence_refs},
  61. trace_id="trace-test",
  62. demand_task_id=1,
  63. demand_content_id=1,
  64. )
  65. def _patch_success(self, itemsets=None):
  66. patches = [
  67. patch("examples.demand.evidence_pack_builder.query_execution_for_evidence", return_value=_execution()),
  68. patch("examples.demand.evidence_pack_builder.query_itemset_evidence", return_value=itemsets or [_itemset()]),
  69. patch("examples.demand.evidence_pack_builder.query_itemset_items_with_categories", return_value=[_item()]),
  70. patch("examples.demand.evidence_pack_builder.query_element_bindings_for_items", return_value=[_binding()]),
  71. patch("examples.demand.evidence_pack_builder.query_case_ids_by_post_ids", return_value=[]),
  72. patch("examples.demand.evidence_pack_builder.query_seed_points_for_itemsets", return_value=[]),
  73. ]
  74. for patcher in patches:
  75. patcher.start()
  76. self.addCleanup(patcher.stop)
  77. def test_topic_itemset_builds_pg_evidence_pack(self):
  78. self._patch_success()
  79. result = self._build(
  80. {
  81. "source_kind": "pattern_itemset",
  82. "source_tool": "get_itemset_detail",
  83. "itemset_ids": [1607313],
  84. "source_post_id": "p1",
  85. "seed_terms": ["LLM伪造词"],
  86. }
  87. )
  88. self.assertTrue(result["success"])
  89. evidence_pack = result["evidence_pack"]
  90. self.assertEqual(evidence_pack["pattern_source_system"], "pg_pattern_v2")
  91. self.assertEqual(evidence_pack["validation_status"], "passed")
  92. self.assertEqual(evidence_pack["source_certainty"], "db_validated")
  93. self.assertEqual(evidence_pack["matched_post_ids"], ["p1", "p2"])
  94. self.assertEqual(evidence_pack["seed_terms"], ["综合性腐败"])
  95. self.assertIn("query_seed_points", evidence_pack)
  96. self.assertIn("demand_scope", evidence_pack)
  97. def test_non_topic_scope_is_rejected(self):
  98. self._patch_success(itemsets=[_itemset(scope="topic_element")])
  99. result = self._build(
  100. {
  101. "source_kind": "pattern_itemset",
  102. "itemset_ids": [1607313],
  103. "source_post_id": "p1",
  104. }
  105. )
  106. self.assertFalse(result["success"])
  107. self.assertIn("scope=topic_element", result["reject_reason"])
  108. def test_source_post_outside_matched_posts_is_rejected(self):
  109. self._patch_success()
  110. result = self._build(
  111. {
  112. "source_kind": "pattern_itemset",
  113. "itemset_ids": [1607313],
  114. "source_post_id": "not-a-source-post",
  115. }
  116. )
  117. self.assertFalse(result["success"])
  118. self.assertIn("not in matched_post_ids", result["reject_reason"])
  119. def test_falls_back_to_db_validated_source_post_with_element_binding(self):
  120. bindings = [
  121. [_empty_binding()],
  122. [{**_binding(), "matched_post_ids": ["p2"]}],
  123. [{**_binding(), "matched_post_ids": ["p2"]}],
  124. ]
  125. with (
  126. patch("examples.demand.evidence_pack_builder.query_execution_for_evidence", return_value=_execution()),
  127. patch("examples.demand.evidence_pack_builder.query_itemset_evidence", return_value=[_itemset()]),
  128. patch("examples.demand.evidence_pack_builder.query_itemset_items_with_categories", return_value=[_item()]),
  129. patch("examples.demand.evidence_pack_builder.query_element_bindings_for_items", side_effect=bindings),
  130. patch("examples.demand.evidence_pack_builder.query_case_ids_by_post_ids", return_value=[]),
  131. patch("examples.demand.evidence_pack_builder.query_seed_points_for_itemsets", return_value=[]),
  132. ):
  133. result = self._build(
  134. {
  135. "source_kind": "pattern_itemset",
  136. "itemset_ids": [1607313],
  137. "source_post_id": "p1",
  138. }
  139. )
  140. self.assertTrue(result["success"])
  141. self.assertEqual(result["evidence_pack"]["source_post_id"], "p2")
  142. def test_multiple_itemsets_are_rejected(self):
  143. self._patch_success()
  144. result = self._build(
  145. {
  146. "source_kind": "pattern_itemset",
  147. "itemset_ids": [1607313, 1607314],
  148. "source_post_id": "p1",
  149. }
  150. )
  151. self.assertFalse(result["success"])
  152. self.assertIn("exactly one itemset_id", result["reject_reason"])
  153. if __name__ == "__main__":
  154. unittest.main()