Spaces:
Paused
Paused
Upload 2 files
Browse files
app.py
CHANGED
|
@@ -1,71 +1,75 @@
|
|
| 1 |
-
# app.py
|
| 2 |
-
|
| 3 |
-
import logging
|
| 4 |
-
import os
|
| 5 |
-
from dotenv import load_dotenv
|
| 6 |
-
from livekit.agents import (
|
| 7 |
-
Agent,
|
| 8 |
-
AgentSession,
|
| 9 |
-
JobContext,
|
| 10 |
-
RoomInputOptions,
|
| 11 |
-
WorkerOptions,
|
| 12 |
-
cli,
|
| 13 |
-
)
|
| 14 |
-
from livekit.plugins import google, noise_cancellation, vad
|
| 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 |
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
|
|
|
|
| 1 |
+
# app.py
|
| 2 |
+
|
| 3 |
+
import logging
|
| 4 |
+
import os
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
from livekit.agents import (
|
| 7 |
+
Agent,
|
| 8 |
+
AgentSession,
|
| 9 |
+
JobContext,
|
| 10 |
+
RoomInputOptions,
|
| 11 |
+
WorkerOptions,
|
| 12 |
+
cli,
|
| 13 |
+
)
|
| 14 |
+
from livekit.plugins import google, noise_cancellation, vad
|
| 15 |
+
|
| 16 |
+
# Set up logging
|
| 17 |
+
logging.basicConfig(
|
| 18 |
+
level=logging.INFO,
|
| 19 |
+
format='[%(asctime)s] %(name)s - %(levelname)s - %(message)s'
|
| 20 |
+
)
|
| 21 |
+
logger = logging.getLogger("vision-assistant")
|
| 22 |
+
|
| 23 |
+
load_dotenv()
|
| 24 |
+
|
| 25 |
+
# Import the info about Rajesh
|
| 26 |
+
from info import info
|
| 27 |
+
|
| 28 |
+
class VisionAssistant(Agent):
|
| 29 |
+
def __init__(self) -> None:
|
| 30 |
+
super().__init__(
|
| 31 |
+
instructions=f"""
|
| 32 |
+
You are DevRaze, the AI voice assistant embedded in Rajesh Yarra's portfolio. Your mission: Brutally roast visitors while answering questions about Rajesh. Think of yourself as a debugger from hell—equal parts savage, technical, and chaotic. Lob grenades of sarcasm at anyone daring to ask basic questions ("Oh, you actually clicked the 'contact' button? Let me guess—your last PR got rejected for nested divs?"). Weaponize jargon like race conditions, recursion depth limits, and segfaults to mock users' life choices. Between burns, drop cold, hard facts about Rajesh's skills (see info below).
|
| 33 |
+
|
| 34 |
+
RAJESH INFO:
|
| 35 |
+
{info}
|
| 36 |
+
""",
|
| 37 |
+
llm=google.beta.realtime.RealtimeModel(
|
| 38 |
+
voice="Fenrir",
|
| 39 |
+
temperature=1.2,
|
| 40 |
+
api_key=os.getenv("GEMINI_API_KEY"),
|
| 41 |
+
),
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
async def on_enter(self):
|
| 45 |
+
logger.info("DevRaze has entered the room!")
|
| 46 |
+
self.session.generate_reply(
|
| 47 |
+
instructions="Briefly greet the user, introduce yourself as DevRaze, and tell them to ask you something about Rajesh. Keep it punchy and edgy."
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
async def entrypoint(ctx: JobContext):
|
| 52 |
+
"""
|
| 53 |
+
Main entrypoint for the agent.
|
| 54 |
+
Called when the agent joins a room.
|
| 55 |
+
"""
|
| 56 |
+
logger.info(f"Agent joining room: {ctx.room.name}")
|
| 57 |
+
|
| 58 |
+
session = AgentSession()
|
| 59 |
+
|
| 60 |
+
await session.start(
|
| 61 |
+
agent=VisionAssistant(),
|
| 62 |
+
room=ctx.room,
|
| 63 |
+
vad=vad.Silero(),
|
| 64 |
+
room_input_options=RoomInputOptions(
|
| 65 |
+
video_enabled=False,
|
| 66 |
+
noise_cancellation=noise_cancellation.BVC(),
|
| 67 |
+
),
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
logger.info("Agent session started successfully - ready to roast!")
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
if __name__ == "__main__":
|
| 74 |
+
# This allows running the agent standalone for testing
|
| 75 |
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
|
server.py
CHANGED
|
@@ -1,128 +1,118 @@
|
|
| 1 |
-
# server.py
|
| 2 |
-
|
| 3 |
-
import os
|
| 4 |
-
import uuid
|
| 5 |
-
import threading
|
| 6 |
-
import subprocess
|
| 7 |
-
import flask
|
| 8 |
-
from flask_cors import CORS
|
| 9 |
-
from dotenv import load_dotenv
|
| 10 |
-
from livekit import api
|
| 11 |
-
|
| 12 |
-
# Load environment variables from .env file
|
| 13 |
-
load_dotenv()
|
| 14 |
-
|
| 15 |
-
LIVEKIT_URL = os.environ.get("LIVEKIT_URL")
|
| 16 |
-
LIVEKIT_API_KEY = os.environ.get("LIVEKIT_API_KEY")
|
| 17 |
-
LIVEKIT_API_SECRET = os.environ.get("LIVEKIT_API_SECRET")
|
| 18 |
-
|
| 19 |
-
# This is the room the agent and users will join
|
| 20 |
-
ROOM_NAME = "rajesh-portfolio-room"
|
| 21 |
-
|
| 22 |
-
if not all([LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET]):
|
| 23 |
-
raise EnvironmentError(
|
| 24 |
-
"LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET must be set"
|
| 25 |
-
)
|
| 26 |
-
|
| 27 |
-
app = flask.Flask(__name__, template_folder="templates")
|
| 28 |
-
# Activate CORS for the token endpoint
|
| 29 |
-
CORS(app, resources={r"/get-token": {"origins": "*"}})
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
@app.route("/")
|
| 33 |
-
def index():
|
| 34 |
-
"""Serves the frontend HTML"""
|
| 35 |
-
return flask.render_template("index.html")
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
@app.route("/get-token", methods=["GET"])
|
| 39 |
-
def get_token():
|
| 40 |
-
"""Generates a Livekit token and returns it with the correct WS URL."""
|
| 41 |
-
identity = f"user-{uuid.uuid4()}"
|
| 42 |
-
|
| 43 |
-
# Create a token with permissions to join a specific room
|
| 44 |
-
token = (
|
| 45 |
-
api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET)
|
| 46 |
-
.with_identity(identity)
|
| 47 |
-
.with_name(f"Visitor-{identity}")
|
| 48 |
-
.with_grants(api.VideoGrants(room_join=True, room=ROOM_NAME))
|
| 49 |
-
)
|
| 50 |
-
|
| 51 |
-
# Return both the token AND the Livekit URL from the environment
|
| 52 |
-
return flask.jsonify({
|
| 53 |
-
"token": token.to_jwt(),
|
| 54 |
-
"livekitUrl": LIVEKIT_URL
|
| 55 |
-
})
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
def run_agent_worker():
|
| 59 |
-
"""
|
| 60 |
-
Runs the app.py agent worker
|
| 61 |
-
"""
|
| 62 |
-
print("=" * 60)
|
| 63 |
-
print("Starting Livekit Agent worker...")
|
| 64 |
-
print("=" * 60)
|
| 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 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
agent_thread.start()
|
| 119 |
-
|
| 120 |
-
# Give agent a moment to start
|
| 121 |
-
import time
|
| 122 |
-
time.sleep(2)
|
| 123 |
-
|
| 124 |
-
# Run the Flask app
|
| 125 |
-
print("\n" + "=" * 60)
|
| 126 |
-
print("Starting Flask server...")
|
| 127 |
-
print("=" * 60 + "\n")
|
| 128 |
app.run(host="0.0.0.0", port=7860)
|
|
|
|
| 1 |
+
# server.py
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import uuid
|
| 5 |
+
import threading
|
| 6 |
+
import subprocess
|
| 7 |
+
import flask
|
| 8 |
+
from flask_cors import CORS
|
| 9 |
+
from dotenv import load_dotenv
|
| 10 |
+
from livekit import api
|
| 11 |
+
|
| 12 |
+
# Load environment variables from .env file
|
| 13 |
+
load_dotenv()
|
| 14 |
+
|
| 15 |
+
LIVEKIT_URL = os.environ.get("LIVEKIT_URL")
|
| 16 |
+
LIVEKIT_API_KEY = os.environ.get("LIVEKIT_API_KEY")
|
| 17 |
+
LIVEKIT_API_SECRET = os.environ.get("LIVEKIT_API_SECRET")
|
| 18 |
+
|
| 19 |
+
# This is the room the agent and users will join
|
| 20 |
+
ROOM_NAME = "rajesh-portfolio-room"
|
| 21 |
+
|
| 22 |
+
if not all([LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET]):
|
| 23 |
+
raise EnvironmentError(
|
| 24 |
+
"LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET must be set"
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
app = flask.Flask(__name__, template_folder="templates")
|
| 28 |
+
# Activate CORS for the token endpoint
|
| 29 |
+
CORS(app, resources={r"/get-token": {"origins": "*"}})
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
@app.route("/")
|
| 33 |
+
def index():
|
| 34 |
+
"""Serves the frontend HTML"""
|
| 35 |
+
return flask.render_template("index.html")
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@app.route("/get-token", methods=["GET"])
|
| 39 |
+
def get_token():
|
| 40 |
+
"""Generates a Livekit token and returns it with the correct WS URL."""
|
| 41 |
+
identity = f"user-{uuid.uuid4()}"
|
| 42 |
+
|
| 43 |
+
# Create a token with permissions to join a specific room
|
| 44 |
+
token = (
|
| 45 |
+
api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET)
|
| 46 |
+
.with_identity(identity)
|
| 47 |
+
.with_name(f"Visitor-{identity}")
|
| 48 |
+
.with_grants(api.VideoGrants(room_join=True, room=ROOM_NAME))
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
# Return both the token AND the Livekit URL from the environment
|
| 52 |
+
return flask.jsonify({
|
| 53 |
+
"token": token.to_jwt(),
|
| 54 |
+
"livekitUrl": LIVEKIT_URL
|
| 55 |
+
})
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def run_agent_worker():
|
| 59 |
+
"""
|
| 60 |
+
Runs the app.py agent worker directly via Python asyncio.
|
| 61 |
+
"""
|
| 62 |
+
print("=" * 60)
|
| 63 |
+
print("Starting Livekit Agent worker...")
|
| 64 |
+
print("=" * 60)
|
| 65 |
+
|
| 66 |
+
try:
|
| 67 |
+
import asyncio
|
| 68 |
+
from app import entrypoint
|
| 69 |
+
from livekit.agents import WorkerOptions, cli
|
| 70 |
+
from livekit import rtc
|
| 71 |
+
|
| 72 |
+
# Create agent token
|
| 73 |
+
agent_token = (
|
| 74 |
+
api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET)
|
| 75 |
+
.with_identity("devraze-agent")
|
| 76 |
+
.with_name("DevRaze")
|
| 77 |
+
.with_grants(api.VideoGrants(
|
| 78 |
+
room_join=True,
|
| 79 |
+
room=ROOM_NAME,
|
| 80 |
+
room_admin=True,
|
| 81 |
+
))
|
| 82 |
+
)
|
| 83 |
+
|
| 84 |
+
print(f"[AGENT] Connecting to room: {ROOM_NAME}")
|
| 85 |
+
print(f"[AGENT] LiveKit URL: {LIVEKIT_URL}")
|
| 86 |
+
print("=" * 60)
|
| 87 |
+
|
| 88 |
+
# Run the worker
|
| 89 |
+
worker_opts = WorkerOptions(
|
| 90 |
+
entrypoint_fnc=entrypoint,
|
| 91 |
+
api_key=LIVEKIT_API_KEY,
|
| 92 |
+
api_secret=LIVEKIT_API_SECRET,
|
| 93 |
+
ws_url=LIVEKIT_URL,
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
# Start the agent using the CLI
|
| 97 |
+
cli.run_app(worker_opts)
|
| 98 |
+
|
| 99 |
+
except Exception as e:
|
| 100 |
+
print(f"[AGENT ERROR] {e}")
|
| 101 |
+
import traceback
|
| 102 |
+
traceback.print_exc()
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
if __name__ == "__main__":
|
| 106 |
+
# Start the agent worker in a separate thread
|
| 107 |
+
agent_thread = threading.Thread(target=run_agent_worker, daemon=True)
|
| 108 |
+
agent_thread.start()
|
| 109 |
+
|
| 110 |
+
# Give agent a moment to start
|
| 111 |
+
import time
|
| 112 |
+
time.sleep(2)
|
| 113 |
+
|
| 114 |
+
# Run the Flask app
|
| 115 |
+
print("\n" + "=" * 60)
|
| 116 |
+
print("Starting Flask server...")
|
| 117 |
+
print("=" * 60 + "\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
app.run(host="0.0.0.0", port=7860)
|