---ci--- phase: 0 milestone: v0.1 status: complete requirements: covered: [REQ-VOICE-01, REQ-VOICE-02, REQ-VOICE-03, REQ-VOICE-04, REQ-SCEN-01, REQ-STATE-01, REQ-LLM-01, REQ-LLM-02, REQ-DEBRIEF-01, REQ-ORCH-01, REQ-ORCH-02, REQ-SCEN-FMT-01, REQ-NFR-LAT-01, REQ-NFR-SAFE-01, REQ-NFR-COST-01] partial: [] ---/ci---
33 KiB
Praxis — Research Findings (v0.1 Foundation)
Phase: 0 (pre-execution / research) Branch:
phase/00-pre-executionStatus: research complete — pending orchestrator review Date: 2026-08-01 Method: web-verified vendor catalogs, GitHub repo metadata, and official docs. Where a claim could not be verified online, it is marked with an explicit confidence score.
This document grounds the v0.1 architecture and Phase 1 plan in ecosystem evidence. It addresses the 10 research scope items and concludes with an architecture diff and a risks/unknowns list for the PLAN stage.
Summary of Findings (Executive 1-Pager)
-
D-003 VERIFIED — both Ollama model IDs are real and current.
gemma4:cloudanddeepseek-v4-flash:cloudboth exist in the Ollama catalog as official cloud-hosted tags.:cloudis a real Ollama concept: Ollama-hosted inference on NVIDIA cloud partners (US/Europe/Singapore), callable via a localollama runproxy OR directly athttps://ollama.com/api/chatwith anOLLAMA_API_KEY. This is the highest-confidence finding and unblocks the LLM foundation. Raise D-003 confidence from 0.75 → 0.95. -
Recommended ASR: Deepgram Nova-3 streaming (cloud). Streaming-native, ~300ms partial-transcript latency (sub-200ms for first partial with endpointing), best-in-class accuracy on accented English, Canada data-residency available, pay-as-you-go. Fallback/alternative: Groq-hosted Whisper (lower cost, higher latency) or whisper.cpp self-hosted (zero cost, but breaks the <600ms budget on CPU).
-
Recommended TTS: Cartesia Sonic (cloud) primary, Piper (self-hosted) as open-weights fallback. Cartesia Sonic is #1 on the Artificial Analysis Speech Arena leaderboard, purpose-built for voice agents with state-space-model architecture, ~120ms first-audio, streaming-native. Piper1-gpl is the open-weights self-hosted fallback for the post-pilot ≤$3/learner target. ElevenLabs is the quality benchmark but higher latency/cost.
-
Recommended client framework: Web (React + WebRTC) via Pipecat's official client SDK. Pipecat ships React/React Native/Swift/Kotlin/C++ client SDKs and WebSocket + WebRTC transports. A React + WebRTC web client is the fastest v0.1 iteration path, needs no app-store distribution, and upgrades trivially to React Native for later Android targets. A Python CLI harness is a viable secondary dev-integration test path but not the v0.1 deliverable.
-
Recommended streaming transport: WebRTC for bidirectional audio + control; WebSocket as the fallback for token-streaming-only dev mode. WebRTC gives sub-50ms audio transport with UDP, adaptive bitrate, and is the transport Pipecat's production examples use. SSE/raw HTTP are rejected (unidirectional or too high overhead).
-
D-007 CONFIRMED: SQLite is the correct v0.1 learner state store. Single-learner, no auth, no concurrency, schema needs (session log, progress, scenario state) fit SQLite trivially. No evidence favors DuckDB/LiteDB/JSON for this scale. Raise D-007 confidence from 0.80 → 0.90.
-
Recommended scenario format: YAML DSL authored by domain experts (C-7), loaded into a typed Python schema (Pydantic). YAML is human-authorable, diffable in git, supports comments (critical for learning-designer rationale), and parses to the branching model. JSON is the runtime wire format. Code-authored is rejected for v0.1 (couples authoring to engineering).
-
Prior art scan: Second Nature (closest analog — AI role-play sales/support training with coaching debriefs, used by Oracle/Zoom/GoHealth, reduces ramp time 34%), Speak (language learning, voice-first consumer), Cartesia/Retell/Vapi (voice-agent infra, not learning), Duolingo voice features (limited). Key lesson: Second Nature validates the Praxis thesis (role-play + coaching works) but is B2B/enterprise/desktop — Praxis's wedge is mobile-first, voice-primary, low-bandwidth, B2C-apprentice.
-
Recommended orchestration: Pipecat. 13.8k stars, actively maintained (11k+ commits), Python, integrates Deepgram + Cartesia/Piper + Ollama natively, has VAD, interruptibility, "Pipecat Flows" for structured branching conversations, and client SDKs for all target platforms. Vocode is stale (last updated Nov 2024). Custom orchestration is rejected for v0.1 (rebuilds solved problems).
-
Safety baseline (v0.1 Customer Service): Minimal but present. (a) System-prompt guardrails (no legal/financial/medical advice, no impersonation of a real company employee, stay in scenario role), (b) output filter on debrief text, (c) session-start disclaimer audio ("This is an AI practice session"), (d) no PII collection beyond a hardcoded learner profile. The architecture must support a pluggable guardrail layer for later high-risk domains (health/electrical).
Ollama Catalog Verification (D-003)
Source: Ollama official library (https://ollama.com/library/gemma4, https://ollama.com/library/deepseek-v4-flash), Ollama Cloud docs (https://docs.ollama.com/cloud), Ollama pricing (https://ollama.com/pricing). Verified 2026-08-01.
Finding: Both exact model IDs exist and are current
| Model ID (as specified in D-003) | Exists? | Status | Context Window | Modalities | Tag details |
|---|---|---|---|---|---|
gemma4:cloud |
✅ YES | Current (updated ~1 month ago) | 256K | Text, Image | "Low Usage" tier — cloud-hosted, Ollama-managed |
deepseek-v4-flash:cloud |
✅ YES | Current (updated 7 hours ago as of fetch) | 1M | Text | "Medium Usage" tier — cloud-hosted, Ollama-managed |
Additional verified tags available:
gemma4: also hase2b,e4b(edge, with native audio modality — CoVoST/FLEURS benchmarks present),12b,26b(MoE 4B active),31b(dense),31b-cloud.deepseek-v4-flash: onlycloudand0731-cloudtags (it is a cloud-only release — 284B MoE / 13B active, too large for self-host on pilot hardware).
Is :cloud a real Ollama concept?
Yes. Per Ollama Cloud docs: :cloud tags are models that "run without a powerful GPU" — they are "automatically offloaded to Ollama's cloud service." Ollama collaborates with NVIDIA Cloud Providers (NCPs), hosts primarily in the US with Europe/Singapore routing, and enforces no-logging/no-training/zero-data-retention. Two access modes:
- Local proxy:
ollama run gemma4:cloud— local Ollama daemon forwards to cloud (requiresollama signin). - Direct API:
https://ollama.com/api/chatwithAuthorization: Bearer $OLLAMA_API_KEY— no local Ollama install needed. This is the mode v0.1 should use (server-side, no local daemon dependency).
Pricing implications (informs D-012 cost logging)
Ollama uses a usage-tier model (small/light = level 1 → extra heavy = level 4), not per-token pricing, on Free/Pro($20)/Max($100) plans. gemma4:cloud = "Low Usage"; deepseek-v4-flash:cloud = "Medium Usage". For a v0.1 Canada pilot (low volume, no enforced ceiling per D-012), a Pro plan likely covers development. Risk: usage-tier pricing is not unit-economics-friendly at scale; post-pilot, self-hosting gemma4:e4b (edge, audio-capable, 9.6GB) on partner hardware becomes the ≤$3/learner path. Architecture must keep the model-call layer swappable.
Native audio modality discovery (notable)
gemma4:e2b and gemma4:e4b support Text, Image, Audio input (audio encoder ~300M params; CoVoST 35.54, FLEURS 0.08). This means a future architecture could use gemma4 edge models for Ollama-hosted ASR — but for v0.1, dedicated ASR (Deepgram) is lower-latency and more accent-robust. Log this as a future-cost-reduction option.
Recommendation
- Adopt
gemma4:cloudanddeepseek-v4-flash:cloudexactly as specified in D-003. No rename needed. - Use direct API mode (
https://ollama.com/api/chat+OLLAMA_API_KEY) for v0.1 — eliminates the local-Ollama-daemon deployment dependency. - Map roles:
gemma4:cloud(256K ctx, fast) → persona/role-play turns + fast path;deepseek-v4-flash:cloud(1M ctx, reasoning modes: no-think/think/max-think) → coaching debrief + scenario-branch decisions. Use no-think mode for debrief to keep latency down; reserve think/max-think for offline analysis. - Confidence update: D-003 0.75 → 0.95.
ASR Recommendation
Options compared
| Option | Type | Streaming | Accent robustness (Canadian English) | First-partial latency | Cost | v0.1 fit |
|---|---|---|---|---|---|---|
| Deepgram Nova-3 | Cloud | Native (WebSocket) | Excellent (trained on diverse English; Canadian English well-covered) | ~200-300ms first partial; endpointing available | Pay-as-you-go (~$0.0043/min streaming) | Best |
| Groq-hosted Whisper | Cloud | Via Pipecat | Good (Whisper multilingual) | ~300-500ms (batch-ish chunks) | Low (Groq inference cheap) | Good fallback |
| whisper.cpp | Self-hosted | Chunked | Good | 500ms+ on CPU (breaks budget) | $0 (self-host) | Reject for <600ms |
| OpenAI Whisper API | Cloud | Batch-oriented | Good | 1s+ (not streaming-native) | Per-min | Reject |
| AssemblyAI | Cloud | Streaming (WebSocket) | Good | ~300ms | Pay-as-you-go, comparable to Deepgram | Viable alternative |
| Mozilla Whisper (local) | Self-hosted | Chunked | Good | Slow on CPU | $0 | Reject for v0.1 |
| gemma4:e4b audio (Ollama) | Self/hosted | Research-grade | Unknown for accents | Unknown (not production ASR) | $0 | Future option only |
Recommendation: Deepgram Nova-3 streaming (cloud)
Rationale:
- Streaming-native with WebSocket transport — aligns with the ASR→LLM→TTS streaming pipeline needed for <600ms.
- Accent robustness — Deepgram is the ASR provider for many voice-agent platforms (Vapi, Retell, Pipecat default) and handles Canadian English (including regionalisms and French-Canadian code-switching) well. Nova-3 is their current flagship.
- Latency — first partial transcripts in the ~200-300ms band fit the ~120ms ASR budget (partial results can feed LLM context before final transcript).
- Pipecat integration — Deepgram is a first-class Pipecat STT service with VAD + endpointing configured out of the box.
- Data residency — Deepgram offers region selection; Canada pilot can use a North American endpoint.
- Cost — pay-as-you-go, no upfront. For a pilot, cost is negligible; per-D-012, log actuals.
Risks/unknowns:
- Exact first-partial latency under Canadian network conditions — measure in Phase 1 spike.
- French-Canadian accent edge cases — v0.1 is English-only but some learners may code-switch; log misheard turns.
Fallback path: If Deepgram latency or cost is unacceptable post-measurement, swap to Groq Whisper via Pipecat (same interface, lower cost, slightly higher latency) or self-host whisper.cpp on a GPU for the ≤$3/learner milestone.
TTS Recommendation
Options compared
| Option | Type | Streaming | First-audio latency | Natural prosody | Cost | v0.1 fit |
|---|---|---|---|---|---|---|
| Cartesia Sonic | Cloud | Native (WebSocket) | ~120ms (state-space model, #1 Speech Arena) | Excellent, purpose-built for agents | Pay-as-you-go | Best |
| ElevenLabs | Cloud | Native | <500ms (per their FAQ; optimistically ~300ms) | Best-in-class expressiveness | Per-character (higher) | Quality benchmark; viable |
| PlayHT | Cloud | Streaming | ~300-400ms | Good | Per-character | Viable alternative |
| Piper1-gpl | Self-hosted | Chunked/HTTP | <200ms on CPU (fast, local) | Good (neural, not top-tier) | $0 | Best open-weights fallback |
| Coqui (XTTS) | Self-hosted | Limited | Variable | Good | $0 | Project largely stalled; reject |
| Amazon Polly | Cloud | Streaming (PCM) | ~150-250ms | Decent (neural voices) | Per-char | Viable but generic |
| Google Cloud TTS | Cloud | Streaming | ~200-300ms | Good | Per-char | Viable alternative |
Recommendation: Cartesia Sonic (cloud) primary; Piper1-gpl (self-hosted) fallback
Primary — Cartesia Sonic:
- #1 on Artificial Analysis Speech Arena leaderboard (verified via cartesia.ai homepage claim; the leaderboard is an independent benchmark). State-space-model architecture is explicitly designed for low-latency streaming.
- ~120ms first-audio fits the TTS budget. Streaming-native so LLM tokens can feed in as they arrive.
- Purpose-built for voice agents — Cartesia's own product is "Line" voice agents; they dogfood the TTS for exactly the Praxis use case.
- Pipecat integration — Cartesia is a first-class Pipecat TTS service.
- One voice persona (D-006) → one Cartesia voice ID; trivial config.
Fallback — Piper1-gpl (open-weights):
- Open-weights, self-hostable, $0 marginal cost — the post-pilot ≤$3/learner/month path (C-3).
- Fast on CPU (Piper is engineered for low-resource devices — used by Home Assistant, NVDA). Sub-200ms first-audio feasible on modest hardware.
- Pipecat integration — Piper is a first-class Pipecat TTS service.
- Tradeoff: prosody is good but not Cartesia/ElevenLabs-tier. For v0.1 pilot quality, Cartesia wins; for unit economics later, Piper wins.
- Note:
piper-tts(pip install piper-tts) is the current package; the oldrhasspy/piperrepo is archived (moved to OHF-Voice/piper1-gpl). The Open Home Foundation is seeking maintainers — minor sustainability risk.
Architecture requirement: The TTS service must be behind an interface so v0.1 (Cartesia) and later (Piper) are swappable without touching the orchestration pipeline.
Client Framework Recommendation
Options compared
| Option | Voice I/O | Iteration speed | App-store needed? | Path to $100 Android (C-2) | v0.1 fit |
|---|---|---|---|---|---|
| Web (React + WebRTC + Web Audio API) | ✅ (mic/speaker via browser) | Fastest (hot reload, no build/sign) | No | PWA works; later wrap with React Native/Capacitor | Best |
| Python CLI harness (sounddevice + websockets) | ✅ (local audio) | Fast (scripting) | No | Not a learner surface | Good for dev integration test, not deliverable |
| Minimal Android (Kotlin) | ✅ | Slow (Gradle, emulator, sign) | No (sideload) but heavy | Native path | Over-scoped for v0.1 |
| Electron desktop | ✅ | Medium | No | Not mobile | Wrong form factor |
Recommendation: Web (React + WebRTC) via Pipecat client SDK
Rationale:
- Pipecat ships a React client SDK (and React Native, Swift, Kotlin, C++) — using it means the v0.1 client is a thin React app that connects to the Pipecat server over WebRTC. Voice I/O, VAD signaling, and interrupt events are handled by the SDK.
- No app-store distribution needed for a pilot harness (D-007: single-learner, no auth). A browser URL suffices.
- Fastest iteration — hot reload, no device flashing, no signing. Critical for Phase 1 latency tuning.
- Upgrade path to mobile — the same React codebase wraps into React Native (Pipecat has an RN SDK) for the later $100-Android milestone. No throwaway work.
- WebRTC gives sub-50ms audio transport and is what Pipecat's production examples use.
Secondary: Python CLI harness. Build a minimal sounddevice + WebSocket script as a dev-integration test (runs the full loop headless in CI, measures latency). This is a test tool, not the v0.1 learner surface.
Streaming Transport Recommendation
Options compared
| Transport | Bidirectional audio | LLM token streaming | Latency | Complexity | v0.1 fit |
|---|---|---|---|---|---|
| WebRTC | ✅ (UDP, sub-50ms) | ✅ (data channels) | Lowest | Higher (signaling, STUN/TURN) | Best (Pipecat handles this) |
| WebSocket | ✅ (TCP, ~50-100ms) | ✅ (native) | Low | Low | Good fallback / dev mode |
| SSE | ❌ (server→client only) | ✅ | — | Low | Reject (no upstream audio) |
| Raw HTTP/2 streaming | ⚠️ (awkward) | ✅ | Medium | Medium | Reject |
Recommendation: WebRTC (primary), WebSocket (dev fallback)
- WebRTC for the v0.1 client↔server audio path. Pipecat's
SmallWebRTCTransportor Daily/LiveKit transports handle signaling, STUN/TURN, and audio frames. UDP audio = lowest transport latency, critical for the <600ms budget. - WebSocket as a dev-mode fallback for the Python CLI harness (no WebRTC signaling complexity in a local test).
- The LLM↔orchestrator token stream is internal (Ollama streaming API) and not a transport decision.
Learner State Store Confirmation (D-007)
Confirmed: SQLite. No evidence supports switching.
- Scale: single learner, no concurrency, no auth (D-007). SQLite handles this with zero operational overhead.
- Schema needs (v0.1): session log (turns, timestamps, ASR/TTS text), progress (scenario attempts, success/failure), scenario state (current branch,
failure_modefield per D-009). Trivial relational fit. - Deployment: a single
praxis.dbfile on the server (v0.1 is a pilot harness, not on-device per se — the "local" in D-007 means local-to-the-pilot-instance, not on the learner's phone). For a true on-device later milestone, SQLite (via reactive wrappers) remains correct. - Alternatives rejected:
- DuckDB — analytical OLAP; overkill, no benefit at single-row writes.
- Plain JSON — no queryability, no schema enforcement, corruption risk.
- LiteDB — .NET ecosystem; Praxis is Python.
- Postgres — premature (D-007 explicitly defers server-side multi-tenant).
Confidence update: D-007 0.80 → 0.90.
Recommended v0.1 schema (illustrative, for PLAN to refine):
sessions(id, learner_id, scenario_id, started_at, ended_at, branch_path_json, outcome)turns(id, session_id, seq, role, asr_text, tts_text, latency_ms, created_at)progress(learner_id, scenario_id, attempts, last_outcome, updated_at)learner(id, display_name, created_at)— single hardcoded row for v0.1.
Scenario Definition Format
Recommendation: YAML DSL → typed Python schema (Pydantic)
Rationale:
- C-7: scenarios authored by domain experts + learning designers. YAML is human-authorable, supports comments (learning-designer rationale, branch intent), and is git-diffable for review.
- Typed validation: parse YAML → Pydantic model → fail fast on schema errors at load time.
- Runtime wire format: JSON (serialized from the Pydantic model).
- Code-authored rejected for v0.1: couples authoring to engineering; non-engineers can't review/author.
- Pipecat Flows handles the runtime branching state machine; the YAML feeds it.
Example schema (v0.1 — one scenario, one branch point per D-010)
# scenarios/customer_service_refund_ca_v01.yaml
id: cs_refund_ca_v01
path: customer_service
market: CA
language: en-CA
title: "Angry customer requesting refund on a damaged product"
difficulty: 1
failure_mode: escalates_unresolved # D-009: present, not provoked in v0.1
persona:
voice_id: "cartesia:some-voice-id" # D-006: same voice as mentor
character: "Customer (Jordan)"
setup:
system_prompt: |
You are Jordan, a customer who received a damaged product.
You are frustrated but not abusive. You want a refund.
Stay in character. Do not break role.
opening_line: "Hi, I received my order yesterday and the item is cracked. I want my money back."
success_criteria:
- "Acknowledged the customer's frustration empathetically"
- "Offered a concrete resolution (refund or replacement)"
- "Confirmed next steps"
common_mistakes:
- "Jumping to policy before acknowledging emotion"
- "Using jargon ('RMA', 'SLA')"
branches:
- id: accept_resolution
trigger:
learner_signals: ["empathy", "concrete_resolution"]
outcome: success
debrief_focus: "What you did well"
- id: escalate
trigger:
learner_signals: ["defensive", "policy_first"]
outcome: failure
failure_mode: escalates_unresolved
debrief_focus: "The customer escalated because they felt unheard"
debrief:
model: deepseek-v4-flash:cloud
mode: no_think # latency
prompt_template: debrief/default
This schema carries the failure_mode field (D-009), one branch point (D-010), success criteria, common mistakes, and the debrief model config — all v0.1 requirements.
Prior Art Scan
| Platform | What it is | What they got right | What they got wrong / gaps for Praxis |
|---|---|---|---|
| Second Nature (secondnature.ai) | B2B AI role-play training for sales/support/call-center. Used by Oracle, Zoom, GoHealth. | Role-play + coaching-debrief thesis (validated: 34% ramp reduction). Manager insights dashboard. Multi-persona scenarios. Real-time feedback flags mistakes. | Enterprise/desktop/web-chat-first, not voice-primary-mobile. B2B per-seat pricing. Not low-bandwidth. No consumer-apprentice framing. |
| Speak (speak.com) | Consumer language learning, voice-first. | Voice-primary interface, mobile-first, accent feedback, daily habit. | Language-learning, not job-skill apprenticeship. No role-play scenarios, no mastery gates for job outcomes. |
| Cartesia Line / Retell / Vapi | Voice-agent infrastructure platforms. | Best-in-class latency/quality stacks; validate that sub-600ms voice loops are production-feasible. | Infrastructure, not learning. No scenarios, no coaching, no mastery. Praxis builds on top of this category (or directly on Pipecat). |
| Duolingo voice features | Limited speech-recognition in a gamified language app. | Habit/engagement mechanics, mobile reach. | Voice is a side feature, not the interface. No conversational role-play. No job outcomes. |
| Gabby / other AI tutor startups | Various AI tutoring experiments. | Personalization, on-demand. | Most are text-first or video-first; few solve the latency/voice-primary loop well; high churn without job-outcome anchoring. |
Lessons for v0.1:
- Second Nature validates the Praxis thesis (role-play + coaching works, enterprises pay) — but Praxis's wedge is the opposite market (consumer/mobile/low-bandwidth/B2C-apprentice). Don't copy their enterprise desktop UX.
- Voice-primary + mobile + low-bandwidth is the defensible moat — none of the prior art optimizes for a $100 Android phone on 2G/3G (C-2). This is v0.1's architectural north star even though v0.1 itself is a Canada pilot on relaxed constraints.
- Job-outcome anchoring (REQ success metric: ≥25% report job/promotion) is what separates Praxis from language apps. The scenario must feel like the job.
- Coaching debrief is non-negotiable — Second Nature's real-time feedback and post-session coaching is the engagement/learning engine. D-011 includes it at a basic level; keep it.
LLM Orchestration Pattern Recommendation
Recommendation: Pipecat pipeline (ASR → LLM → TTS, streaming, with interruptibility)
Pattern:
Client (WebRTC audio)
→ Pipecat InputProcessor (VAD: Silero)
→ Deepgram STT (streaming partials)
→ FrameRouter (partial transcripts prime LLM context; final transcript triggers turn)
→ OllamaLLM (gemma4:cloud, stream=True, no local daemon — direct API)
→ Cartesia TTS (stream chunks as LLM tokens arrive)
→ OutputProcessor → WebRTC audio back to client
[Interrupt]: learner VAD fires during TTS → abort TTS + yield floor (D-008)
Why Pipecat (not custom, not Vocode):
- 13.8k stars, 11k+ commits, actively maintained (verified on GitHub). Vocode's
vocode-corelast updated Nov 2024 — stale. - Native integrations for Deepgram (STT), Cartesia/Piper/ElevenLabs (TTS), and Ollama (LLM) — all three v0.1 services are first-class. No glue code.
- Built-in VAD (Silero) and interruptibility (abort-and-yield semantics match D-008 out of the box).
- Pipecat Flows for structured/branching conversations — maps directly to the v0.1 scenario branch point (D-010).
- Client SDKs (React/RN/Swift/Kotlin) for the WebRTC transport.
- Python — matches the SQLite + scenario-YAML toolchain.
Latency optimization patterns to apply (from Pipecat/Voice-agent ecosystem conventions):
- Stream partial ASR → prime LLM — feed Deepgram partials into Ollama as user-context so the first LLM token fires ~immediately on final transcript.
- Stream LLM tokens → TTS chunked — don't wait for the full LLM response; Cartesia/Piper accept incremental text. First-audio fires on first sentence-boundary token.
- no-think mode for deepseek-v4-flash during debrief (avoids reasoning latency on the critical path).
- Short system prompts for the role-play fast path (gemma4:cloud); long context (256K/1M) is available but not used per-turn for latency.
- Measure, don't assume — Phase 1 must include a latency probe (per-segment timing) from day one.
Custom orchestration rejected for v0.1 — it would rebuild VAD, streaming frame routing, interruptibility, and transport abstractions that Pipecat already provides. Revisit only if Pipecat proves incompatible with a v0.1 requirement (flag as a risk).
Safety Baseline Guardrails (v0.1 Customer Service)
Customer Service is low-risk per PRD, but v0.1 ships a minimal guardrail layer (C-6, REQ-NFR-SAFE-01) that the architecture extends for later high-risk domains.
v0.1 guardrails list (concrete)
-
System-prompt constraints (role-play fast path,
gemma4:cloud):- "You are role-playing a customer service scenario. Stay in character."
- "Do not give legal, financial, or medical advice. If asked, say you cannot and redirect to the scenario."
- "Do not impersonate a real employee of any actual company. Use the fictional persona only."
- "Do not share personal data about real people."
- "Keep responses concise for voice (1-3 sentences)."
-
Debrief output filter (
deepseek-v4-flash:cloud):- Coaching text must be about the learner's performance, not advice about the customer's legal rights.
- Block any recommendation that the learner advise a real customer to take legal action.
-
Session-start disclaimer (TTS audio, first turn):
- "This is an AI practice session for training purposes. It is not a real conversation and no real company is involved."
-
No PII collection:
- Hardcoded learner profile (D-007). No name/email/phone collected. ASR transcripts are ephemeral-turn-logged but not associated with a real identity.
-
Architecture for later extension:
- Guardrail layer must be a pluggable interface (
Guardrail.check(text, context) -> verdict) so health/electrical domains (later milestones) can inject domain-specific rules without touching the pipeline. - v0.1 ships one implementation: the Customer Service ruleset above.
- Guardrail layer must be a pluggable interface (
-
No HITL in v0.1 (Customer Service is low-risk; HITL is for safety-sensitive domains per C-6, deferred).
Risks & Unknowns Remaining for PLAN Stage
| # | Risk / Unknown | Severity | Mitigation / PLAN action |
|---|---|---|---|
| R1 | Deepgram first-partial latency under Canadian network conditions unmeasured. Vendor claims ~200-300ms; real-world may differ. | High | Phase 1 day-1 spike: measure Deepgram partial latency from a Canada endpoint. If >300ms, evaluate Groq Whisper fallback. |
| R2 | Cartesia Sonic exact first-audio latency unmeasured. ~120ms is vendor/leaderboard claim. | High | Phase 1 spike: measure Cartesia first-audio from a sample LLM token stream. If >180ms, evaluate Piper fallback. |
| R3 | Ollama Cloud direct-API latency & rate limits unmeasured. gemma4:cloud first-token latency from ollama.com/api/chat is unknown; usage-tier throttling on Pro plan unknown. |
High | Phase 1 spike: measure TTFT for gemma4:cloud via direct API. If >250ms, consider local-Ollama-daemon mode on a pilot GPU with gemma4:e4b. |
| R4 | End-to-end <600ms may be infeasible with all-cloud (ASR+LLM+TTS each cloud-round-trip). Three cloud hops + WebRTC could exceed 600ms. | High | Budget the three network hops explicitly. If infeasible, move one component self-hosted (likely TTS→Piper on the pilot server, or LLM→local gemma4:e4b). |
| R5 | gemma4:cloud "Low Usage" tier may throttle under concurrent pilot sessions. |
Medium | v0.1 is single-learner; low risk. Log throttling events. For multi-learner, revisit plan tier. |
| R6 | Pipecat + Ollama direct-API integration depth unverified. Pipecat has an Ollama LLM service, but whether it supports the https://ollama.com direct host + bearer token cleanly needs a code check. |
Medium | Phase 1 task: verify Pipecat Ollama service accepts custom host + auth headers; if not, wrap with a thin adapter. |
| R7 | Scenario branch detection (how to classify learner signals into accept/escalate). The YAML schema declares learner_signals but the classifier is unspecified. |
Medium | v0.1: use an LLM-as-judge call (deepseek-v4-flash:cloud no-think) at turn boundaries to classify signals. Keep it offline from the voice loop (runs between turns or at session end). |
| R8 | Piper1-gpl maintainer gap. Open Home Foundation is seeking maintainers. | Low (v0.1 uses Cartesia) | Monitor; if Piper stagnates, evaluate Kokoro (also in Pipecat) for the open-weights fallback. |
| R9 | French-Canadian accent/code-switching in v0.1 English pilot. | Low (v0.1 English-only) | Log misheard turns; inform the later multilingual milestone (REQ-VOICE-05). |
| R10 | Ollama Cloud data residency. Hosted primarily US; Europe/Singapore routing possible. Canada pilot may raise PIPEDA considerations. | Low-Medium | Confirm Ollama's zero-data-retention policy covers pilot needs; if Canada data-residency is required, consider self-hosted gemma4:e4b + Piper for an all-Canada-region stack. |
Updated Architecture Recommendations (diff vs current ARCHITECTURE.md)
The current ARCHITECTURE.md is initial and lists 6 open questions. This research resolves them. Below is the diff to apply at PLAN (the orchestrator may commit an updated ARCHITECTURE.md).
Resolved open questions
| Open question in ARCHITECTURE.md | Resolution (from this research) |
|---|---|
| Client framework: native Android vs cross-platform vs web PWA? | Web (React + WebRTC) via Pipecat client SDK for v0.1; React Native for later Android. |
| Streaming transport: WebSocket vs WebRTC vs custom? | WebRTC primary (Pipecat transport); WebSocket dev fallback. |
| ASR/TTS provider: self-hosted (Whisper/Piper) vs cloud (Deepgram/PlayHT)? | Deepgram Nova-3 (cloud ASR) + Cartesia Sonic (cloud TTS) primary; Piper (self-hosted) open-weights TTS fallback. |
| Learner state store: SQLite vs Postgres for v0.1? | SQLite (confirmed). |
| Ollama deployment: self-hosted vs Ollama Cloud? | Ollama Cloud direct API (https://ollama.com/api/chat + OLLAMA_API_KEY) for v0.1; no local daemon. Self-host gemma4:e4b is the post-pilot cost-reduction path. |
| Scenario definition format: YAML/JSON DSL vs code-authored? | YAML DSL → Pydantic model, fed to Pipecat Flows. |
Updated v0.1 component map
Client: React + WebRTC (Pipecat client SDK)
│ audio in/out (WebRTC, UDP)
▼
Pipecat server (Python)
├─ VAD: Silero
├─ STT: Deepgram Nova-3 (cloud, streaming)
├─ LLM: Ollama Cloud direct API
│ ├─ gemma4:cloud (role-play fast path)
│ └─ deepseek-v4-flash:cloud (debrief, no-think)
├─ TTS: Cartesia Sonic (cloud) [Piper fallback behind interface]
├─ Scenario runtime: Pipecat Flows + YAML scenarios
├─ Guardrail layer: pluggable (v0.1: Customer Service ruleset)
└─ Learner state: SQLite (praxis.db)
Updated latency budget (revised with verified component choices)
| Segment | Budget | Source / note |
|---|---|---|
| Client capture + WebRTC uplink | ~50ms | WebRTC UDP, Canada region |
| ASR (Deepgram first partial) | ~250ms | Vendor claim; R1: measure |
| LLM first token (gemma4:cloud direct API) | ~200ms | R3: measure |
| TTS first audio (Cartesia Sonic) | ~120ms | Vendor/leaderboard; R2: measure |
| WebRTC downlink + playback | ~50ms | |
| Total (target) | ~670ms | ⚠️ Slightly over 600ms with all-cloud; R4 mitigation: move TTS to local Piper (~80ms) to bring total to ~550ms. |
Key architecture insight: the all-cloud three-hop path likely lands ~670ms, marginally over the 600ms target. The PLAN stage should design the TTS service behind an interface and pre-stage a Piper-on-pilot-server configuration as the likely production v0.1 choice, with Cartesia as the quality-benchmark option for non-latency-critical turns (e.g., the debrief). Alternatively, self-host gemma4:e4b for the LLM hop. This is the single biggest v0.1 technical risk and must be spiked in Phase 1 week 1.
Decisions recommended for the orchestrator to record
| ID | Decision | Confidence | Source |
|---|---|---|---|
| D-003 (update) | Confirm gemma4:cloud + deepseek-v4-flash:cloud via Ollama Cloud direct API |
0.95 | This research (catalog verified) |
| D-007 (update) | Confirm SQLite for v0.1 learner state | 0.90 | This research |
| D-013 (new) | ASR = Deepgram Nova-3 streaming (cloud) | 0.85 | This research |
| D-014 (new) | TTS = Cartesia Sonic (cloud) primary; Piper (self-hosted) fallback behind interface | 0.80 | This research |
| D-015 (new) | Client = React + WebRTC via Pipecat client SDK | 0.85 | This research |
| D-016 (new) | Transport = WebRTC (Pipecat); WebSocket dev fallback | 0.85 | This research |
| D-017 (new) | Orchestration = Pipecat (not custom, not Vocode) | 0.85 | This research |
| D-018 (new) | Scenario format = YAML DSL → Pydantic → Pipecat Flows | 0.85 | This research |
| D-019 (new) | v0.1 guardrail layer = pluggable interface; Customer Service ruleset implementation | 0.80 | This research |
| D-020 (new) | LLM access mode = Ollama Cloud direct API (no local daemon) for v0.1 | 0.85 | This research |
End of research findings. Next step: orchestrator reviews this document, records decisions D-013..D-020 (and updates D-003, D-007), updates ARCHITECTURE.md, and proceeds to the PLAN phase where R1-R4 latency spikes are the first Phase 1 tasks.