diff --git a/README.md b/README.md index bc585fa3a..4dd3af33f 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,82 @@ -# Daily AI SDK +# dailyai — an open source framework for real-time, multi-modal, conversational AI applications -Build conversational, multi-modal AI apps with real-time voice and video, like this: +Build things like this: -_Demo Video to come_ +[![AI-powered voice patient intake for healthcare](https://img.youtube.com/vi/lDevgsp9vn0/0.jpg)](https://www.youtube.com/watch?v=lDevgsp9vn0) -With built-in support for many of the best AI platforms (or [add your own](/docs)): -- Azure - DALL-E, ChatGPT, and Azure AI Text-to-Speech -- Deepgram - Speech-to-text, and Aura text-to-speech -- Eleven Labs text-to-speech -- Fal.ai image generation -- OpenAI DALL-E and ChatGPT -- Whisper local speech-to-text -## Step 1: Get Started -## Build/Install +**`dailyai` started as a toolkit for implementing generative AI voice bots.** Things like personal coaches, meeting assistants, story-telling toys for kids, customer support bots, and snarky social companions. + + +In 2023 a *lot* of us got excited about the possibility of having open-ended conversations with LLMs. It became clear pretty quickly that we were all solving the same [low-level problems](https://www.daily.co/blog/how-to-talk-to-an-llm-with-your-voice/): +- low-latency, reliable audio transport +- echo cancellation +- phrase endpointing (knowing when the bot should respond to human speech) +- interruptibility +- writing clean code to stream data through "pipelines" of speech-to-text, LLM inference, and text-to-speech models + +As our applications expanded to include additional things like image generation, function calling, and vision models, we started to think about what a complete framework for these kinds of apps could look like. + +Today, `dailyai` is: + +1. a set of code building blocks for interacting with generative AI services and creating low-latency, interruptible data pipelines that use multiple services +2. transport services that moves audio, video, and events across the Internet +3. implementations of specific generative AI services + +Currently implemented services: +- Speech-to-text + - Deepgram + - Whisper +- LLMs + - Azure + - OpenAI +- Image generation + - Azure + - Fal + - OpenAI +- Text-to-speech + - Azure + - Deepgram + - ElevenLabs +- Transport + - Daily + - Local (in progress, intended as a quick start example service) + +If you'd like to [implement a service]((https://github.com/daily-co/daily-ai-sdk/tree/main/src/dailyai/services)), we welcome PRs! Our goal is to support lots of services in all of the above categories, plus new categories (like real-time video) as they emerge. + +## Step 1: Get started + +Today, the easiest way to get started with `dailyai` is to use [Daily](https://www.daily.co/) as your transport service. This toolkit started life as an internal SDK at Daily and millions of minutes of AI conversation have been served using it and its earlier prototype incarnations. (The [transport base class](https://github.com/daily-co/daily-ai-sdk/blob/main/src/dailyai/services/base_transport_service.py) is easy to extend, though, so feel free to submit PRs if you'd like to implement another transport service.) + +``` +# install the module +pip install dailyai + +# set up an .env file with API keys +# for example +OPENAI_API_KEY=... +ELEVENLABS_API_KEY=... +ELEVENLABS_VOICE_ID=... +DAILY_SAMPLE_ROOM_URL=https://... + +# sign up for a free Daily account, if you don't already have one, and +# join the Daily room URL directly from a browser tab, then run one of the +# samples +python src/examples/foundational/02-llm-say-one-thing.py +``` + +## Code examples + +There are two directories of examples: + +- [foundational](https://github.com/daily-co/daily-ai-sdk/tree/main/src/examples/foundational) — demos that build on each other, introducing one or two concepts at a time +- [starter apps](https://github.com/daily-co/daily-ai-sdk/tree/main/src/examples/starter-apps) — complete applications that you can use as starting points for development + + + +## Hacking on the framework itself _Note that you may need to set up a virtual environment before following the instructions below. For instance, you might need to run the following from the root of the repo:_ @@ -43,117 +104,3 @@ If you want to use this package from another directory, you can run: pip install path_to_this_repo ``` -## Running the samples - -Tou can run the simple sample like so: - -``` -python src/examples/theoretical-to-real/01-say-one-thing.py -u -k -``` -## Overview - -The Daily AI SDK allows you to build applications that can participate in WebRTC sessions and interact with AI Services. Some examples of what you can build with this: - -- conversational bots that interact 1:1 with a user, using voice recognition and text-to-speech -- assistant bots that aggregate transcriptions from multiple participants in a meeting and provide realtime summaries or other AI-generated output. -- image-recognition bots -- etc - -## Concepts - -### Transport Service - -The SDK provides one “transport service”, which is a wrapper around Daily’s `daily-python` client (tk add link). You can use this service to listen for events related to a WebRTC session, such as “a participant joined the meeting”. -The transport service also exposes a send queue, and a receive queue. You can use the send queue to send audio and video to the WebRTC session, and you can listen to the receive queue to see audio, video and transcription data from the WebRTC session. - -### AI Services - -The AI Service classes provide wrappers around various AI providers, and allow you to query LLMs, convert text to speech and make images from text. The audio and images can then be placed on the transport service’s send queue, where they’ll be sent to the WebRTC session. - -### Queue Frames - -Communication between the transport service and AI services, and between various AI services, takes place in Queue Frames. These frames contain an indication of the type of data as well as the data itself. - -## Using Transports, AI Services and Frames - -AI Services all define a `.run` method. This method consumes and generates `QueueFrame` frames. The kind of frames that can be consumed and generated depend on the kind of service. For instance, an LLM AI Service consumes `LLM_MESSAGE` frames (which define a history of interaction with an LLM) and emit `TEXT` frames (the response from the LLM). - -The `.run` method is an `AsyncIterable`, and it takes an `iterable`, `AsyncIterable` or `asyncio.Queue` that produces QueueFrames as a parameter. This makes it easy to chain AI Services, and consume input from the Transport’s `receive_queue` . - -AI Services also have a `.run_to_queue` method. This method is not an AsyncIterable, but instead sends processed QueueFrames to a queue. This makes it easy to send the output of an AI Service to the Transport’s `send_queue`. - -AI Services also define convenience functions that let you bypass creating QueueFrames for some simple cases (eg. using the TTS service to convert a string to audio output and send that audio to the transport’s `send_queue`). See below for examples. - -## Examples - -### Say Something - -The base TTS AI service exposes a `.say` method. After creating a transport and TTS service, you can use this method like so: - -``` -transport = DailyTransportService(...) -tts = AzureTTSService() -await tts.say("hello world", transport.send_queue) -``` - -This will call the TTS service to render the text to audio frames, then put the audio frames on the transport’s send queue. The transport will then send those frames along to the WebRTC session. - -### Speak an LLM response - -Given a system prompt contained in a `messages` array, you can emit the LLM’s response as audio with a chain like this: - -``` -transport = DailyTransportService(...) # setup parameters omitted -tts = AzureTTSService() -llm = AzureLLMService() -messages = [...] # system prompt omitted for brevity - -await tts.run_to_queue( - transport.send_queue, - llm.run([QueueFrame.LLM_MESSAGES, messages]) -) -``` - -In this code, the LLM service object sends the messages to Azure’s OpenAI implementation, which streams chunks back asynchronously. Those chunks are aggregated by the TTS Service to ensure the best audio response (TTS works best when it gets complete sentence, so it can inflect correctly), then sent to Azure’s TTS service, converted to audio frames, and sent to the WebRTC session via the Daily transport. - -### Pre-cache an LLM response - -Sometimes LLMs can be slower than we’d like for natural-feeling communication. Here’s an example where we take advantage of the time it takes to speak some pre-defined text to get a head start on the LLM response: - -(TK link to 04- sample) - -In this sample, we set up a buffer queue to receive the audio frames from the LLM response before while we are joining the call and start an asynchronous task to start filling this buffer: - -``` - buffer_queue = asyncio.Queue() - llm_response_task = asyncio.create_task( - elevenlabs_tts.run_to_queue( - buffer_queue, - llm.run([QueueFrame(FrameType.LLM_MESSAGE, messages)]), - True, - ) - ) -``` - -Then, when we’ve joined the call, we speak the static text: - -``` - await azure_tts.say("My friend...", transport.send_queue) -``` - -As that text is being spoken, the asynchronous LLM task continues in the background. When the text is done, we pull the frames off the buffer queue and put them in the transport’s `send_queue`: - -``` - async def buffer_to_send_queue(): - while True: - frame = await buffer_queue.get() - await transport.send_queue.put(frame) - buffer_queue.task_done() - if frame.frame_type == FrameType.END_STREAM: - break - - await asyncio.gather(llm_response_task, buffer_to_send_queue()) - -``` - -One thing to note here is the last parameter to `run_to_queue` in the first code clause above: this causes the `run_to_queue` method to send an `END_STREAM` frame when it’s done rendering. This lets us know when to stop our `buffer_to_send_queue` task above.