"""
tests/test_low_quality_response_v2.py
─────────────────────────────────────────────────────────────────
Operation Ollama-First v5.0 / Phase 17 — _is_low_quality_response 4 條新規則驗證
驗證面(規則 5-8 是 Phase 17 新增):
規則 1-4:既有(test_openclaw_qa_routing 已驗)
規則 5: 純英文回應(中文 < 30%)
規則 6: thinking-mode 漏洞(...)
規則 7: 重複迴圈(前 50 字 ≥ 3 次)
規則 8: 佔位符未填充({{var}} / [TODO] / <待填>)
"""
def test_rule5_pure_english_response_rejected():
"""純英文長文應被拒(中文 < 30%)"""
from services.openclaw_strategist_service import _is_low_quality_response
text = (
"This is a long English response from the LLM model that does not "
"have any traditional Chinese characters in it. We expect this kind "
"of response to be rejected as low quality because the user is asking "
"in Traditional Chinese and expects an answer in Traditional Chinese."
)
assert _is_low_quality_response(text) is True
def test_rule5_mixed_chinese_english_acceptable():
"""中英混合(中文佔比 ≥ 30%)應通過"""
from services.openclaw_strategist_service import _is_low_quality_response
# 中文密度高的 text(40%+ 中文字元)
text = (
"本週業績分析報告:總營收較上週成長百分之十二,主要來自家電類別與生活雜貨。\n"
"競品動向監控:對手實施大規模補貼戰,預估壓縮我方百分之三毛利率。\n"
"建議行動:(一) 加碼家電促銷檔期 (二) 觀察補貼是否延續至下週。"
)
assert _is_low_quality_response(text) is False
def test_rule6_thinking_block_leak_rejected():
"""reasoning model thinking 區塊洩漏應拒"""
from services.openclaw_strategist_service import _is_low_quality_response
text_with_open_tag = (
"讓我思考一下這個問題...\n"
"本週業績分析:總營收成長 12% YoY,主要來自家電類別的銷售提升。"
)
assert _is_low_quality_response(text_with_open_tag) is True
text_with_close_only = (
"本週業績分析:總營收成長 12% YoY,主要來自家電類別的銷售提升。\n"
""
)
assert _is_low_quality_response(text_with_close_only) is True
def test_rule7_repetition_loop_rejected():
"""前 50 字出現 ≥ 3 次 → 卡迴圈"""
from services.openclaw_strategist_service import _is_low_quality_response
# 重複 8 次保證 > 200 字(前 50 字出現 ≥ 3 次觸發規則 7)
base = "本週業績有顯著成長,主要驅動類別是家電與生活雜貨大類別。額外文字。"
repeated = base * 8
assert len(repeated) > 200
assert _is_low_quality_response(repeated) is True
def test_rule7_normal_long_text_acceptable():
"""正常長文(即使重複某些字)不該被誤判為迴圈"""
from services.openclaw_strategist_service import _is_low_quality_response
normal_long = (
"本週業績整體呈現上升趨勢,主要驅動類別為家電與生活雜貨大類別。\n"
"競品動向:PChome 在 3C 類發動大規模補貼戰,預估壓縮我方 3-5 個百分點毛利率。\n"
"蝦皮也在母嬰用品加碼免運券促銷,需密切觀察跟降節奏。\n"
"建議行動:(1) 加碼家電促銷檔期 (2) 觀察 PChome 補貼是否延續至下週 "
"(3) 對價差大於 5% 的 SKU 主動啟動 EA 流程。"
)
# 雖然「主要」「促銷」等詞可能重複,但前 50 字的整體 substring 不會出現 ≥ 3 次
assert _is_low_quality_response(normal_long) is False
def test_rule8_placeholder_markers_rejected():
"""偵測佔位符 / 未實作標記"""
from services.openclaw_strategist_service import _is_low_quality_response
cases = [
# {{var}} jinja unfilled
"本週業績:{{revenue}} 元,較上週成長 {{wow_pct}}%。建議行動 ...",
# [TODO] / [todo]
"本週銷售分析:[TODO] 補上具體數字後完成此段。",
"業績檢討:競品分析 [todo] 待補充。",
# <待填>
"本週概況:營收 NT$<待填>,毛利率 <待填>。",
# 尚未實作
"策略建議:(尚未實作) 請統帥手動補充。",
]
for text in cases:
# 補長度避免被規則 1 拒(< 50 字)
text = text + "(測試填充內容延長至大於 50 字)"
assert _is_low_quality_response(text) is True, f"應拒絕含佔位符: {text[:30]}"
def test_legitimate_chinese_business_text_passes():
"""合法繁中商業文字應通過所有 8 條規則"""
from services.openclaw_strategist_service import _is_low_quality_response
text = (
"本週業績分析(2026-05-04):\n"
"總營收 NT$ 4,230,000,較上週成長 12.3% WoW。\n"
"主要驅動類別:家電(+18%)、生活雜貨(+9%)。\n"
"競品動向:PChome 在 3C 類補貼戰預估壓縮我方 3-5pp 毛利率。\n"
"建議行動:加碼家電檔期,對價差 > 5% SKU 啟動 EA 流程。"
)
assert _is_low_quality_response(text) is False