Spaces:
Sleeping
Sleeping
File size: 8,356 Bytes
54ae55a 23b8fad b87bd2d 54ae55a 23b8fad 54ae55a 132a829 54ae55a 132a829 23b8fad 132a829 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | # Discovery Conversation Script
> β οΈ **Design intent, not the present-state map.** The turn-by-turn script
> and adaptive rules below capture the discovery *intent*; the implementation
> is now a single Gemini 2.5-flash call per turn with function-calling tools
> (`backend/single_brain.py` / `brain_tools.py`) β there is no scripted
> question renderer, no `orchestrator`, no `sales_brain` / `qa_brain` split,
> and no separate faithfulness judge. Present-state authority:
> [`README.md`](../../README.md) Β§4.
The 10-turn fact-find that turns a stranger into a profiled buyer.
**Design principles** (inspired by Even.in's tone + insurance-sector buyer-research norms):
1. **Plain language.** No "PED", no "UIN", no "sub-limit". We're talking to an adult who hasn't read a policy wording end-to-end.
2. **Every question explains WHY we're asking.** A form feels invasive; a conversation feels helpful. The one-line why-this-matters subtitle is non-optional.
3. **Chips, not text boxes.** Multi-choice + sliders + toggles. Free-text only when no chip set is honest.
4. **Honesty pre-commitment.** Right after the first turn, the bot tells the user: "Tell me the truth, even on hard things. Your honest answer protects your claim later β not just my recommendation."
5. **Optional, not gated.** The user can stop at any time. We surface what we can with partial profiles (insurer-level CSR / complaints) but ONLY personalize the scorecard once `profile_completeness >= 0.6`.
---
## Turn-by-turn script
### Turn 0 β Welcome (the bot starts)
> "Hi β I'm here to help you find a health policy that genuinely fits **you**, not the one that pays the highest commission to a broker. I'll ask about 8β10 short questions. Some will feel personal (your health, what you earn). **Be honest** β every answer is private to this chat, and being upfront about your medical history is the single biggest thing that protects you when you actually need to claim. Ready?"
[Chip: "Let's start" Β· "Tell me how this works first" Β· "Just let me browse"]
### Turn 1 β Age
> "What's your age?"
>
> *Why we ask: premium, eligibility, and renewability all hinge on this.*
[Slider 18β80, step 1]
### Turn 2 β Who's covered
> "Who else do you want to cover?"
>
> *Why we ask: covering parents or kids changes which policies make sense β some plans price family floaters very differently.*
[Multi-select chips: "Just me", "Spouse", "Children", "Parents", "Parents-in-law"]
### Turn 3 β Parents' health (CONDITIONAL β only if Turn 2 included parents)
> "If you're covering parents, what's the older one's age, and do they have any pre-existing conditions like diabetes, BP, or heart issues?"
>
> *Why we ask: parents-with-PED need policies with shorter PED waiting periods and lifelong renewability β that narrows the field a lot.*
[Slider for age + chips: "None", "Diabetes", "Hypertension/BP", "Heart", "Cancer", "Thyroid", "Multiple"]
### Turn 4 β Your own conditions
> "Any pre-existing conditions for yourself? Diabetes, BP, thyroid, asthma, anything chronic?"
>
> *Why we ask: this is where honesty matters most. Hiding it gets your premium βΉ500 cheaper today and a denied claim of βΉ8 lakh later. Insurers can and do find out at claim time.*
[Multi-select: "None", "Diabetes", "BP/Hypertension", "Thyroid", "Asthma", "Heart", "Cancer history", "Other"]
### Turn 5 β Existing cover
> "Do you already have any health insurance β through your employer or that you bought yourself?"
>
> *Why we ask: if you already have βΉ5L from work, you might need a top-up rather than a full base plan β different product, different price.*
[Chips: "None", "Employer only", "Personal policy", "Both" β if any, ask sum insured slider]
### Turn 6 β City
> "Which city or town?"
>
> *Why we ask: cashless hospital network density varies massively. A "16,000-hospital network" means nothing if none are near you.*
[Free text + autocomplete] OR [Chips: "Metro", "Tier-1", "Tier-2", "Tier-3 / smaller town"]
### Turn 7 β Budget
> "Roughly what annual premium budget feels comfortable?"
>
> *Why we ask: helps us rank β but if a slightly higher budget materially improves your protection, we'll flag it.*
[Slider with 4 markers: <βΉ15k, βΉ15β30k, βΉ30β60k, βΉ60k+]
### Turn 8 β Maternity & near-term events (CONDITIONAL)
> "Anything planned in the next 12β24 months β pregnancy, a known surgery, anything you've discussed with a doctor recently?"
>
> *Why we ask: most policies have 30-day initial waits and 24β36-month maternity waits. If you need cover soon, that filters the list.*
[Multi-select: "Pregnancy planned", "Surgery planned", "Recent hospitalisation", "None of these"]
### Turn 9 β Risk preference
> "When it comes to surprises in your bill, what do you prefer?"
>
> *Why we ask: this single answer decides whether co-pay/deductible plans (cheaper premium, share-of-bill) or full-cover plans (higher premium, predictable bill) fit you.*
[Chips: "Lowest premium, I'll accept a 10β20% co-pay", "Balanced", "No surprises β full cover at higher premium"]
### Turn 10 β Income (optional, asked last)
> "One last optional question β your annual income band. We use it only to gauge how much sum insured fits your risk."
>
> *Why we ask: if you earn βΉ8L/yr, a βΉ50L cover is overkill; if you earn βΉ40L/yr, a βΉ5L cover leaves you exposed.*
[Chips: "Prefer not to say", "<βΉ5L", "βΉ5β10L", "βΉ10β25L", "βΉ25L+"]
### Wrap
> "That's all I needed. Here's what I heard: <readback_summary>. I'll now show you 3 policies that fit best, with the exact reasons they ranked well **for you specifically**."
β Render scorecard cards (now personalised because `profile_completeness >= 0.6`).
---
## Honest disclosure β the trust contract
Right after Turn 0 and again before Turn 4 (own conditions), the bot surfaces a one-line contract:
> "Your answers stay in this conversation. They are NOT shared with any insurer until you choose to buy a policy through their channel. Being honest with me about your medical history is also what makes your claim defensible later β because insurers can match disclosed history against hospital records at claim time."
This is the customer-protection framing. It tells the user honesty is **self-protection**, not insurer-favoring.
---
## Adaptive rules
- If the user is in free-form mode (asks questions back to the bot), don't push the script β let them lead. Resume when they ask "what do you recommend?"
- If `profile_completeness >= 0.6` after some subset of questions, offer to skip the rest: "I have enough to recommend now. Want to keep going, or see what I'd suggest?"
- Never ask the same question twice. `Profile.asked` tracks this.
- A user who says "just show me policies" gets the marketplace with insurer-level metrics (CSR / complaints) visible but per-user scorecards GREYED with a "complete your profile to see how this ranks for you" CTA.
---
## Implementation notes
The 9-slot fact-find SCHEMA still lives in `backend/needs_finder.py::GRAPH` β used now as the schema source embedded in the single-LLM system prompt rather than as a scripted question list. Each entry's `id`, `field`, `is_core`, and `condition` are consumed by the LLM as a structured contract; the `prompt_en` / `prompt_hi` strings are no longer rendered to the user (the LLM owns voice + cadence end-to-end via its system prompt + the conversation so far, and records facts through the `save_profile_field` tool).
To add a new question:
1. Add a `Question(...)` entry with `id`, `field` (which Profile attribute it sets), `is_core` (boolean β counts toward completeness), optional `condition` callable, optional `parser`.
2. Surface the new slot in the single-brain system prompt's 9-slot schema (alongside accepted value shapes + examples) so the LLM knows to capture it. See the system prompt in `backend/single_brain.py`.
3. Wire any post-capture validation into the `save_profile_field` handler in `backend/brain_tools.py` (enum coercion, INR parsing, bounds).
4. Add a row in `70-docs/scorecard-knowledge-graph.md` Part B showing how the new input shifts weights.
5. Wire the shift into `_profile_tuned_weights()` in `backend/scorecard.py`.
Drift between these places breaks the transparency promise. Keep them in sync.
|