test_template_heading_levels.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import copy
  2. import unittest
  3. from models import BidOutline, Chapter, SkeletonParagraph, TenderAnalysis
  4. from step3_outlining.outline_generator import _OutlineGenerator
  5. from step3_outlining.outline_report import build_outline_report, validate_outline_gate
  6. from step3_outlining.scoring_structure import apply_scoring_structure
  7. from scripts.tests.test_scoring_structure_and_business_forms import criterion, FakeMappingLlm
  8. class TemplateHeadingLevelTests(unittest.TestCase):
  9. def setUp(self):
  10. self.parent = Chapter(id='4.13', title='十三、应急预案和紧急事件处置措施',
  11. level=2, from_template=True)
  12. self.root = Chapter(id='4', title='基本服务方案', level=1,
  13. template_chapter_id='4', children=[self.parent])
  14. self.skeletons = [SkeletonParagraph(para_idx=0, text=self.parent.title,
  15. similarity=1.0, inferred_level=1, is_heading=True)]
  16. def test_reference_h1_cannot_override_template_h2_or_scoring_children(self):
  17. template = BidOutline(project_name='测试', chapters=[copy.deepcopy(self.root)])
  18. _OutlineGenerator.__new__(_OutlineGenerator)._apply_heading_levels([self.root], self.skeletons)
  19. self.assertEqual(self.parent.level, 2, '参考骨架H1不得覆盖模板H2')
  20. outline = BidOutline(project_name='测试', chapters=[self.root])
  21. scoring = criterion('SC-01', '应急预案和紧急事件处置措施', '防汛应急预案')
  22. apply_scoring_structure(outline, [scoring], llm=FakeMappingLlm())
  23. child = self.parent.children[-1]
  24. self.assertEqual(child.level, 3)
  25. self.assertTrue(child.title.startswith('(一)'))
  26. report, _ = build_outline_report(template, outline, TenderAnalysis(project_name='测试', scoring_criteria=[scoring]))
  27. self.assertIn('H2 `4.13`', report)
  28. self.assertIn(f'H3 `{child.id}`', report)
  29. def test_gate_rejects_nested_h1_and_wrong_new_child_level(self):
  30. template = BidOutline(project_name='测试', chapters=[copy.deepcopy(self.root)])
  31. self.parent.level = 1
  32. self.parent.children = [Chapter(id='4.13.1', title='错误子项', level=2)]
  33. errors = validate_outline_gate(template, BidOutline(project_name='测试', chapters=[self.root]), TenderAnalysis(project_name='测试'))
  34. self.assertTrue(any('4.13 H1,应为 H2' in error for error in errors))
  35. self.assertTrue(any('4.13.1 H2,应为 H3' in error for error in errors))
  36. def test_non_template_reference_inference_cannot_break_parent_tree(self):
  37. self.parent.from_template = False
  38. _OutlineGenerator.__new__(_OutlineGenerator)._apply_heading_levels([self.root], self.skeletons)
  39. self.assertEqual(self.parent.level, 2)