smart-advisor / docs /PROJECT_FLOW.md
sajaahmed5
Deploy
35769d4
|
Raw
History Blame Contribute Delete
3.39 kB

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.ipynb top 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.txt and set the env vars described in src/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.