"""Generate a user's own persona (private) from weak-area spec or a manual form.""" from __future__ import annotations from typing import Any from ..llm import LLMClient OWN_PERSONA_SYSTEM = """You generate ONE customer persona for a sales-training simulator, PRIVATE to a specific trainee. You produce valid JSON only: {"persona": { ... }}. The persona dict must contain: name, tier, channel, initiation_mode, profession, age_group, location, product_context (revealable), plus background, income, lifestyle, personality, communication_style, budget, decision_timeline, goal, objections[], pains[] (with fit + rootCause + resolutionConditions), negotiation_levers[], opener, difficulty, special, notes. The trainee wants to specifically practice against the described weakness/profile, so make this persona HARD in exactly that dimension (e.g. heavy price negotiation, seller-initiated cold lead, skeptical). Keep pains partially product-solvable for realism. """ def build_own_persona_user_prompt(*, mode: str, spec: dict[str, Any]) -> str: if mode == "weak-area": return ( "Mode: WEAK-AREA 'lock' persona. Generate a persona specifically targeting the " "trainee's reported weaknesses:\n" + str(spec) ) return "Mode: MANUAL. Generate a persona matching the trainee's description:\n" + str(spec) def generate_own_persona(llm: LLMClient, *, mode: str, spec: dict[str, Any]) -> dict[str, Any]: user_prompt = build_own_persona_user_prompt(mode=mode, spec=spec) result = llm.complete_json(OWN_PERSONA_SYSTEM, user_prompt, temperature=0.8, max_tokens=7000) persona = result.get("persona") or result if not isinstance(persona, dict): raise ValueError("own-persona generator returned invalid data") persona.setdefault("tier", "B") persona.setdefault("channel", "social") persona.setdefault("initiation_mode", "customer") persona.setdefault("pains", []) persona.setdefault("negotiation_levers", []) return persona