test_v4_m2_platform_sources_replay.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. from __future__ import annotations
  2. import json
  3. from content_agent.business_modules import platform_access
  4. from content_agent.business_modules.content_discovery import content_discovery_builder
  5. from content_agent.integrations.database_runtime import DatabaseRuntimeStore
  6. from content_agent.integrations.runtime_files import LocalRuntimeFileStore
  7. from tests.test_database_runtime import FakeConnection, _config, _insert_values
  8. RUN_ID = "run_m2_replay"
  9. POLICY_RUN_ID = "policy_m2_replay"
  10. class SearchOnlyPlatformClient:
  11. def __init__(self, platform: str, content_id: str):
  12. self.platform = platform
  13. self.content_id = content_id
  14. def search(self, search_query):
  15. return [
  16. {
  17. "content_discovery_id": f"{search_query['search_query_id']}_content_001",
  18. "search_query_id": search_query["search_query_id"],
  19. "platform": self.platform,
  20. "platform_content_id": self.content_id,
  21. "platform_content_format": "video",
  22. "description": f"{self.platform} 内容",
  23. "platform_author_id": f"{self.platform}_author",
  24. "author_display_name": f"{self.platform} 作者",
  25. "statistics": {
  26. "digg_count": 10,
  27. "comment_count": 2,
  28. "share_count": 3,
  29. "collect_count": 4,
  30. "play_count": 100,
  31. },
  32. "tags": ["#祝福"],
  33. "play_url": f"https://video.test/{self.content_id}.mp4",
  34. "has_more": False,
  35. "next_cursor": "",
  36. "platform_raw_payload": {
  37. "channel_content_id": self.content_id,
  38. "channel_account_id": f"{self.platform}_author",
  39. },
  40. "discovery_start_source": search_query["discovery_start_source"],
  41. "previous_discovery_step": "search_query_direct",
  42. }
  43. ]
  44. def test_v4_m2_platform_sources_replay_preserves_observable_containers(tmp_path):
  45. platform_results = []
  46. for platform in ["douyin", "kuaishou", "shipinhao"]:
  47. query = {
  48. "search_query_id": f"q_{platform}",
  49. "search_query": f"{platform} 祝福",
  50. "search_query_generation_method": "item_single",
  51. "discovery_start_source": "pattern_itemset",
  52. }
  53. result = platform_access.run(
  54. [query],
  55. SearchOnlyPlatformClient(platform, f"{platform}_content_001"),
  56. )
  57. assert result["query_failures"] == []
  58. platform_results.extend(result["platform_results"])
  59. runtime = LocalRuntimeFileStore(tmp_path / "runtime")
  60. runtime.prepare_run(RUN_ID)
  61. discovery_result = content_discovery_builder.run(
  62. RUN_ID,
  63. POLICY_RUN_ID,
  64. platform_results,
  65. _source_context(),
  66. runtime,
  67. )
  68. connection = FakeConnection()
  69. store = DatabaseRuntimeStore(_config(), connection_factory=lambda: connection)
  70. store.append_jsonl(
  71. RUN_ID,
  72. "discovered_content_items.jsonl",
  73. discovery_result["discovered_content_items"],
  74. )
  75. inserted = [_insert_values(sql, params) for sql, params in connection.statements]
  76. assert len(inserted) == 3
  77. for values in inserted:
  78. statistics = json.loads(values["statistics"])
  79. platform_raw_payload = json.loads(values["platform_raw_payload"])
  80. raw_payload = json.loads(values["raw_payload"])
  81. assert statistics["digg_count"] == 10
  82. assert statistics["play_count"] == 100
  83. assert platform_raw_payload["channel_content_id"].endswith("_content_001")
  84. assert raw_payload["statistics"] == statistics
  85. assert raw_payload["platform_raw_payload"] == platform_raw_payload
  86. assert raw_payload["matched_search_query_ids"] == [values["search_query_id"]]
  87. def _source_context():
  88. return {
  89. "schema_version": "runtime_record.v1",
  90. "run_id": RUN_ID,
  91. "demand_content_id": "demand_001",
  92. "ext_data": {
  93. "evidence_pack": {
  94. "pattern_source_system": "pg_pattern_v2",
  95. "source_kind": "pattern_itemset",
  96. "source_post_id": "post_001",
  97. "pattern_execution_id": 581,
  98. "mining_config_id": 2082,
  99. "itemset_ids": [1608352],
  100. "seed_terms": ["祝福"],
  101. }
  102. },
  103. }