Skip to content

Commit

Permalink
Add a podcastai bot
Browse files Browse the repository at this point in the history
  • Loading branch information
afzal442 committed Oct 20, 2024
1 parent ee5ae0d commit ee0a0db
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 0 deletions.
24 changes: 24 additions & 0 deletions examples/podcast-chatbot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# podcastai

### Have a conversation about any article on the web

podcastai is a fast conversational AI built using [Daily](https://www.daily.co/) for real-time media transport and [Cartesia](https://cartesia.ai) for text-to-speech. Everything is orchestrated together (VAD -> STT -> LLM -> TTS) using [Pipecat](https://www.pipecat.ai/).

## Get started

```python
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

cp env.example .env # and add your credentials

```

## Run the bot

```bash
python bot.py
```

While the app is running, go to the `https://<yourdomain>.daily.co/<room_url>` set in `DAILY_SAMPLE_ROOM_URL` and talk to studypal!
98 changes: 98 additions & 0 deletions examples/podcast-chatbot/bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import aiohttp
import asyncio
import os
import sys
from loguru import logger
from dotenv import load_dotenv

from pipecat.vad.silero import SileroVADAnalyzer
from pipecat.frames.frames import LLMMessagesFrame
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.services.cartesia import CartesiaTTSService
from pipecat.services.openai import OpenAILLMService
from pipecat.transports.services.daily import DailyParams, DailyTransport

from runner import configure

load_dotenv(override=True)

# Run this script directly from your command line.
# This project was adapted from
# https://github.com/pipecat-ai/pipecat/blob/main/examples/foundational/07d-interruptible-cartesia.py

logger.remove(0)
logger.add(sys.stderr, level="DEBUG")


# This is the main function that handles STT -> LLM -> TTS


async def main():
async with aiohttp.ClientSession() as session:
(room_url, token) = await configure(session)

transport = DailyTransport(
room_url,
token,
"Tech Podcast",
DailyParams(
audio_out_sample_rate=44100,
audio_out_enabled=True,
transcription_enabled=True,
vad_enabled=True,
vad_analyzer=SileroVADAnalyzer(),
),
)

tts = CartesiaTTSService(
api_key=os.getenv("CARTESIA_API_KEY"),
voice_id=os.getenv("CARTESIA_VOICE_ID", "4d2fd738-3b3d-4368-957a-bb4805275bd9"), # British Narration Lady
sample_rate=44100,
)

llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4")

messages = [
{
"role": "system",
"content": "You are Keith, the podcast host. You will engage with the participants by asking about tech topics, keeping responses short, clear, and conversational."
}
]

context = OpenAILLMContext(messages)
context_aggregator = llm.create_context_aggregator(context)

pipeline = Pipeline(
[
transport.input(),
context_aggregator.user(),
llm,
tts,
transport.output(),
context_aggregator.assistant(),
]
)

task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True, enable_metrics=True))

@transport.event_handler("on_first_participant_joined")
async def on_first_participant_joined(transport, participant):
transport.capture_participant_transcription(participant["id"])
messages.append(
{
"role": "system",
"content": "Hey, You are Keith. Start introducing yourself and welcoming participants to the tech podcast! Ask them `What topic are you interested in today?`",
}
)
await task.queue_frames([LLMMessagesFrame(messages)])

runner = PipelineRunner()

await runner.run(task)


if __name__ == "__main__":
asyncio.run(main())
5 changes: 5 additions & 0 deletions examples/podcast-chatbot/env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DAILY_SAMPLE_ROOM_URL= # Follow instructions here and put your https://YOURDOMAIN.daily.co/YOURROOM (Instructions: https://docs.pipecat.ai/quickstart#preparing-your-environment)
DAILY_API_KEY= # Create here: https://dashboard.daily.co/developers
OPENAI_API_KEY= # Create here: https://platform.openai.com/docs/overview
CARTESIA_API_KEY= # Create here: https://play.cartesia.ai/console
CARTESIA_VOICE_ID= # Find here: https://play.cartesia.ai/
4 changes: 4 additions & 0 deletions examples/podcast-chatbot/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pypdf==4.3.1
loguru
pipecat-ai[daily,cartesia,openai,silero]==0.0.40
python-dotenv==1.0.1
62 changes: 62 additions & 0 deletions examples/podcast-chatbot/runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#
# Copyright (c) 2024, Daily
#
# SPDX-License-Identifier: BSD 2-Clause License
#

import aiohttp
import argparse
import os

from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper


async def configure(aiohttp_session: aiohttp.ClientSession):
(url, token, _) = await configure_with_args(aiohttp_session)
return (url, token)


async def configure_with_args(
aiohttp_session: aiohttp.ClientSession, parser: argparse.ArgumentParser | None = None
):
if not parser:
parser = argparse.ArgumentParser(description="Daily AI SDK Bot Sample")
parser.add_argument(
"-u", "--url", type=str, required=False, help="URL of the Daily room to join"
)
parser.add_argument(
"-k",
"--apikey",
type=str,
required=False,
help="Daily API Key (needed to create an owner token for the room)",
)

args, unknown = parser.parse_known_args()

url = args.url or os.getenv("DAILY_SAMPLE_ROOM_URL")
key = args.apikey or os.getenv("DAILY_API_KEY")

if not url:
raise Exception(
"No Daily room specified. use the -u/--url option from the command line, or set DAILY_SAMPLE_ROOM_URL in your environment to specify a Daily room URL."
)

if not key:
raise Exception(
"No Daily API key specified. use the -k/--apikey option from the command line, or set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers."
)

daily_rest_helper = DailyRESTHelper(
daily_api_key=key,
daily_api_url=os.getenv("DAILY_API_URL", "https://api.daily.co/v1"),
aiohttp_session=aiohttp_session,
)

# Create a meeting token for the given room with an expiration 1 hour in
# the future.
expiry_time: float = 60 * 60

token = await daily_rest_helper.get_token(url, expiry_time)

return (url, token, args)

0 comments on commit ee0a0db

Please sign in to comment.