fix(scenario): recontact chats normally first then re-engages mid-chat; channel default=social; remove 'add more' button (15 personas auto)
- recontact persona now opens as a NORMAL customer (no 'I asked before' in the opening); the mid-chat time-lapse system note (turn 2) makes them re-engage warmer instead. - channel default changed facebook->social everywhere (create/analyze/store/simulator/me). - 15 personas auto-generated (TARGET=15); removed the 'สร้างบุคคลต้นแบบเพิ่มเติม' button/guide. All 9 backend suites pass. Rebuilt dist.
This commit is contained in:
@@ -35,7 +35,7 @@ def generate_own_persona(llm: LLMClient, *, mode: str, spec: dict[str, Any]) ->
|
||||
if not isinstance(persona, dict):
|
||||
raise ValueError("own-persona generator returned invalid data")
|
||||
persona.setdefault("tier", "B")
|
||||
persona.setdefault("channel", "facebook")
|
||||
persona.setdefault("channel", "social")
|
||||
persona.setdefault("initiation_mode", "customer")
|
||||
persona.setdefault("pains", [])
|
||||
persona.setdefault("negotiation_levers", [])
|
||||
|
||||
@@ -8,7 +8,8 @@ from ..llm import LLMClient
|
||||
from .persona_prompts import PERSONA_SYSTEM
|
||||
|
||||
TIERS = ["A", "B", "C"]
|
||||
PER_TIER = 5
|
||||
PER_TIER = 5 # 5 per tier = 15 total
|
||||
TARGET = 15 # total personas the system generates (no "add more" button needed)
|
||||
|
||||
|
||||
class PersonaGenerator:
|
||||
@@ -20,7 +21,7 @@ class PersonaGenerator:
|
||||
*,
|
||||
sales_kit: dict[str, Any],
|
||||
language: str = "en",
|
||||
channel: str = "facebook",
|
||||
channel: str = "social",
|
||||
) -> list[dict[str, Any]]:
|
||||
kit_json = json.dumps(sales_kit, ensure_ascii=False)[:12000]
|
||||
lang_name = "Thai" if language == "th" else "English"
|
||||
@@ -46,13 +47,15 @@ class PersonaGenerator:
|
||||
PERSONA_SYSTEM, prompt, temperature=0.8, max_tokens=14000
|
||||
)
|
||||
personas = result.get("personas") or []
|
||||
if (isinstance(personas, list) and len(personas) >= 15) or attempt >= 3:
|
||||
if (isinstance(personas, list) and len(personas) >= TARGET) or attempt >= 3:
|
||||
break
|
||||
if not isinstance(personas, list) or not personas:
|
||||
raise ValueError("persona generator returned no personas")
|
||||
|
||||
normalized, counts = [], {"A": 0, "B": 0, "C": 0}
|
||||
for idx, p in enumerate(personas, start=1):
|
||||
if len(normalized) >= TARGET:
|
||||
break # already reached 20 total
|
||||
if not isinstance(p, dict):
|
||||
continue
|
||||
tier = p.get("tier", p.get("intent_tier"))
|
||||
@@ -86,7 +89,6 @@ class PersonaGenerator:
|
||||
|
||||
if len(normalized) < 8:
|
||||
raise ValueError(f"expected ~15 personas, generated only {len(normalized)}")
|
||||
# NOTE: if we're short of 15 (real LLMs occasionally return 14/13), we ACCEPT what we
|
||||
# got rather than crashing the whole analyze — the caller/UI can top up with
|
||||
# "create more personas". A retry loop lives in generate().
|
||||
# NOTE: if we're short of 15 (real LLMs occasionally return 14), we ACCEPT what we
|
||||
# got rather than crashing the whole analyze — with TARGET=15 there's normally no gap.
|
||||
return normalized
|
||||
|
||||
@@ -102,21 +102,16 @@ class Simulator:
|
||||
"social": "Chat style: short, casual, quick social-messaging replies.",
|
||||
"f2f_call": "Style: natural, conversational like a live face-to-face or phone talk.",
|
||||
}.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')."
|
||||
)
|
||||
# NOTE: 'recontact' is a MID-CHAT behavior, not baked into the opening — the trainee
|
||||
# chats with this customer normally first. At the right turn (see chat_routes) a
|
||||
# time-lapse system note is inserted and only THEN does the customer re-engage warmer.
|
||||
tolerance = int(persona.get("tolerance", 3) or 3)
|
||||
system = CHAT_SYSTEM.format(
|
||||
name=persona.get("name", "Customer"),
|
||||
tone=persona.get("communication_style", "natural, casual"),
|
||||
profession=persona.get("profession", "customer"),
|
||||
age_group=persona.get("age_group", "adult"),
|
||||
channel=persona.get("channel", "facebook") + (f" ({scenario})" if scenario else ""),
|
||||
channel=persona.get("channel", "social") + (f" ({scenario})" if scenario else ""),
|
||||
background=persona.get("background", ""),
|
||||
personality=persona.get("personality", ""),
|
||||
lifestyle=persona.get("lifestyle", ""),
|
||||
|
||||
Reference in New Issue
Block a user