walk_strategy.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. """终端边映射与血缘模板(V3-M4 后被 walk_engine._terminal_stage 消费)。
  2. 原 run(plan_walk 节点)的编排已并入 walk_engine 终端阶段;本模块只留
  3. 决策→终端动作映射与终端边 wa_id(decision_id 后缀,与扩展边的语义后缀是两套约定,冻结)。
  4. """
  5. from __future__ import annotations
  6. import hashlib
  7. from typing import Any
  8. from content_agent.constants import RUNTIME_RECORD_SCHEMA_VERSION
  9. from content_agent.record_payload import with_raw_payload
  10. def _action_for_decision(decision_action: str) -> dict[str, str]:
  11. if decision_action == "ADD_TO_CONTENT_POOL":
  12. return {
  13. "edge_id": "decision_to_asset",
  14. "edge_type": "terminal",
  15. "walk_action": "commit_asset",
  16. "walk_status": "success",
  17. "budget_tier": "normal",
  18. }
  19. if decision_action == "KEEP_CONTENT_FOR_REVIEW":
  20. return {
  21. "edge_id": "budget_downgrade",
  22. "edge_type": "budget",
  23. "walk_action": "downgrade_budget",
  24. "walk_status": "success",
  25. "budget_tier": "low_budget",
  26. }
  27. return {
  28. "edge_id": "path_stop",
  29. "edge_type": "terminal",
  30. "walk_action": "stop_path",
  31. "walk_status": "skipped",
  32. "budget_tier": "stop",
  33. }
  34. def _walk_action_row(
  35. decision: dict[str, Any],
  36. item: dict[str, Any],
  37. decision_action: dict[str, str],
  38. walk_action_id: str,
  39. created_at: str,
  40. binding: dict[str, Any],
  41. execution: dict[str, Any],
  42. ) -> dict[str, Any]:
  43. row = with_raw_payload(
  44. {
  45. "record_schema_version": RUNTIME_RECORD_SCHEMA_VERSION,
  46. "run_id": decision["run_id"],
  47. "policy_run_id": decision["policy_run_id"],
  48. "walk_action_id": walk_action_id,
  49. "edge_id": decision_action["edge_id"],
  50. "edge_type": decision_action["edge_type"],
  51. "from_node_type": "RuleDecision",
  52. "from_node_id": decision["decision_id"],
  53. "to_node_type": "Content",
  54. "to_node_id": item["platform_content_id"],
  55. "walk_action": decision_action["walk_action"],
  56. "walk_status": decision_action["walk_status"],
  57. "budget_tier": decision_action["budget_tier"],
  58. "depth": 0,
  59. "page_cursor": item.get("page_cursor"),
  60. "next_cursor": item.get("next_cursor"),
  61. "decision_id": decision["decision_id"],
  62. "rule_pack_id": binding.get("rule_pack_id") or decision["rule_pack_id"],
  63. "rule_pack_version": binding.get("rule_pack_version") or decision["rule_pack_version"],
  64. "reason_code": decision["decision_reason_code"],
  65. "content_effect_status": decision["search_query_effect_status"],
  66. "decision_target_type": decision.get("decision_target_type"),
  67. "decision_target_id": decision.get("decision_target_id"),
  68. "created_at": created_at,
  69. }
  70. )
  71. row["raw_payload"]["rule_pack_binding"] = binding
  72. row["raw_payload"]["rule_pack_execution"] = execution
  73. return row
  74. def _walk_action_id(
  75. run_id: str,
  76. policy_run_id: str,
  77. edge_id: str,
  78. target_id: str,
  79. decision_id: str,
  80. ) -> str:
  81. raw = f"{run_id}:{policy_run_id}:{edge_id}:{target_id}:{decision_id}"
  82. return f"wa_{hashlib.sha1(raw.encode('utf-8')).hexdigest()[:16]}"