From 8e1539c3600665c32dd8d3b7881857c9362a222a Mon Sep 17 00:00:00 2001 From: Jon Taylor Date: Wed, 3 Jul 2024 16:48:14 +0100 Subject: [PATCH 1/2] virtualized deployment and added room-based balancing --- examples/storytelling-chatbot/Dockerfile | 4 +- examples/storytelling-chatbot/README.md | 6 +- examples/storytelling-chatbot/env.example | 14 +- .../frontend/components/App.tsx | 25 +- .../components/DevicePicker/index.tsx | 10 +- .../frontend/components/Setup.tsx | 7 +- .../storytelling-chatbot/frontend/env.example | 1 - examples/storytelling-chatbot/src/bot.py | 13 +- .../storytelling-chatbot/src/bot_runner.py | 233 ++++++++++++++++++ examples/storytelling-chatbot/src/server.py | 175 ------------- 10 files changed, 277 insertions(+), 211 deletions(-) create mode 100644 examples/storytelling-chatbot/src/bot_runner.py delete mode 100644 examples/storytelling-chatbot/src/server.py diff --git a/examples/storytelling-chatbot/Dockerfile b/examples/storytelling-chatbot/Dockerfile index b84ba5431..5d762cd14 100644 --- a/examples/storytelling-chatbot/Dockerfile +++ b/examples/storytelling-chatbot/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-bullseye +FROM python:3.11-slim-bookworm ARG DEBIAN_FRONTEND=noninteractive ARG USE_PERSISTENT_DATA @@ -51,4 +51,4 @@ COPY --chown=user ./frontend/ frontend/ RUN cd frontend && npm install && npm run build # Start the FastAPI server -CMD python3 src/server.py --port ${FAST_API_PORT} \ No newline at end of file +CMD python3 src/bot_runner.py --port ${FAST_API_PORT} \ No newline at end of file diff --git a/examples/storytelling-chatbot/README.md b/examples/storytelling-chatbot/README.md index f3a23d305..b2c1e3d8a 100644 --- a/examples/storytelling-chatbot/README.md +++ b/examples/storytelling-chatbot/README.md @@ -48,6 +48,8 @@ pip install -r requirements.txt mv env.example .env ``` +When deploying to production, to ensure only this app can spawn a new bot, set your `ENV` to `production` + **Build the frontend:** This project uses a custom frontend, which needs to built. Note: this is done automatically as part of the Docker deployment. @@ -64,11 +66,11 @@ The build UI files can be found in `frontend/out` Start the API / bot manager: -`python src/server.py` +`python src/bot_runner.py` If you'd like to run a custom domain or port: -`python src/server.py --host somehost --p 7777` +`python src/bot_runner.py --host somehost --p someport` ➡️ Open the host URL in your browser `http://localhost:7860` diff --git a/examples/storytelling-chatbot/env.example b/examples/storytelling-chatbot/env.example index 56b121a4d..7060aef52 100644 --- a/examples/storytelling-chatbot/env.example +++ b/examples/storytelling-chatbot/env.example @@ -1,5 +1,9 @@ -DAILY_API_KEY=7df... -ELEVENLABS_API_KEY=aeb... -ELEVENLABS_VOICE_ID=7S... -FAL_KEY=8c... -OPENAI_API_KEY=sk-PL... +DAILY_API_KEY= +DAILY_SAMPLE_ROOM_URL= +ELEVENLABS_API_KEY= +ELEVENLABS_VOICE_ID= +FAL_KEY= +OPENAI_API_KEY= + +ENV= # dev | production +RUN_AS_VM= # Set this if you want to run bots on process (not launch a new VM) \ No newline at end of file diff --git a/examples/storytelling-chatbot/frontend/components/App.tsx b/examples/storytelling-chatbot/frontend/components/App.tsx index 761787c88..73ad50a97 100644 --- a/examples/storytelling-chatbot/frontend/components/App.tsx +++ b/examples/storytelling-chatbot/frontend/components/App.tsx @@ -27,14 +27,11 @@ export default function Call() { // Create a new room for the story session try { - const response = await fetch("/create", { + const response = await fetch("/start_bot", { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - room_url: process.env.NEXT_PUBLIC_ROOM_URL || null, - }), }); const { room_url, token } = await response.json(); @@ -55,21 +52,9 @@ export default function Call() { // Disable local audio, the bot will say hello first daily.setLocalAudio(false); - // Start the bot - const resp = await fetch("/start", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - room_url, - }), - }); - setState("started"); } catch (error) { setState("error"); - leave(); } } @@ -79,7 +64,13 @@ export default function Call() { } if (state === "error") { - return
An Error occured
; + return ( +
+

+ This demo is currently at capacity. Please try again later. +

+
+ ); } if (state === "started") { diff --git a/examples/storytelling-chatbot/frontend/components/DevicePicker/index.tsx b/examples/storytelling-chatbot/frontend/components/DevicePicker/index.tsx index 6cc69796d..cdbc21c5b 100644 --- a/examples/storytelling-chatbot/frontend/components/DevicePicker/index.tsx +++ b/examples/storytelling-chatbot/frontend/components/DevicePicker/index.tsx @@ -108,26 +108,26 @@ export default function DevicePicker({}: Props) { {hasMicError && (
{micState === "blocked" ? ( -

+

Please check your browser and system permissions. Make sure that this app is allowed to access your microphone.

) : micState === "in-use" ? ( -

+

Your microphone is being used by another app. Please close any other apps using your microphone and restart this app.

) : micState === "not-found" ? ( -

+

No microphone seems to be connected. Please connect a microphone.

) : micState === "not-supported" ? ( -

+

This app is not supported on your device. Please update your software or use a different device.

) : ( -

+

There seems to be an issue accessing your microphone. Try restarting the app or consult a system administrator.

diff --git a/examples/storytelling-chatbot/frontend/components/Setup.tsx b/examples/storytelling-chatbot/frontend/components/Setup.tsx index 42781e87e..4b6c35ea6 100644 --- a/examples/storytelling-chatbot/frontend/components/Setup.tsx +++ b/examples/storytelling-chatbot/frontend/components/Setup.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Button } from "@/components/ui/button"; import DevicePicker from "@/components/DevicePicker"; -import { IconEar, IconLoader2 } from "@tabler/icons-react"; +import { IconAlertCircle, IconEar, IconLoader2 } from "@tabler/icons-react"; type SetupProps = { handleStart: () => void; @@ -24,7 +24,6 @@ export const Setup: React.FC = ({ handleStart }) => {

Welcome to Storytime

- {state === "intro" ? ( <>

@@ -38,6 +37,9 @@ export const Setup: React.FC = ({ handleStart }) => { For best results, try in a quiet environment!

+

+ This demo expires after 5 minutes. +

) : ( <> @@ -49,7 +51,6 @@ export const Setup: React.FC = ({ handleStart }) => { )} -