Problem Β· Demo Β· How It Works Β· System Design Β· AI Pipeline Β· Requirements Β· Judging Β· Setup
Click the card below to open the 200 Words Write-up PDF.
Click the card below to open the Supported Voice Commands guide PDF.
|
A full periodontal exam demands 192 measurements β pocket depths, bleeding flags, recession values β dictated at full conversational speed while both hands hold instruments. Every existing voice charting tool breaks in one of three ways: |
|
ToothStream solves all three β by design, not by accident.
YOU SPEAK CHART UPDATES
ββββββββββ βββββββββββββ
"tooth fourteen Tooth #14 buccal
buccal three depths: [3,5,4]
five four bleeding dot: β
bleeding" cursor β lingual
β β²
β 16 kHz PCM Β· WebSocket Β· 20ms chunks β
βΌ β
FastAPI /ws/audio βββΊ Deepgram Nova-3 βββΊ normalizer.py βββΊ parser.py
[< 20 ms STT] [keyterm-boosted] [homophones] [token extractor]
β
JSON PerioPayload βββββ
β
clinicalRules.ts βββ confidence gate
β
βββββββββββββββββββ΄βββββββββββββββββββ
VERIFIED SUSPICIOUS
< 50 ms Whisper + DeepSeek
β arbitration
βΌ β
State Machine ββββββββββββββββββββββββββββββ
commits entry
advances cursor
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BROWSER β
β β
β π Microphone β
β β Web AudioWorklet β resamples to 16 kHz, linear16 PCM β
β β 20 ms chunks, linear interpolation for non-44.1 kHz inputs β
β βΌ β
β useDeepgramTranscription.ts β
β β binary WebSocket frames (max 120 pending chunks buffered) β
β βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β WebSocketProvider.tsx β global chart state + orchestration β β
β β β β
β β transcriptParser.ts βββΊ clinicalRules.ts βββΊ VERIFIED βββ β β
β β β (7 rule checks) β β β
β β β suspicious? β β β
β β βΌ β β β
β β whisperVerification.ts β β β
β β + deepseekDecision.ts βββββββββββββββββββββββββββββββββββ β β
β β (async AI fallback, only on escalation) β β
β β β β β
β β βΌ β β
β β Clinical State Machine β β
β β tooth β surface β sites[3] β β
β β chart-order cursor Β· per-tooth undo stack β β
β β β β β
β β βΌ β β
β β PerioChart SVG (live render, 32 teeth) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β² JSON PerioPayload
β
β binary PCM βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FASTAPI BACKEND β
β β
β /ws/audio β
β ββ receive_browser_audio() asyncio coroutine β
β ββ stream_audio_to_deepgram() asyncio coroutine β
β ββ relay_deepgram_messages() asyncio coroutine β
β β audio queue maxsize=240, drop-oldest on overflow β
β βΌ β
β Deepgram Nova-3 [keyterm-boosted dental vocabulary] β
β β raw transcript β
β βΌ β
β normalizer.py [homophone + dental alias corrections] β
β β β
β βΌ β
β parser.py [token-level extractor, consumed-index] β
β β structured PerioPayload JSON β
β βββββββββββββββββββββββββββββββββββββββββββΊ Browser β
β β
β /api/whisper-verify Oxlo whisper-large-v3 β
β /api/deepseek-decision DeepSeek v3.2 arbitration β
β /api/generate-report DeepSeek clinical summary β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
States Cursor position Chart traversal order |
Transitions
|
Step 1 AudioWorklet captures 20 ms PCM chunk
Step 2 useDeepgramTranscription sends binary frame over WebSocket
Step 3 FastAPI relay_deepgram_messages() receives Deepgram transcript
Step 4 normalizer.py corrects homophones β parser.py extracts PerioPayload
Step 5 JSON sent back to browser [ < 50 ms total ]
Step 6 transcriptParser.ts re-parses for frontend context
Step 7 clinicalRules.ts validates: confidence Β· tooth range Β· depth range Β·
triplet completeness Β· surface Β· statistical outlier (Ξ > 4 from avg)
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββ
Step 8a β VERIFIED β State machine commits Β· cursor advances β
Step 8b β SUSPICIOUS β Whisper re-transcribes audio Β· DeepSeek β
β β arbitrates with chart context Β· retry Step 7 β
ββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββ
Three layers, ordered by cost. The happy path never touches Layer 3.
|
Homophone Normalizer
Runs before parsing even starts.
|
Clinical Rules Engine
7 deterministic rule checks:
|
Whisper + DeepSeek
Activated when Layer 2 flags suspicious:
|
Result: Happy path < 50 ms Β· 20Γ faster than the 1.0 s p95 target. Layer 3 fires only when data integrity demands it.
| # | Requirement |
|---|---|
FR-01 |
Accept live browser mic audio β 16 kHz, 16-bit PCM, binary WebSocket |
FR-02 |
Transcribe in real time with interim (live feedback) + final (committed) results |
FR-03 |
Parse spoken triplets "three five four" β [3,5,4] without misreading tooth numbers |
FR-04 |
Resolve all dental surface aliases: buccal / lingual / palatal / facial / labial |
FR-05 |
Track cursor across 32 teeth Γ 2 surfaces Γ 3 sites = 192 measurement positions |
FR-06 |
Record: pocket depth Β· bleeding Β· recession Β· furcation class Β· mobility Β· missing Β· implant |
FR-07 |
Handle compound one-breath commands: "tooth 14 buccal 3 5 4 bleeding" |
FR-08 |
Correct STT homophones before parsing reaches the rules engine |
FR-09 |
Validate every payload through clinical rules before chart commit |
FR-10 |
On suspicious payload, replay audio through Whisper and arbitrate via DeepSeek |
FR-11 |
Voice "undo" β per-tooth snapshot stack, no session restart |
FR-12 |
Auto-advance cursor in chart order; handle missing-tooth skip cleanly |
FR-13 |
Export completed chart as a structured PDF report |
FR-14 |
Auto-reconnect to Deepgram on stream drop β no data loss, no manual restart |
| # | Requirement | Threshold | How It's Met |
|---|---|---|---|
NFR-01 |
End-to-end latency p95 | β€ 1.0 s | Achieved: < 50 ms β async pipeline, zero blocking I/O |
NFR-02 |
Hard latency ceiling | β€ 2.0 s | Deepgram Nova-3 STT < 20 ms; rules engine synchronous |
NFR-03 |
Pocket depth accuracy | β₯ 98% | 3-layer pipeline; consumed-index extraction; rules gate |
NFR-04 |
Bleeding flag accuracy | β₯ 90β95% | Token-match + homophone correction; no triplet confusion |
NFR-05 |
State collapses per session | 0 | Formal state machine; explicit commit guards throughout |
NFR-06 |
Reconnection | Auto, no data loss | Exponential backoff 0.5 s β 5.0 s; chart state in browser |
NFR-07 |
Concurrency | Multi-client ready | 3 async coroutines per session; no shared mutable state |
NFR-08 |
Audio fidelity | 16 kHz linear16 | AudioWorklet resamples via linear interpolation |
NFR-09 |
Availability | Stateless, restartable | Zero server-side session state; all chart data in browser |
NFR-10 |
Correctness gate | Confidence β₯ 0.85 | Payloads below threshold escalate; never commit silently |
How:
|
How:
|
|||||||||||||||||||||||||||
|
Zero unrecovered state collapses Β· No ghost entries Β· No wrong-surface drift Β· No session restart needed
|
||||||||||||||||||||||||||||
|
ποΈ Voice & Real-Time
π¦· Clinical Completeness
|
π€ AI Accuracy
βοΈ Reliability
|
| Spoken | Action |
|---|---|
"tooth fourteen" |
Jump cursor to tooth #14 |
"buccal" Β· "lingual" |
Switch active surface |
"three five four" |
Commit depth triplet β mesial / mid / distal |
"bleeding" |
Mark current site DP positive |
"recession two" |
Record 2 mm recession value |
"missing" |
Mark tooth absent, auto-advance cursor |
"implant" |
Mark tooth as implant |
"furcation buccal class 2" |
Furcation class with surface metadata |
"undo" |
Pop per-tooth snapshot stack |
"next tooth" |
Advance cursor in chart order |
ToothStream/
β
βββ backend/
β βββ main.py FastAPI Β· /ws/audio Β· /api/whisper-verify
β β /api/deepseek-decision Β· /api/generate-report
β β Three async coroutines per WS session
β βββ parser.py Token-level extractor Β· consumed-index tracking
β βββ normalizer.py Homophone + dental alias corrections
β
βββ frontend/src/
βββ clinicalRules.ts 7-rule validation gate β Layer 2
βββ components/
βββ WebSocketProvider.tsx Chart state + state machine β core
βββ transcriptParser.ts Voice β PerioPayload
βββ clinicalRulesBridge.ts Rules context + DeepSeek bridge
βββ whisperVerification.ts WAV encode + Whisper fallback β Layer 3a
βββ deepseekDecision.ts DeepSeek arbitration β Layer 3b
βββ useDeepgramTranscription.ts AudioWorklet β 16 kHz PCM β WS
βββ PerioChart.tsx Full-arch chart orchestrator
βββ EnhancedToothCard.tsx Per-tooth SVG + depth render
Prerequisites: Python 3.10+ Β· Node.js 18+ Β· Deepgram API key (free)
git clone https://github.com/A-VISHAL/ToothStream.git
cd ToothStream|
Windows β one command start.batInstalls everything, starts both servers. |
Backend cd backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
echo "DEEPGRAM_API_KEY=your_key" > .env
uvicorn main:app --port 8000 --reload |
# Frontend (new terminal)
cd frontend && npm install && PORT=3002 npm start| Service | URL |
|---|---|
| Frontend | http://localhost:3002 |
| Backend | http://127.0.0.1:8000 |
| WebSocket | ws://127.0.0.1:8000/ws/audio |
