Spaces:
Running
Running
Project Flow โ How Smart Advisor Fits Together
A 5-minute map for the team. Not deeply technical โ just "who does what, and where does my part plug in." For the deep-dive details, see the links at the bottom.
What Smart Advisor does
A student asks an academic question โ by voice or by typing, in Arabic โ and gets back an answer grounded in official UCAS documents, spoken back to them (or shown as text). No hallucinated answers: if the system isn't confident, it says so instead of guessing.
The end-to-end flow
flowchart LR
S(["๐๏ธ Student asks a question"]) --> UI1["๐ฅ๏ธ UI โ Shahd\nrecords the audio"]
UI1 --> STT["๐ง Voice (STT) โ Saja\ntranscribe_audio(audio)"]
STT -->|MSA question text| RAG["๐ง RAG โ Fatema\nretrieve + generate the answer"]
RAG -->|MSA answer text| TTS["๐ Voice (TTS) โ Saja\nsynthesize_speech(text)"]
TTS --> UI2["๐ฅ๏ธ UI โ Shahd\nplays the spoken answer"]
UI2 --> E(["โ
Student hears/reads the answer"])
The UI wraps the whole loop โ it captures the recording at the start and plays the result at the end. Everything in between is one pillar handing a plain value to the next: audio โ text โ answer text โ audio.
How the pieces connect
The voice layer is exactly two functions.
from voice import transcribe_audio, synthesize_speech, VoiceError
def voice_loop(audio):
try:
question = transcribe_audio(audio).text # <- Voice: speech to text
except VoiceError:
return None, "ูู
ุฃููู
ู
ุง ููุชูุ ู
ู ูุถูู ุญุงูู ู
ุฑุฉ ุฃุฎุฑู." # "I didn't catch that"
# <<< Fatema's RAG pipeline plugs in right here >>>
answer_text = fatema_rag_pipeline(question)
try:
speech = synthesize_speech(answer_text) # <- Voice: text to speech
return speech.audio_path, answer_text
except VoiceError:
return None, answer_text # still show the text even if TTS failed
Mock mode vs real mode
- Build against mock mode โ it's the default, needs zero setup (no models, no GPU, no API key), and returns realistic-shaped fake data instantly. This is what you should develop and test against day to day.
- Flip one env var for real audio:
VOICE_BACKEND=real. The exact same code runs โ same two functions, same return fields, same exceptions โ just with real Whisper transcription and real spoken audio (Azure or offline Piper) instead of placeholders. - The voice models are done and real mode works today. You don't need to wait for anything โ build against mock now, flip the switch whenever you want to hear it for real.
Getting started for teammates
- Clone the repo
- Nothing to install for mock mode โ
from voice import ...just works - Open and run
docs/voice_usage_guide.ipynbtop to bottom - In your own code:
from voice import transcribe_audio, synthesize_speech, VoiceError - Wrap every call in
try/except VoiceError - Only if you need real audio:
pip install -r requirements-voice.txtand set the env vars described insrc/voice/CONTRACT.md
Want more detail?
docs/voice_usage_guide.ipynbโ a runnable, teaching notebook: the same examples above, plus async variants and picking a male/female voice.