refactor(scenario): only 2 scenarios (social / face-to-face); 're-contact' becomes a persona trait

- Scenario picker now has only social + f2f_call (removed recontact) in backend
  _scenarios, start_session validation, and Chat.vue picker.
- 'ลูกค้ากลับมาติดต่อ' is no longer a scenario: it's now a PERSONA trait. Persona prompt
  generates ~1-in-4 personas with recontact=true (asked before, now returns warmer/ready);
  store shape gets recontact field; simulator injects a re-contact note into the persona's
  system prompt so it plays as a returning customer naturally.
- test_scenario updated: unknown scenario defaults to social; recontact shown as a
  generated persona trait.
All 9 backend suites pass. Rebuilt dist.
This commit is contained in:
Macky
2026-08-09 11:21:34 +07:00
parent cb2642a659
commit fd2cae9e62
35 changed files with 54 additions and 48 deletions

View File

@@ -25,6 +25,10 @@ EACH persona MUST include ALL of these fields:
- tolerance (1-5): how many irritant/poor answers you tolerate before you walk away ("heart"). IMPORTANT:
a temperamental/impatient persona has LOW tolerance (1-2, walks away fast after poor answers); a patient
one has HIGH (4-5). Avg is 3. Match tolerance to personality (e.g. a busy owner / abrupt personality = low).
- recontact (true/false): if true, this persona asked about the product BEFORE (earlier contact, e.g. a few
weeks/months back) and is ONLY NOW coming back / re-opening, more ready to buy and less price-sensitive.
These are already-pre-qualified, warmer leads. Make about 1 in every 4 personas recontact=true, spread across tiers.
A recontact persona opener/small-talk often references "I asked about this before" naturally.
RULES:
1. DIVERSITY: 15 distinct people across age groups, occupations, incomes, lifestyles,

View File

@@ -101,8 +101,15 @@ class Simulator:
adapt = scenario_adapt or {
"social": "Chat style: short, casual, quick social-messaging replies.",
"f2f_call": "Style: natural, conversational like a live face-to-face or phone talk.",
"recontact": "Style: casual messaging; you already know the product from 1-3 months ago.",
}.get(scenario, "")
# Personality trait: a "recontact" customer asked about this before and is only now
# coming back, already warmer / more ready to buy. Reference it in chat naturally.
if persona.get("recontact"):
adapt += (
"\nYou contacted/interacted with this seller BEFORE (earlier contact) and are now "
"coming back — you already know the product basics, so you're warmer and more ready "
"to decide. Mention this naturally (e.g. 'I asked about this a while back')."
)
tolerance = int(persona.get("tolerance", 3) or 3)
system = CHAT_SYSTEM.format(
name=persona.get("name", "Customer"),

View File

@@ -43,6 +43,7 @@ def ensure_persona_shape(p: dict[str, Any]) -> dict[str, Any]:
"negotiation_levers": p.get("negotiation_levers", []),
"opener": p.get("opener", ""),
"special": p.get("special", ""), # e.g. "wrong_text" | ""
"recontact": bool(p.get("recontact")), # returned after researching earlier (pre-qualified, warm)
"difficulty": p.get("difficulty", 1), # 1..5
"tolerance": p.get("tolerance", 3), # misses before this persona walks away (temper)
"notes": p.get("notes", ""),