Repository navigation
Expand file tree
/
Copy pathrag.py
More file actions
112 lines (91 loc) · 5.59 KB
/
Copy pathrag.py
File metadata and controls
112 lines (91 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import asyncio
from videosdk.agents import Agent, AgentSession, Pipeline, WorkerJob, JobContext, RoomOptions
from videosdk.plugins.openai import OpenAILLM
from videosdk.plugins.deepgram import DeepgramSTT
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import TurnDetector, pre_download_model
from videosdk.plugins.elevenlabs import ElevenLabsTTS
from openai import AsyncOpenAI
import chromadb
import numpy as np
import os
pre_download_model()
class VoiceAgent(Agent):
def __init__(self):
super().__init__(
instructions="You are a helpful voice assistant that answers questions based on provided context. Use the retrieved documents to ground your answers. If no relevant context is found, say so."
)
# Initialize OpenAI client for embeddings
self.openai_client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# FAQ documents from VideoSDK Integration FAQ
self.documents = [
"What is VideoSDK? VideoSDK is a comprehensive video calling and live streaming platform supporting Web (JavaScript), Mobile (React Native, Flutter, Android, iOS), and Server-side REST APIs.",
"How do I authenticate with VideoSDK? Use JWT tokens generated with your API key and secret from the VideoSDK dashboard, including permissions and expiration time.",
"How do I create a video meeting room? Call the VideoSDK REST API or use VideoSDK.createMeeting() to generate a meeting ID for participants to join.",
"How do I implement screen sharing in VideoSDK? Use enableScreenShare() to start and disableScreenShare() to stop, listening to screen-share-started and screen-share-stopped events.",
"How do I record video meetings? Start recording with startRecording(), configure mode (video-and-audio or audio-only) and quality, and stop with stopRecording().",
"Can I live stream VideoSDK meetings to social media? Yes, use startLivestream() with RTMP URLs for platforms like YouTube or Facebook, supporting multiple platforms simultaneously."
]
"""
List[str]: The ultimate guidebook for our VideoSDK integration guru! This collection of FAQ entries powers the RAG pipeline, embedding VideoSDK's integration secrets into vectors via OpenAI's `text-embedding-ada-002` and storing them in Chroma DB's digital vault. From creating meetings to live streaming, these nuggets of wisdom enable the assistant to deliver precise answers, transcribed by Deepgram's audio wizardry and voiced through ElevenLabs' sonic brilliance. Swap with your own VideoSDK FAQs or expand with custom docs to make this assistant the go-to expert for video integration queries!
"""
# Set up Chroma DB
self.chroma_client = chromadb.Client() # In-memory client; use PersistentClient for disk storage
self.collection = self.chroma_client.create_collection(name="videosdk_faq_collection")
# Generate embeddings and add to Chroma
embeddings = [self._get_embedding_sync(doc) for doc in self.documents]
self.collection.add(
documents=self.documents,
embeddings=embeddings,
ids=[f"doc_{i}" for i in range(len(self.documents))]
)
def _get_embedding_sync(self, text: str) -> np.ndarray:
"""Synchronous embedding for initialization (since __init__ can't be async)."""
import openai # Use sync client for init
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
response = client.embeddings.create(input=text, model="text-embedding-ada-002")
return response.data[0].embedding
async def get_embedding(self, text: str) -> np.ndarray:
"""Async embedding for queries."""
response = await self.openai_client.embeddings.create(input=text, model="text-embedding-ada-002")
return response.data[0].embedding
async def retrieve(self, query: str, k: int = 2) -> list[str]:
"""Retrieve top-k documents from Chroma DB."""
query_emb = await self.get_embedding(query)
results = self.collection.query(
query_embeddings=[query_emb],
n_results=k
)
return results["documents"][0] # List of matching documents
async def on_enter(self) -> None:
await self.session.say("Hello, how can I help you today?")
async def on_exit(self) -> None:
await self.session.say("Goodbye!")
async def entrypoint(ctx: JobContext):
agent = VoiceAgent()
pipeline = Pipeline(
stt=DeepgramSTT(),
llm=OpenAILLM(),
tts=ElevenLabsTTS(),
vad=SileroVAD(),
turn_detector=TurnDetector()
)
# Pipeline hook: retrieve relevant documents at the start of each user turn
# and inject them into the agent's context before the LLM responds
@pipeline.on("user_turn_start")
async def on_user_turn_start(transcript: str):
context_docs = await agent.retrieve(transcript)
if context_docs:
context_str = "\n\n".join(f"Document {i + 1}: {doc}" for i, doc in enumerate(context_docs))
agent.chat_context.add_message(
role="system",
content=f"Retrieved Context:\n{context_str}\n\nUse this context to answer the user's question."
)
session = AgentSession(agent=agent, pipeline=pipeline)
await session.start(wait_for_participant=True, run_until_shutdown=True)
def make_context() -> JobContext:
room_options = RoomOptions(name="Agent", playground=True)
return JobContext(room_options=room_options)
if __name__ == "__main__":
job = WorkerJob(entrypoint=entrypoint, jobctx=make_context)
job.start()