test_evaluation_report_parser_v8.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. from app.evaluation_report_parser import EvaluationReportParser
  2. def test_multipath_report_becomes_structured_business_data():
  3. report = """## 评估报告 script_build_id=436
  4. ### 分支评估 branch_id=3
  5. **该支结论**:通过
  6. **目标推进**:完成核心教学段落。
  7. ### 分支评估 branch_id=4
  8. **该支结论**:部分通过
  9. **未通过项**:工具属性说明还需补充。
  10. ### 对比与建议
  11. **采纳建议**:组合方案 3 与方案 4。
  12. """
  13. parsed = EvaluationReportParser().parse(report, kind="multipath")
  14. assert parsed["subjects"] == ["方案 3", "方案 4"]
  15. assert [item["conclusion"] for item in parsed["itemConclusions"]] == ["通过", "部分通过"]
  16. assert parsed["itemConclusions"][0]["achievements"] == ["完成核心教学段落。"]
  17. assert parsed["recommendation"] == "采纳建议:组合方案 3 与方案 4。"
  18. assert "script_build_id" not in str(parsed)
  19. assert "branch_id" not in str(parsed)
  20. def test_overall_report_extracts_criteria_achievements_problems_and_next_goal():
  21. report = """### 评审标准
  22. - 内容完整性
  23. - 证据可靠性
  24. ### 已达成
  25. - 三个核心段落已完成。
  26. ### 问题详情
  27. - **paragraph_id=9**:收尾段落缺失。
  28. - 【中】数据说明仍需补充。
  29. ### 整体结论:部分通过
  30. ### 下一步引领目标
  31. 补齐收尾并形成闭环。
  32. """
  33. parsed = EvaluationReportParser().parse(report, kind="overall")
  34. assert parsed["criteria"] == ["内容完整性", "证据可靠性"]
  35. assert parsed["achievements"] == ["三个核心段落已完成。"]
  36. assert [item["summary"] for item in parsed["problems"]] == ["收尾段落缺失。", "【中】数据说明仍需补充。"]
  37. assert parsed["problems"][1]["severity"] == "中"
  38. assert parsed["conclusion"] == "部分通过"
  39. assert parsed["nextGoal"] == "补齐收尾并形成闭环。"
  40. def test_markdown_table_is_parsed_without_exposing_internal_dimension_codes():
  41. report = """### 维度评估
  42. | 维度 | 结论 | 已达成 | 问题 |
  43. | --- | --- | --- | --- |
  44. | D1 维度体系一致性 | 部分通过 | 主线统一 | 段 3 命名重复 |
  45. | P1 元素完整性 | 通过 | 元素齐全 | |
  46. """
  47. parsed = EvaluationReportParser().parse(report, kind="overall")
  48. assert parsed["criteria"] == ["维度体系一致性", "元素完整性"]
  49. assert [item["subject"] for item in parsed["itemConclusions"]] == [
  50. "维度体系一致性",
  51. "元素完整性",
  52. ]
  53. assert parsed["problems"][0]["summary"] == "段 3 命名重复"
  54. assert "D1" not in str(parsed)
  55. assert "P1" not in str(parsed)
  56. def test_json_fence_and_wrong_build_id_never_become_business_content_or_association():
  57. report = """## 评估报告 script_build_id=1393
  58. ```json
  59. {"script_build_id": 434, "branch_id": 99, "dimension_pass": false}
  60. ```
  61. ### 整体结论:通过
  62. ### 评审建议
  63. 保留当前主线。
  64. """
  65. parsed = EvaluationReportParser().parse(report, kind="overall")
  66. assert parsed["conclusion"] == "通过"
  67. assert parsed["recommendation"] == "保留当前主线。"
  68. serialized = str(parsed)
  69. assert "1393" not in serialized
  70. assert "434" not in serialized
  71. assert "99" not in serialized
  72. assert "dimension_pass" not in serialized
  73. def test_missing_headings_and_broken_markdown_still_extract_explicit_labels():
  74. report = """**整体结论**:需要重试
  75. 遗留问题:开头和结尾未呼应
  76. **下一轮目标**:重写收尾
  77. *** 未闭合的 Markdown
  78. """
  79. parsed = EvaluationReportParser().parse(report, kind="overall")
  80. assert parsed["conclusion"] == "需要重试"
  81. assert parsed["problems"] == [{"summary": "开头和结尾未呼应"}]
  82. assert parsed["nextGoal"] == "重写收尾"
  83. assert parsed["notices"] == []
  84. def test_business_numbers_are_not_removed_by_identifier_sanitizing():
  85. report = """### 已达成
  86. - 领域信息 31/32 已确认。
  87. - 完成 5 个段落、12 个元素和 4:3 画面说明。
  88. ### 整体结论:通过
  89. """
  90. parsed = EvaluationReportParser().parse(report)
  91. assert parsed["achievements"] == [
  92. "领域信息 31/32 已确认。",
  93. "完成 5 个段落、12 个元素和 4:3 画面说明。",
  94. ]
  95. def test_empty_or_unparseable_report_returns_stable_empty_shape():
  96. parsed = EvaluationReportParser().parse("```json\n{broken}\n```", kind="overall")
  97. assert parsed == {
  98. "parserVersion": 1,
  99. "kind": "overall",
  100. "subjects": [],
  101. "criteria": [],
  102. "itemConclusions": [],
  103. "achievements": [],
  104. "problems": [],
  105. "conclusion": None,
  106. "recommendation": None,
  107. "nextGoal": None,
  108. "notices": ["unparsed-report"],
  109. }
  110. def test_no_problem_markers_are_not_presented_as_warnings_and_suffix_heading_splits():
  111. parsed = EvaluationReportParser().parse(
  112. """
  113. ### 分支评估 branch_id=5
  114. **该支结论**:通过
  115. **目标推进**:已完成收尾。
  116. **未通过项**:无显著质量问题。
  117. **领域评估维度**(已激活并判定):
  118. - 烹饪常识:通过
  119. """,
  120. kind="multipath",
  121. )
  122. assert parsed["problems"] == []
  123. assert parsed["itemConclusions"][0]["problems"] == []
  124. assert "烹饪常识:通过" in parsed["criteria"]
  125. def test_positive_sentence_after_no_problem_marker_is_not_a_problem():
  126. parsed = EvaluationReportParser().parse(
  127. "## 问题\n无显著质量问题。脚本已达到发布标准。\n\n## 整体结论\n通过",
  128. kind="overall",
  129. )
  130. assert parsed["problems"] == []
  131. def test_multipath_report_keeps_branch_groups_and_does_not_treat_not_passed_as_achievement():
  132. report = """### 分支评估 branch_id=1
  133. **该支结论**:部分通过
  134. **目标推进**:
  135. - 领域信息库新增 5 条事实(id 54-58)。
  136. **未通过/存疑项**:
  137. - 元素创建尚未完整落地。
  138. **有据扎实度**:来源可指位。
  139. ### 分支评估 branch_id=2
  140. **该支结论**:部分通过
  141. **目标推进**:
  142. - 已搭建五段骨架。
  143. **未通过/部分通过项**:
  144. - 数量红线违规。
  145. - function_elements 全部为空。
  146. ### 对比与建议
  147. | 维度 | branch1 | branch2 | 差异依据 |
  148. | --- | --- | --- | --- |
  149. | 与本轮目标的契合度 | 高 | 高 | 各自完成主任务 |
  150. | 结构完备性 | 不适用 | 部分通过 | 仅方案二涉及 |
  151. """
  152. parsed = EvaluationReportParser().parse(report, kind="multipath")
  153. assert parsed["branchEvaluations"][0] == {
  154. "subject": "方案 1",
  155. "conclusion": "部分通过",
  156. "achievements": ["领域信息库新增 5 条事实(id 54-58)。"],
  157. "problems": ["元素创建尚未完整落地。"],
  158. "evidence": "来源可指位。",
  159. }
  160. assert parsed["branchEvaluations"][1]["achievements"] == ["已搭建五段骨架。"]
  161. assert parsed["branchEvaluations"][1]["problems"] == ["数量红线违规。", "function_elements 全部为空。"]
  162. assert "数量红线违规。" not in parsed["achievements"]
  163. assert parsed["comparisonRows"][0] == {
  164. "criterion": "与本轮目标的契合度",
  165. "candidates": [
  166. {"subject": "方案 1", "value": "高"},
  167. {"subject": "方案 2", "value": "高"},
  168. ],
  169. "basis": "各自完成主任务",
  170. }