diff --git a/OS/01/.env.example b/OS/01/.env.example index 06aa136..1c39a75 100644 --- a/OS/01/.env.example +++ b/OS/01/.env.example @@ -7,6 +7,10 @@ ALL_LOCAL=False # WHISPER_MODEL_PATH=... # OPENAI_API_KEY=sk-... +# Whisper Model (if using local model) +WHISPER_MODEL_NAME="ggml-tiny.en.bin" +WHISPER_MODEL_URL="https://huggingface.co/ggerganov/whisper.cpp/resolve/main/" + # Expose through Ngrok # Uncomment following line with your Ngrok auth token (https://dashboard.ngrok.com/get-started/your-authtoken) # export NGROK_AUTHTOKEN="AUTH_TOKEN" diff --git a/OS/01/device.py b/OS/01/device.py index b0079c4..eed28e3 100644 --- a/OS/01/device.py +++ b/OS/01/device.py @@ -9,19 +9,21 @@ from starlette.websockets import WebSocket from queue import Queue from pynput import keyboard import json +import traceback import websockets import queue +import pydub import ast from pydub import AudioSegment from pydub.playback import play import io +import time import wave import tempfile from datetime import datetime from interpreter import interpreter # Just for code execution. Maybe we should let people do from interpreter.computer import run? from utils.kernel import put_kernel_messages_into_queue from stt import stt_wav -import asyncio from utils.logs import setup_logging from utils.logs import logger @@ -35,6 +37,10 @@ RATE = 44100 # Sample rate RECORDING = False # Flag to control recording state SPACEBAR_PRESSED = False # Flag to track spacebar press state +# Configuration for WebSocket +WS_URL = os.getenv('SERVER_URL') +if not WS_URL: + raise ValueError("The environment variable SERVER_URL is not set. Please set it to proceed.") # Initialize PyAudio p = pyaudio.PyAudio() @@ -124,6 +130,7 @@ def on_release(key): logger.info("Exiting...") os._exit(0) +import asyncio send_queue = queue.Queue() @@ -136,12 +143,8 @@ async def message_sender(websocket): async def websocket_communication(WS_URL): while True: try: - logger.info(f"Connecting to `{WS_URL}` ...") - - headers = {"ngrok-skip-browser-warning": str(80), "User-Agent": "project01"} if os.getenv('NGROK_AUTHTOKEN') else {} - async with websockets.connect(WS_URL, extra_headers=headers) as websocket: + async with websockets.connect(WS_URL) as websocket: logger.info("Press the spacebar to start/stop recording. Press ESC to exit.") - asyncio.create_task(message_sender(websocket)) initial_message = {"role": None, "type": None, "format": None, "content": None} @@ -195,12 +198,7 @@ async def websocket_communication(WS_URL): if __name__ == "__main__": - # Configuration for WebSocket async def main(): - WS_URL = os.getenv('SERVER_CONNECTION_URL') - if not WS_URL: - raise ValueError("The environment variable SERVER_URL is not set. Please set it to proceed.") - # Start the WebSocket communication asyncio.create_task(websocket_communication(WS_URL)) diff --git a/OS/01/requirements.txt b/OS/01/requirements.txt index 08d5d35..6e70eb4 100644 --- a/OS/01/requirements.txt +++ b/OS/01/requirements.txt @@ -1,16 +1,12 @@ git+https://github.com/KillianLucas/open-interpreter.git -asyncio==3.4.3 -PyAudio==0.2.14 -pynput==1.7.6 -fastapi==0.109.2 -uvicorn==0.27.1 -websockets==12.0 -playsound==1.3.0 -python-dotenv==1.0.1 -ffmpeg-python==0.2.0 -textual==0.50.1 -pydub==0.25.1 -ngrok==1.0.0 -wheel - - +asyncio +PyAudio +pynput +fastapi +uvicorn +websockets +playsound +python-dotenv +ffmpeg-python +textual +pydub \ No newline at end of file diff --git a/OS/01/server.py b/OS/01/server.py index 0d04a72..cc6cbc9 100644 --- a/OS/01/server.py +++ b/OS/01/server.py @@ -4,12 +4,17 @@ load_dotenv() # take environment variables from .env. from starlette.websockets import WebSocketDisconnect import ast import json +import time import queue import os import traceback +from queue import Queue +from threading import Thread +import threading +import uvicorn import re from fastapi import FastAPI -from fastapi.responses import PlainTextResponse +from threading import Thread from starlette.websockets import WebSocket from stt import stt_bytes from tts import tts @@ -19,8 +24,6 @@ import urllib.parse from utils.kernel import put_kernel_messages_into_queue from i import configure_interpreter from interpreter import interpreter -import ngrok -import signal from utils.logs import setup_logging from utils.logs import logger @@ -90,10 +93,6 @@ if os.getenv('CODE_RUNNER') == "device": # Configure interpreter interpreter = configure_interpreter(interpreter) -@app.get("/ping") -async def ping(): - return PlainTextResponse("pong") - @app.websocket("/") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() @@ -237,7 +236,6 @@ from uvicorn import Config, Server if __name__ == "__main__": async def main(): - # Start listening asyncio.create_task(listener()) @@ -249,19 +247,6 @@ if __name__ == "__main__": if not server_url: raise ValueError("The environment variable SERVER_URL is not set. Please set it to proceed.") parsed_url = urllib.parse.urlparse(server_url) - - # Set up Ngrok - ngrok_auth_token = os.getenv('NGROK_AUTHTOKEN') - if ngrok_auth_token is not None: - logger.info("Setting up Ngrok") - ngrok_listener = await ngrok.forward(f"{parsed_url.hostname}:{parsed_url.port}", authtoken=ngrok_auth_token) - ngrok_parsed_url = urllib.parse.urlparse(ngrok_listener.url()) - - # Setup SERVER_URL environment variable for device to use - connection_url = f"wss://{ngrok_parsed_url.hostname}/" - logger.info(f"Ngrok established at {ngrok_parsed_url.geturl()}") - logger.info(f"\033[1mSERVER_CONNECTION_URL should be set to \"{connection_url}\"\033[0m") - logger.info("Starting `server.py`...") config = Config(app, host=parsed_url.hostname, port=parsed_url.port, lifespan='on') diff --git a/OS/01/start.sh b/OS/01/start.sh index 56580c8..ec21daf 100755 --- a/OS/01/start.sh +++ b/OS/01/start.sh @@ -8,7 +8,6 @@ set -a; source .env; set +az ### SETUP # if using local models, install the models / executables -WHISPER_MODEL_URL="https://huggingface.co/ggerganov/whisper.cpp/resolve/main/" WHISPER_RUST_PATH="`pwd`/local_stt/whisper-rust" curl -OL "${WHISPER_MODEL_URL}${WHISPER_MODEL_NAME}" --output-dir ${WHISPER_RUST_PATH} @@ -63,14 +62,6 @@ fi start_device() { echo "Starting device..." - if [[ -n $NGROK_AUTHTOKEN ]]; then - echo "Waiting for Ngrok to setup" - sleep 7 - read -p "Enter the Ngrok URL: " ngrok_url - export SERVER_CONNECTION_URL=$ngrok_url - echo "SERVER_CONNECTION_URL set to $SERVER_CONNECTION_URL" - fi - python device.py & DEVICE_PID=$! echo "Device started as process $DEVICE_PID" @@ -98,18 +89,18 @@ stop_processes() { # Trap SIGINT and SIGTERM to stop processes when the script is terminated trap stop_processes SIGINT SIGTERM -# SERVER -# Start server if SERVER_START is True -if [[ "$SERVER_START" == "True" ]]; then - start_server -fi - # DEVICE # Start device if DEVICE_START is True if [[ "$DEVICE_START" == "True" ]]; then start_device fi +# SERVER +# Start server if SERVER_START is True +if [[ "$SERVER_START" == "True" ]]; then + start_server +fi + # Wait for device and server processes to exit wait $DEVICE_PID wait $SERVER_PID