2026-02-16
Course: Human-AI Interaction β Willamette University
Format: Hands-on lab (CLI/IDE workflow), building directly on rasa_project_demo from Labs 1β2
Outcome: Build a working voice conversation and run a live barge-in demo
By the end of lab, you will:
browser_audioRasa Pro CALM is channel-agnostic: the same flows, slots, and patterns work for text and voice.
rest (JSON in/out)browser_audio (mic streaming + ASR + CALM + TTS)| Provider | ASR | TTS | Notes |
|---|---|---|---|
| Deepgram | β | β | Streaming both directions; simplest setup |
| Cartesia | β | β | Streaming TTS |
| Azure Speech | β | β | TTS does not support streaming |
| Rime | β | β | No streaming, 24kHz only |
This lab uses Deepgram for both ASR and TTS.
Voice exposes HAI concepts text chat hides:
Lab 3 focus: make these concepts concrete and testable in class.
Sign up at deepgram.com or console.deepgram.com/signup.
Tip: add this to .venv/bin/activate like your RASA_LICENSE.
browser_audio channel in credentials.ymlbrowser_audio:
server_url: localhost
interruptions:
enabled: false
min_words: 3
asr:
name: deepgram
tts:
name: deepgramenabled: allow mid-speech interruption (barge-in)min_words: minimum partial transcript words before interrupt triggersTwo flows:
domain.yml)room_type:
type: categorical
values:
- "quiet"
- "group"
- "media"
mappings:
- type: from_llm
room_status:
type: text
mappings:
- type: controlledroom_status is controlled because your custom action sets it (not user speech).
domain.yml)β οΈ Must be explicitly listed under top-level actions:
If omitted, youβll get: action used in flow but not listed in domain.
domain.yml)utter_library_hours:
- text: "The library is open Monday through Friday, 8am to midnight, and weekends 10am to 8pm."
utter_ask_room_type:
- text: "Would you like a quiet room, a group room, or a media room?"
utter_please_wait_room_check:
- text: "One moment, let me check that for you."
utter_room_availability_result:
- text: "Here's what I found: the {room_type} room is {room_status}."data/flows.yml)tell_library_hours:
description: User wants to know the library's opening hours.
steps:
- action: utter_library_hours
check_room_availability:
description: User wants to check whether a study room is available to book.
steps:
- collect: room_type
- action: utter_please_wait_room_check
- action: action_check_room_availability
- action: utter_room_availability_resultβ Key ordering: filler response β slow action β result.
actions/actions.py)class ActionCheckRoomAvailability(Action):
def name(self) -> Text:
return "action_check_room_availability"
def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict[Text, Any]]:
# Simulates a slow backend lookup.
time.sleep(3)
room_type = tracker.get_slot("room_type")
hardcoded_status = {
"quiet": "available now",
"group": "booked until 3pm",
"media": "available now",
}
room_status = hardcoded_status.get(room_type, "not found")
return [SlotSet("room_status", room_status)]Note: add import time if needed.
endpoints.yml already contains:
So actions run embedded in the assistant process.
No separate rasa run actions needed for this lab.
Before audio debugging, validate logic quickly via REST.
Try saying:
You should hear TTS playback of assistant replies.
Current config:
Assistant finishes speaking even if user talks over it.
Edit credentials.yml:
Restart rasa inspect, then interrupt mid-sentence with 3+ words
(e.g., βwait, stop, change it to groupβ).
min_words: 3 instead of 1?time.sleep(3), what is interruptible: speaking, thinking, or both?| Symptom | Likely cause | Fix |
|---|---|---|
| No microphone prompt | Browser/context issue | Use Chrome; localhost is secure origin |
| No transcript / hears nothing | DEEPGRAM_API_KEY missing in launch shell |
Re-export key or place in .venv/bin/activate |
credentials.yml edits ignored |
Server not restarted | Restart rasa inspect |
| Feedback loop | Mic picks up speaker output | Use headphones |
| Text works, voice fails | Channel config problem, not flow logic | Re-test over REST first, then voice config |
Replace hardcoded_status with a real API call
Compare Deepgram vs Cartesia TTS quality/latency
Explore telephony channels (Twilio/Jambonz) for production
Makes flows, slots, triggers, and branching explicit as text
Better for learning how CALM actually works under the hood
Strong foundation before moving to visual/no-code tooling
In this lab, we optimize for conceptual understanding, not just click-through completion.