conftest.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. from __future__ import annotations
  2. from copy import deepcopy
  3. import pytest
  4. @pytest.fixture
  5. def current_bundle():
  6. bundle = {
  7. "record": {
  8. "id": 88001,
  9. "status": "running",
  10. "script_direction": "解释一家工厂怎样通过柔性排产减少浪费。",
  11. "summary": None,
  12. "error_message": None,
  13. "agent_config": {"model_name": "test-model"},
  14. "cost_usd": 1.2,
  15. "start_time": "2026-07-13T10:00:00",
  16. "end_time": None,
  17. },
  18. "rounds": [
  19. {
  20. "id": 1,
  21. "round_index": 1,
  22. "goal": "确定文章结构并补齐可靠行业事实",
  23. "multipath_plan": [
  24. {"path_index": 1, "target": "文章结构"},
  25. {"path_index": 2, "target": "行业事实"},
  26. {"path_index": 3, "target": "结尾表达"},
  27. ],
  28. "race_or_divide": "分工",
  29. "plan_note": "内容方案和领域信息方案并行推进。",
  30. "status": "done",
  31. },
  32. {
  33. "id": 2,
  34. "round_index": 2,
  35. "goal": "补齐正文细节",
  36. "multipath_plan": [{"path_index": 1, "target": "正文"}],
  37. "race_or_divide": "赛马",
  38. "plan_note": None,
  39. "status": "open",
  40. },
  41. ],
  42. "branches": [
  43. _branch(1, 1, "内容", "形成三段式文章结构", "merged"),
  44. _branch(1, 2, "领域信息", "核实柔性排产数据", "discarded"),
  45. _branch(1, 3, "内容", "形成行动建议结尾", "parked"),
  46. _branch(2, 4, "内容", "补齐正文案例", "open"),
  47. ],
  48. "dataDecisions": [
  49. _data_decision(11, 1, 1, "采用案例中的三段结构", "结构能解释因果关系"),
  50. _data_decision(12, 1, 2, "采用两条交叉印证的数据", "两类来源结论一致"),
  51. _data_decision(13, 1, 3, "采用行动建议写法", None),
  52. ],
  53. "multipathDecisions": [
  54. {
  55. "id": 21,
  56. "script_build_id": 88001,
  57. "round_index": 1,
  58. "branch_ids": [1, 2],
  59. "decision": "采用方案 1;方案 2 的领域事实保留,但内容分支不采用。",
  60. "reasoning": "结构可直接进入主脚本,领域事实独立沉淀。",
  61. "created_at": "2026-07-13T10:03:00",
  62. },
  63. {
  64. "id": 22,
  65. "script_build_id": 88001,
  66. "round_index": 1,
  67. "branch_ids": [3],
  68. "decision": "方案 3 暂存。",
  69. "reasoning": "方向可用,但与正文衔接仍需调整。",
  70. "created_at": "2026-07-13T10:04:00",
  71. },
  72. ],
  73. "domainInfo": [
  74. {
  75. "id": 31,
  76. "script_build_id": 88001,
  77. "round_index": 1,
  78. "branch_id": 2,
  79. "content": "柔性排产可降低小批量切换损耗。",
  80. "source": [{"type": "report", "id": "R-1", "loc": "p.4"}],
  81. "note": "两份报告交叉印证",
  82. "created_at": "2026-07-13T10:02:30",
  83. }
  84. ],
  85. "events": [
  86. {
  87. "id": 39,
  88. "event_seq": 6,
  89. "event_type": "agent_invoke",
  90. "event_name": "script_multipath_evaluator",
  91. "round_index": 1,
  92. "status": "ok",
  93. "inputData": {"task": "比较 branch_id=1, branch_id=2"},
  94. "agentOutputData": {"summary": "### 分支评估 branch_id=1\n**该支结论**:通过\n**目标推进**:结构清晰。\n\n### 分支评估 branch_id=2\n**该支结论**:部分通过\n**目标推进**:事实可靠。\n\n### 对比与建议\n**采纳建议**:优先采用 branch_id=1。"},
  95. "started_at": "2026-07-13T10:02:40",
  96. "ended_at": "2026-07-13T10:02:50",
  97. },
  98. {
  99. "id": 40,
  100. "event_seq": 7,
  101. "event_type": "agent_invoke",
  102. "event_name": "script_multipath_evaluator",
  103. "round_index": 1,
  104. "status": "ok",
  105. "inputData": {"task": "评审 branch_id=3"},
  106. "agentOutputData": {"summary": "### 分支评估 branch_id=3\n**该支结论**:通过\n**目标推进**:结尾方向可用。\n\n### 对比与建议\n**采纳建议**:可以暂存后调整。"},
  107. "started_at": "2026-07-13T10:03:30",
  108. "ended_at": "2026-07-13T10:03:40",
  109. },
  110. {
  111. "id": 41,
  112. "event_seq": 8,
  113. "event_type": "agent_invoke",
  114. "event_name": "script_evaluator",
  115. "round_index": 1,
  116. "status": "ok",
  117. "title": "派发 script_evaluator (ok)",
  118. "input_preview": "请评估第1轮",
  119. "output_preview": "### 整体结论:部分通过\n仍需完善正文细节。",
  120. "agentOutputData": {"summary": "### 整体结论:部分通过\n仍需完善正文细节。"},
  121. "started_at": "2026-07-13T10:05:00",
  122. "ended_at": "2026-07-13T10:05:10",
  123. },
  124. {
  125. "id": 42,
  126. "event_seq": 9,
  127. "event_type": "agent_invoke",
  128. "event_name": "retrieve_data_knowledge",
  129. "status": "ok",
  130. "title": "无法归属的取数 Agent",
  131. "started_at": "2026-07-13T10:06:00",
  132. "ended_at": "2026-07-13T10:06:10",
  133. },
  134. {
  135. "id": 50,
  136. "event_seq": 10,
  137. "event_type": "agent_invoke",
  138. "event_name": "script_implementer",
  139. "agent_role": "script_implementer",
  140. "round_index": 1,
  141. "branch_id": 1,
  142. "status": "ok",
  143. "started_at": "2026-07-13T10:00:00",
  144. "ended_at": "2026-07-13T10:02:00",
  145. },
  146. {
  147. "id": 51,
  148. "event_seq": 11,
  149. "event_type": "tool_call",
  150. "event_name": "get_script_snapshot",
  151. "agent_role": "script_implementer",
  152. "scope_event_id": 50,
  153. "round_index": 1,
  154. "branch_id": 1,
  155. "status": "ok",
  156. "inputData": {},
  157. "output_preview": "{\"count\": 1}",
  158. "started_at": "2026-07-13T10:00:05",
  159. "ended_at": "2026-07-13T10:00:06",
  160. },
  161. {
  162. "id": 52,
  163. "event_seq": 12,
  164. "event_type": "agent_invoke",
  165. "event_name": "retrieve_data_decode_case",
  166. "parent_event_id": 50,
  167. "scope_event_id": 50,
  168. "round_index": 1,
  169. "branch_id": 1,
  170. "status": "ok",
  171. "inputData": {"task": "查找可说明因果结构的解构 Case"},
  172. "agentOutputData": {"summary": "初筛出两个可用的三段式案例。"},
  173. "started_at": "2026-07-13T10:00:10",
  174. "ended_at": "2026-07-13T10:00:40",
  175. },
  176. {
  177. "id": 53,
  178. "event_seq": 13,
  179. "event_type": "tool_call",
  180. "event_name": "search_script_decode_case",
  181. "scope_event_id": 52,
  182. "parent_event_id": 52,
  183. "round_index": 1,
  184. "branch_id": 1,
  185. "status": "ok",
  186. "inputData": {"keyword": "因果结构"},
  187. "output_preview": "{\"count\": 2}",
  188. "started_at": "2026-07-13T10:00:15",
  189. "ended_at": "2026-07-13T10:00:20",
  190. },
  191. {
  192. "id": 54,
  193. "event_seq": 14,
  194. "event_type": "tool_call",
  195. "event_name": "search_script_decode_case",
  196. "scope_event_id": 52,
  197. "parent_event_id": 52,
  198. "round_index": 1,
  199. "branch_id": 1,
  200. "status": "ok",
  201. "inputData": {"keyword": "柔性排产"},
  202. "output_preview": "{\"count\": 0}",
  203. "started_at": "2026-07-13T10:00:25",
  204. "ended_at": "2026-07-13T10:00:30",
  205. },
  206. ],
  207. "ignoredLegacyDataDecisionCount": 2,
  208. "currentArtifact": {
  209. "paragraphs": [{"id": 1}, {"id": 2}, {"id": 3}],
  210. "elements": [{"id": 10}, {"id": 11}],
  211. "paragraphElements": [{"id": 100, "paragraph_id": 1, "element_id": 10}],
  212. "sourceOrigin": "database",
  213. },
  214. }
  215. return deepcopy(bundle)
  216. def _branch(round_index: int, branch_id: int, path_type: str, task: str, status: str):
  217. snapshot = {
  218. "paragraphs": [{"id": branch_id * 100, "name": task}],
  219. "elements": [{"id": branch_id * 1000}],
  220. "paragraphElements": [],
  221. }
  222. return {
  223. "id": branch_id,
  224. "script_build_id": 88001,
  225. "branch_id": branch_id,
  226. "round_index": round_index,
  227. "path_type": path_type,
  228. "target": task,
  229. "impl_task": task,
  230. "self_assessment": f"已经完成:{task}",
  231. "status": status,
  232. "decision_reasoning": f"方案 {branch_id} 的当前处理理由",
  233. "candidate_snapshot": {
  234. "snapshot": snapshot if path_type == "内容" else None,
  235. "snapshotKind": "saved-at-disposition" if status in {"merged", "discarded"} else "current-overlay",
  236. "historicalAccuracy": "exact" if status in {"merged", "discarded"} else "unknown",
  237. "currentProjectionAccuracy": "exact" if status in {"open", "parked"} else "not-applicable",
  238. "note": "测试候选版本",
  239. },
  240. }
  241. def _data_decision(record_id: int, round_index: int, branch_id: int, decision: str, reasoning: str | None):
  242. return {
  243. "id": record_id,
  244. "script_build_id": 88001,
  245. "round_index": round_index,
  246. "branch_id": branch_id,
  247. "sources": [{"data_type": "领域信息", "data_id": f"S-{record_id}", "data_content": "已核实材料"}],
  248. "decision": decision,
  249. "reasoning": reasoning,
  250. "created_at": "2026-07-13T10:02:00",
  251. }