Update readme
Browse files
README.md
CHANGED
|
@@ -12,71 +12,200 @@ pinned: true
|
|
| 12 |
|
| 13 |
**Your first tough pitch should not be in front of a real judge.**
|
| 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 |
## Run Locally
|
| 48 |
|
| 49 |
```bash
|
| 50 |
python -m venv venv
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
pip install -r requirements.txt
|
| 53 |
-
cp .env.example .env
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
python app.py
|
| 55 |
```
|
| 56 |
|
| 57 |
-
Open
|
| 58 |
|
| 59 |
-
|
| 60 |
|
| 61 |
-
##
|
| 62 |
|
| 63 |
-
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
## Project Structure
|
| 68 |
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
-
##
|
| 77 |
|
| 78 |
-
|
| 79 |
-
- [Model Strategy](docs/MODELS_FINAL.md)
|
| 80 |
-
- [Nemotron Omni Audio Architecture](docs/NEMOTRON_OMNI_AUDIO.md)
|
| 81 |
-
- [Full Documentation](docs/DOCUMENTATION.md)
|
| 82 |
-
- [Demo Notes](docs/DEMO_NOTES.md)
|
|
|
|
| 12 |
|
| 13 |
**Your first tough pitch should not be in front of a real judge.**
|
| 14 |
|
| 15 |
+
PitchFight AI is a voice-and-text sparring arena for student founders. Practice a startup pitch, get grilled by realistic AI judges, negotiate a deal round, and walk away with a scorecard that shows what landed and what to fix next.
|
| 16 |
|
| 17 |
+
Built for the Hugging Face **Build Small Hackathon** (Backyard AI track) — deployed as a **Gradio Space** with a custom HTML/CSS/JS frontend.
|
| 18 |
|
| 19 |
+
## What It Does
|
| 20 |
|
| 21 |
+
| Mode | Description |
|
| 22 |
+
|------|-------------|
|
| 23 |
+
| **Pitch battle** | Multi-round Q&A against persona-driven AI judges (skeptical VC, technical judge, hackathon judge, and more) |
|
| 24 |
+
| **Voice pitch** | Record your opening pitch; Nemotron Omni transcribes and extracts structured startup fields |
|
| 25 |
+
| **Voice turns** | Answer judge questions by voice during the battle |
|
| 26 |
+
| **Deal battle** | Post-pitch negotiation phase with anchor points, concessions, and deal-specific scoring |
|
| 27 |
+
| **Scorecard** | Claim-based scoring across six dimensions plus coaching, improved answers, and prep points |
|
| 28 |
+
| **Retry weakest** | Re-answer your weakest question and compare against the original |
|
| 29 |
|
| 30 |
+
## Architecture
|
| 31 |
|
| 32 |
+
```
|
| 33 |
+
Browser (custom frontend)
|
| 34 |
+
│ fetch → /api/*
|
| 35 |
+
▼
|
| 36 |
+
Gradio Server (app.py)
|
| 37 |
+
│ model_router → nvidia_client
|
| 38 |
+
▼
|
| 39 |
+
NVIDIA Nemotron API (integrate.api.nvidia.com)
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
- **Gradio Server** hosts the app on Hugging Face Spaces (`sdk: gradio`, `app_file: app.py`).
|
| 43 |
+
- **Custom frontend** lives in `frontend/` and talks only to `/api/*` routes — never to model providers directly.
|
| 44 |
+
- **All AI inference is API-backed.** Nemotron runs on NVIDIA's servers; this Space does not load local model weights or require a GPU.
|
| 45 |
+
- **Local CPU work** covers session management, rule-based scoring fallbacks, JSON parsing, and optional `ffmpeg` audio format conversion before API calls.
|
| 46 |
+
- **MongoDB** is optional (`MONGODB_ENABLED=false` by default). Sessions work in memory when persistence is off.
|
| 47 |
+
|
| 48 |
+
Gradio also registers internal runtime routes (`/gradio_api/*`, `/queue`, `/upload`, etc.) automatically. Those are framework plumbing for Spaces — the product API is under `/api/...`.
|
| 49 |
+
|
| 50 |
+
## Hugging Face Spaces Deployment
|
| 51 |
+
|
| 52 |
+
### 1. Create the Space
|
| 53 |
+
|
| 54 |
+
- **SDK:** Gradio
|
| 55 |
+
- **Hardware:** CPU basic is sufficient (inference is remote via NVIDIA API)
|
| 56 |
+
- **App file:** `app.py` (set automatically by the README frontmatter above)
|
| 57 |
+
|
| 58 |
+
Push this repository to the Space repo. Hugging Face reads the YAML frontmatter at the top of `README.md` to configure the Space.
|
| 59 |
+
|
| 60 |
+
### 2. Set Space Secrets
|
| 61 |
|
| 62 |
+
In **Settings → Repository secrets**, add:
|
| 63 |
|
| 64 |
+
| Secret | Required | Purpose |
|
| 65 |
+
|--------|----------|---------|
|
| 66 |
+
| `NVIDIA_API_KEY` | **Yes** | Nemotron judge, scoring, and voice calls |
|
| 67 |
+
| `NVIDIA_BASE_URL` | No | Defaults to `https://integrate.api.nvidia.com/v1` |
|
| 68 |
+
| `NVIDIA_OMNI_MODEL` | No | Defaults to `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning` |
|
| 69 |
+
| `DEFAULT_MODEL_MODE` | No | Defaults to `premium_nvidia` |
|
| 70 |
+
| `MAX_ROUNDS` | No | Battle round limit (default `6`) |
|
| 71 |
+
| `ENABLE_VOICE_MODE` | No | Set `false` to disable voice endpoints |
|
| 72 |
+
| `ENABLE_DEAL_BATTLE` | No | Set `false` to disable deal phase |
|
| 73 |
+
| `MONGODB_URI` | No | Only if `MONGODB_ENABLED=true` |
|
| 74 |
+
| `MONGODB_ENABLED` | No | Set `true` to persist sessions to MongoDB |
|
| 75 |
|
| 76 |
+
Never commit real API keys. The frontend never reads secrets — only the Python backend does.
|
| 77 |
|
| 78 |
+
### 3. System packages
|
| 79 |
|
| 80 |
+
`packages.txt` installs `ffmpeg` on the Space for browser audio (WebM) conversion before sending to Nemotron Omni. No extra Space configuration is needed beyond pushing that file.
|
| 81 |
|
| 82 |
+
### 4. Verify deployment
|
| 83 |
+
|
| 84 |
+
After the Space builds:
|
| 85 |
+
|
| 86 |
+
1. Open the Space URL — you should see the PitchFight battle arena.
|
| 87 |
+
2. Hit `/health` — expect `{"status":"ok","app":"PitchFight AI",...}`.
|
| 88 |
+
3. Hit `/api/model-health` — confirm the NVIDIA provider reports configured (keys are not exposed).
|
| 89 |
+
4. Run a full battle: load sample → start session → chat rounds → end battle → view scorecard.
|
| 90 |
+
|
| 91 |
+
If voice fails on certain browsers, ensure `ffmpeg` built successfully (check Space build logs) and `NVIDIA_API_KEY` is set.
|
| 92 |
|
| 93 |
## Run Locally
|
| 94 |
|
| 95 |
```bash
|
| 96 |
python -m venv venv
|
| 97 |
+
|
| 98 |
+
# Windows PowerShell
|
| 99 |
+
.\venv\Scripts\Activate.ps1
|
| 100 |
+
|
| 101 |
+
# macOS / Linux
|
| 102 |
+
# source venv/bin/activate
|
| 103 |
+
|
| 104 |
pip install -r requirements.txt
|
| 105 |
+
cp .env.example .env
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
Edit `.env` and set at minimum:
|
| 109 |
+
|
| 110 |
+
```env
|
| 111 |
+
NVIDIA_API_KEY=your_key_here
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
Optional: install `ffmpeg` locally for reliable voice audio conversion (same role as on the Space).
|
| 115 |
+
|
| 116 |
+
```bash
|
| 117 |
python app.py
|
| 118 |
```
|
| 119 |
|
| 120 |
+
Open `http://127.0.0.1:7860` (or the port set via `PITCHFIGHT_PORT`).
|
| 121 |
|
| 122 |
+
Without `NVIDIA_API_KEY`, model calls fail and the app falls back to mock or local scoring where implemented.
|
| 123 |
|
| 124 |
+
## API Endpoints
|
| 125 |
|
| 126 |
+
Product routes (used by the frontend):
|
| 127 |
|
| 128 |
+
| Method | Path | Purpose |
|
| 129 |
+
|--------|------|---------|
|
| 130 |
+
| `GET` | `/health` | App health check |
|
| 131 |
+
| `GET` | `/api/model-health` | Provider status (no keys exposed) |
|
| 132 |
+
| `POST` | `/api/load-sample` | Load a sample startup |
|
| 133 |
+
| `POST` | `/api/start-session` | Start a pitch battle session |
|
| 134 |
+
| `POST` | `/api/chat-round` | Send a user answer; receive judge reply |
|
| 135 |
+
| `POST` | `/api/end-battle` | End battle and generate scorecard |
|
| 136 |
+
| `POST` | `/api/retry-weakest-question/start` | Begin retry on weakest answer |
|
| 137 |
+
| `POST` | `/api/retry-weakest-question/submit` | Submit retry answer |
|
| 138 |
+
| `POST` | `/api/reset-session` | Clear session state |
|
| 139 |
+
| `POST` | `/api/voice-pitch` | Transcribe opening voice pitch |
|
| 140 |
+
| `POST` | `/api/voice-turn` | Transcribe a battle voice answer |
|
| 141 |
+
| `POST` | `/api/start-deal-phase` | Enter deal negotiation |
|
| 142 |
+
| `POST` | `/api/deal-round` | Send a deal negotiation turn |
|
| 143 |
+
| `POST` | `/api/end-deal` | End deal and generate deal scorecard |
|
| 144 |
+
| `POST` | `/api/deck-critique` | Deck critique placeholder |
|
| 145 |
|
| 146 |
## Project Structure
|
| 147 |
|
| 148 |
+
```
|
| 149 |
+
app.py Gradio Server entrypoint + REST routes
|
| 150 |
+
core/
|
| 151 |
+
api_handlers.py Shared handler logic (REST + Gradio)
|
| 152 |
+
model_router.py Routes tasks to NVIDIA Nemotron
|
| 153 |
+
nvidia_client.py Backend-only NVIDIA API client
|
| 154 |
+
battle_flow.py Pitch battle turn logic
|
| 155 |
+
scoring_engine.py Claim-based scorecard generation
|
| 156 |
+
voice_handler.py Voice transcription via Nemotron Omni
|
| 157 |
+
deal_flow.py Deal negotiation turns
|
| 158 |
+
deal_scoring_engine.py Deal scorecard generation
|
| 159 |
+
session_manager.py In-memory session state
|
| 160 |
+
session_repository.py Optional MongoDB persistence
|
| 161 |
+
frontend/
|
| 162 |
+
index.html Battle arena UI
|
| 163 |
+
script.js Session + battle client
|
| 164 |
+
voice.js Microphone capture + voice API calls
|
| 165 |
+
styles.css UI styling
|
| 166 |
+
config/
|
| 167 |
+
personas.json Judge personas
|
| 168 |
+
attack_tags.json Question attack patterns
|
| 169 |
+
pitch_rubric.json Scoring rubric
|
| 170 |
+
sample_startups.json Demo startups
|
| 171 |
+
packages.txt HF Space system deps (ffmpeg)
|
| 172 |
+
requirements.txt Python dependencies
|
| 173 |
+
.env.example Local env template (copy to .env)
|
| 174 |
+
```
|
| 175 |
+
|
| 176 |
+
## Model & Hackathon Compliance
|
| 177 |
+
|
| 178 |
+
| Rule | How PitchFight complies |
|
| 179 |
+
|------|-------------------------|
|
| 180 |
+
| ≤32B parameters | Primary model: **NVIDIA Nemotron 3 Nano Omni 30B-A3B** |
|
| 181 |
+
| Gradio + HF Spaces | `gradio.Server` in `app.py`, Space metadata in this README |
|
| 182 |
+
| Demo-first | Full battle → scorecard flow runnable in the Space |
|
| 183 |
+
| No frontend API keys | All inference backend-only via `NVIDIA_API_KEY` in Secrets |
|
| 184 |
+
|
| 185 |
+
Inference runs on NVIDIA's hosted API — not on Space hardware — so a CPU Space is enough for production demos.
|
| 186 |
+
|
| 187 |
+
## Environment Variables
|
| 188 |
+
|
| 189 |
+
Copy `.env.example` to `.env` for local development. On Hugging Face, set the same keys as **Space Secrets**.
|
| 190 |
+
|
| 191 |
+
```env
|
| 192 |
+
APP_ENV=development
|
| 193 |
+
MAX_ROUNDS=6
|
| 194 |
+
DEFAULT_MODEL_MODE=premium_nvidia
|
| 195 |
+
|
| 196 |
+
NVIDIA_API_KEY=
|
| 197 |
+
NVIDIA_BASE_URL=https://integrate.api.nvidia.com/v1
|
| 198 |
+
NVIDIA_OMNI_MODEL=nvidia/nemotron-3-nano-omni-30b-a3b-reasoning
|
| 199 |
+
|
| 200 |
+
ENABLE_VOICE_MODE=true
|
| 201 |
+
ENABLE_DEAL_BATTLE=true
|
| 202 |
+
ENABLE_DECK_CRITIQUE=true
|
| 203 |
+
|
| 204 |
+
MONGODB_ENABLED=false
|
| 205 |
+
MONGODB_URI=
|
| 206 |
+
MONGODB_DB_NAME=pitchfight_db
|
| 207 |
+
```
|
| 208 |
|
| 209 |
+
## License
|
| 210 |
|
| 211 |
+
See repository license file if present. API usage is subject to NVIDIA's terms for the Nemotron integrate API.
|
|
|
|
|
|
|
|
|
|
|
|