- Auth/roles (no self-reg), admin user provision, JWT - Analyze: sales kit + initial pain-fit from form/upload - Persona generator: 15 personas (5/tier) w/ pain variety, negotiation, init mode, channel, latent/revealable, wrong_text special - Chat simulator: per-mode initiation, one-shot, hidden signals, judge-LLM debrief+coaching - Trainee loop: win/lose board, weak-areas, user-generated personas - Admin analytics; EN+TH Vue SPA served by Flask - Deploy: Dockerfile, docker-compose, README, eng-log + HANDOFF - Tests (mock LLM): m0/m1/routes/e2e all pass
120 lines
4.6 KiB
Markdown
120 lines
4.6 KiB
Markdown
# 🎯 Sales Trainer
|
||
|
||
A **corporate, multi-user sales-training simulator**. Admins upload/describe a product; the app
|
||
analyzes it and generates **15 realistic customer personas** (5 per buying-intent tier) with real,
|
||
varied pains. Trainees **chat one-on-one** with each persona to practice closing a sale — customers
|
||
negotiate, stall, and refuse unless their pain is genuinely resolved. Debrief reveals + coaches.
|
||
|
||
Built on patterns from the **CrowdSight / MiroFish** swarm engine and clean-room Hermes Brain & Tools plugin.
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
- **Login + roles** (no self-registration): `super_admin` / `admin` / `user`.
|
||
- Admin builds & edits **persona groups** (product + 15 personas), hand-edits personas, sees analytics.
|
||
- User (trainee) **can't create** — only selects a group and practices; sees own results.
|
||
- **Input** via form (product / segment / description) **and/or file upload** (.pdf/.md/.txt).
|
||
Product data is used mainly to extract **pains**; personas are reusable across similar products.
|
||
- **15 personas** (5 × tier A/B/C):
|
||
- A = ready to buy · B = unsure · C = not interested but has pain (hardest).
|
||
- Varied demographics, income, occupation, lifestyle, personality — consistent with product.
|
||
- **Pain variety** (directly-solvable / partial / unrelated red-herring).
|
||
- **Negotiation levers** (price, freebies, delivery time, scope, payment).
|
||
- **Initiation mode**: customer opens OR seller must open the sale (outbound, e.g. insurance).
|
||
- **Channel**: Facebook / LINE.
|
||
- Special tier-C **"wrong_text"** persona (appears to buy, loses interest, but still has pain).
|
||
- **One-shot rule**: a persona is chatted **once per user** (final); shared across other users.
|
||
- **Chat realism**: all tiers can lose; everything negotiates; hidden internal signals + latent
|
||
fields (pain/income/personality/budget) revealed only after the result.
|
||
- **Debrief**: short summary + **coaching** (how to answer better on weak-score messages),
|
||
scored by a **separate judge LLM** (no speed factor).
|
||
- **Training loop**: win/lose board, **weak-area analysis**, and **user-generated personas**
|
||
(weak-area "lock" or manual form).
|
||
- **Admin analytics**: close rate, avg score, hardest personas.
|
||
- **EN + TH** UI.
|
||
|
||
---
|
||
|
||
## Quick start
|
||
|
||
### Local (dev)
|
||
|
||
```bash
|
||
# backend (Python 3.11)
|
||
cd backend
|
||
uv venv --python 3.11 .venv
|
||
uv pip install -r requirements.txt --python .venv/bin/python
|
||
cp .env.example .env # edit LLM keys + JWT_SECRET
|
||
uv run python run.py # Flask on :5001
|
||
|
||
# frontend (separate terminal)
|
||
cd frontend
|
||
npm install
|
||
npm run dev # Vite on :3000 -> proxies /api to :5001
|
||
```
|
||
|
||
The first run creates a default super-admin: **`admin@salestrainer.local` / `admin123`** (change it!).
|
||
|
||
### Docker / EasyPanel
|
||
|
||
```bash
|
||
cp .env.example .env # set LLM_API_KEY + a strong JWT_SECRET
|
||
docker compose up -d # single container serving frontend + API on :5001
|
||
```
|
||
|
||
---
|
||
|
||
## LLM config
|
||
|
||
Any OpenAI-compatible endpoint (OpenAI, DeepSeek, or custom base URL):
|
||
|
||
```env
|
||
LLM_PROVIDER=deepseek # deepseek | openai | custom
|
||
LLM_BASE_URL= # optional override
|
||
LLM_MODEL_NAME=deepseek-chat # optional override
|
||
LLM_API_KEY=sk-...
|
||
```
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
```
|
||
frontend/ Vue 3 + Vite SPA (login, dashboard, group builder, personas, chat, debrief,
|
||
gen-persona, weak-areas, analytics). Built to dist/ and served by Flask.
|
||
backend/ Flask API (JWT auth, roles, groups, analyzer, persona generator, chat simulator,
|
||
judge, trainee loop, analytics). Filesystem JSON persistence (no external DB).
|
||
app/services/ analyzer · persona_generator · simulator (+ judge) · report · trainee · groups · sessions
|
||
docs/PLAN.md full design & decisions record
|
||
```
|
||
|
||
- **Storage**: `backend/data/` — JSON files per entity (users, orgs, groups, sessions, my_personas).
|
||
- **LLM calls**: analyzer (sales kit + pain-fit), persona generator, persona chat, judge.
|
||
|
||
---
|
||
|
||
## Tests
|
||
|
||
Run with the built-in deterministic **mock LLM** (no external key needed):
|
||
|
||
```bash
|
||
cd backend
|
||
uv run python scripts/test_m0.py # auth/roles/no-self-registration
|
||
uv run python scripts/test_m1.py # group create + failure handling + role visibility
|
||
uv run python scripts/test_routes.py # all API routes registered
|
||
uv run python scripts/test_e2e.py # full flow: analyze→personas→chat→debrief→one-shot→board→analytics
|
||
```
|
||
|
||
Real-model verification requires a live `LLM_API_KEY` in `.env`.
|
||
|
||
---
|
||
|
||
## Default accounts
|
||
|
||
| Role | Email | Password |
|
||
|------|-------|----------|
|
||
| super_admin | `admin@salestrainer.local` | `admin123` (change after first login) |
|
||
|
||
Admins create additional users (users/login has no self-registration).
|