test_gate2_query_50plus.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. """M9E:Gate 2 query 级 50+ 判定——yes 保留/no 丢弃/拿不准从宽;judge 解析;游走标签复用。"""
  2. import pytest
  3. from content_agent.business_modules import search_intent
  4. from content_agent.business_modules.search_intent import _gate2_keep
  5. from content_agent.integrations import query_variant
  6. from content_agent.integrations.query_variant import OpenRouterQueryVariantClient
  7. class _Judge:
  8. def __init__(self, verdict):
  9. self.verdict = verdict
  10. self.calls: list[str] = []
  11. def judge_query_fifty_plus(self, query_text):
  12. self.calls.append(query_text)
  13. return self.verdict
  14. class _RaisingJudge:
  15. def judge_query_fifty_plus(self, query_text):
  16. raise RuntimeError("llm down")
  17. class _NoJudge:
  18. pass
  19. def test_gate2_keeps_yes_and_drops_no():
  20. assert _gate2_keep("广场舞", _Judge(True)) is True
  21. assert _gate2_keep("二次元", _Judge(False)) is False
  22. def test_gate2_keeps_on_error_and_missing_method():
  23. assert _gate2_keep("x", _RaisingJudge()) is True # 拿不准从宽放过
  24. assert _gate2_keep("x", _NoJudge()) is True # mock client 无 judge → 放过
  25. def test_judge_parses_no_as_drop_and_else_as_keep(monkeypatch):
  26. client = OpenRouterQueryVariantClient(api_key="k", model="m")
  27. def fake_post(url, headers, json, timeout):
  28. import httpx
  29. answer = {"choices": [{"message": {"content": fake_post.reply}}]}
  30. return httpx.Response(200, json=answer, request=httpx.Request("POST", url))
  31. monkeypatch.setattr(query_variant.httpx, "post", fake_post)
  32. fake_post.reply = "no"
  33. assert client.judge_query_fifty_plus("二次元") is False
  34. fake_post.reply = "yes"
  35. assert client.judge_query_fifty_plus("广场舞") is True
  36. fake_post.reply = "不确定"
  37. assert client.judge_query_fifty_plus("模糊") is True # 非 no 一律放行
  38. def test_judge_keeps_on_http_exception(monkeypatch):
  39. client = OpenRouterQueryVariantClient(api_key="k", model="m")
  40. def boom(*args, **kwargs):
  41. raise RuntimeError("network")
  42. monkeypatch.setattr(query_variant.httpx, "post", boom)
  43. assert client.judge_query_fifty_plus("x") is True
  44. class _Runtime:
  45. def __init__(self):
  46. self.rows: dict = {}
  47. def append_jsonl(self, run_id, filename, rows):
  48. self.rows.setdefault(filename, []).extend(rows)
  49. def _qsp_seed_pack():
  50. return {
  51. "seed_terms": ["养生"],
  52. "query_seed_points": [
  53. {"point_text": "广场舞教学", "point_type": "灵感点", "rank": 1, "post_id": "p1", "id": "a1"},
  54. {"point_text": "二次元手办", "point_type": "灵感点", "rank": 2, "post_id": "p2", "id": "a2"},
  55. {"point_text": "钓鱼技巧", "point_type": "灵感点", "rank": 3, "post_id": "p3", "id": "a3"},
  56. {"point_text": "电竞比赛", "point_type": "灵感点", "rank": 4, "post_id": "p4", "id": "a4"},
  57. ],
  58. "pattern_execution_id": 1,
  59. "mining_config_id": 1,
  60. "source_post_id": "p1",
  61. "matched_post_ids": ["p1"],
  62. "itemset_ids": [],
  63. }
  64. def test_gate2_rejects_query_seed_points_but_keeps_mandatory_seed_terms_for_non_douyin():
  65. # seed_terms 是首轮必搜;非抖音 Gate2 只过滤 query_seed_points。
  66. queries = search_intent.run(
  67. "r", "p", _qsp_seed_pack(), _Runtime(), _Judge(False),
  68. strategy_version="V4", platform="kuaishou",
  69. )
  70. assert [q["search_query"] for q in queries] == ["养生"]
  71. assert queries[0]["search_query_generation_method"] == "seed_term"
  72. assert "gate2_fallback" not in queries[0]["query_source_refs"][0]["source_ref"]
  73. def test_douyin_skips_gate2_and_fallback():
  74. # M13:抖音豁免 Gate2,全产出、无 fallback 标记(零回归)。
  75. queries = search_intent.run(
  76. "r", "p", _qsp_seed_pack(), _Runtime(), _Judge(False),
  77. strategy_version="V4", platform="douyin",
  78. )
  79. assert len(queries) == 5
  80. assert all(
  81. "gate2_fallback" not in q["query_source_refs"][0]["source_ref"] for q in queries
  82. )