walk_strategy.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. if decision_action == "TECHNICAL_RETRY_REQUIRED":
  28. return {
  29. "edge_id": "path_stop",
  30. "edge_type": "terminal",
  31. "walk_action": "stop_path",
  32. "walk_status": "failed",
  33. "budget_tier": "stop",
  34. }
  35. return {
  36. "edge_id": "path_stop",
  37. "edge_type": "terminal",
  38. "walk_action": "stop_path",
  39. "walk_status": "skipped",
  40. "budget_tier": "stop",
  41. }
  42. def _walk_action_row(
  43. decision: dict[str, Any],
  44. item: dict[str, Any],
  45. decision_action: dict[str, str],
  46. walk_action_id: str,
  47. created_at: str,
  48. binding: dict[str, Any],
  49. execution: dict[str, Any],
  50. ) -> dict[str, Any]:
  51. row = with_raw_payload(
  52. {
  53. "record_schema_version": RUNTIME_RECORD_SCHEMA_VERSION,
  54. "run_id": decision["run_id"],
  55. "policy_run_id": decision["policy_run_id"],
  56. "walk_action_id": walk_action_id,
  57. "edge_id": decision_action["edge_id"],
  58. "edge_type": decision_action["edge_type"],
  59. "from_node_type": "RuleDecision",
  60. "from_node_id": decision["decision_id"],
  61. "to_node_type": "Content",
  62. "to_node_id": item["platform_content_id"],
  63. "walk_action": decision_action["walk_action"],
  64. "walk_status": decision_action["walk_status"],
  65. "budget_tier": decision_action["budget_tier"],
  66. "depth": 0,
  67. "page_cursor": item.get("page_cursor"),
  68. "next_cursor": item.get("next_cursor"),
  69. "decision_id": decision["decision_id"],
  70. "rule_pack_id": binding.get("rule_pack_id") or decision["rule_pack_id"],
  71. "rule_pack_version": binding.get("rule_pack_version") or decision["rule_pack_version"],
  72. "reason_code": decision["decision_reason_code"],
  73. "content_effect_status": decision["search_query_effect_status"],
  74. "decision_target_type": decision.get("decision_target_type"),
  75. "decision_target_id": decision.get("decision_target_id"),
  76. "created_at": created_at,
  77. }
  78. )
  79. row["raw_payload"]["rule_pack_binding"] = binding
  80. row["raw_payload"]["rule_pack_execution"] = execution
  81. return row
  82. def _walk_action_id(
  83. run_id: str,
  84. policy_run_id: str,
  85. edge_id: str,
  86. target_id: str,
  87. decision_id: str,
  88. ) -> str:
  89. raw = f"{run_id}:{policy_run_id}:{edge_id}:{target_id}:{decision_id}"
  90. return f"wa_{hashlib.sha1(raw.encode('utf-8')).hexdigest()[:16]}"