refactor(chat): decide buy/walk by per-turn LLM judge (not fixed keywords)

Removed the fixed-value text detector. persona_reply no longer forces JSON meta; instead a
per-turn evaluate_turn() calls the judge LLM after every customer reply to read the persona's
current mood + whether it has decided (buy/walk/pending) + score_delta + reason. send_message
consumes that context-based decision to (a) end the chat as won/lost and (b) move the score.

This is what the user asked: the system evaluates EVERY turn and decides at the moment it's
truly committed — not keyword matching (so 'ซื้อไม่ไหว แต่ว่ามีผ่อนไหม?' stays pending).
Mock updated: judge returns buy on first send (keeps E2E deterministic). 11/11 suites pass.
This commit is contained in:
Macky
2026-08-09 13:19:15 +07:00
parent 94e75238a3
commit c92400b195
4 changed files with 102 additions and 68 deletions

View File

@@ -104,6 +104,10 @@ class MockLLM:
"coaching": [],
"painProgress": {"slow checkout": 100},
}
if "neutral sales-coaching judge" in sp:
# Per-turn state evaluation: mock decides to buy on the first seller message
# (keeps E2E deterministic: first send auto-finishes as won), else pending.
return {"mood": 1, "decision": "buy", "score_delta": 5, "reason": "mock buy"}
return {}
def complete_conversation(self, messages, **kw) -> str: