Merge pull request #44 from tomchapin/feature/replace-ngrok-with-open-source

Feature/replace ngrok with open source
pull/53/head
killian 11 months ago committed by GitHub
commit c599f585bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,4 @@
_archive
__pycache__
.idea

@ -16,16 +16,16 @@ TEACH_MODE=False
PIPER_VOICE_URL="https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/" PIPER_VOICE_URL="https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/"
PIPER_VOICE_NAME="en_US-lessac-medium.onnx" PIPER_VOICE_NAME="en_US-lessac-medium.onnx"
# Expose through Ngrok
# Uncomment following line with your Ngrok auth token (https://dashboard.ngrok.com/get-started/your-authtoken)
#NGROK_AUTHTOKEN="AUTH TOKEN"
# If SERVER_START, this is where we'll serve the server. # If SERVER_START, this is where we'll serve the server.
# If CLIENT_START, this is where the client expects the server to be. # If CLIENT_START, this is where the client expects the server to be.
# SERVER_URL=ws://localhost:8000/
SERVER_URL=ws://0.0.0.0:8000/ SERVER_URL=ws://0.0.0.0:8000/
SERVER_START=True SERVER_START=True
CLIENT_START=True CLIENT_START=True
# The port to start the local server on
SERVER_LOCAL_PORT=8000
# Explicitly set the client type (macos, rpi) # Explicitly set the client type (macos, rpi)
CLIENT_TYPE=auto CLIENT_TYPE=auto
@ -34,9 +34,6 @@ CODE_RUNNER=server
TTS_RUNNER=server # If client, audio will be sent over websocket. TTS_RUNNER=server # If client, audio will be sent over websocket.
STT_RUNNER=client # If server, audio will be sent over websocket. STT_RUNNER=client # If server, audio will be sent over websocket.
# Will expose the server publically and display that URL.
SERVER_EXPOSE_PUBLICALLY=False
# Image capture settings # Image capture settings
CAMERA_ENABLED=False CAMERA_ENABLED=False

@ -18,7 +18,6 @@ import urllib.parse
from .utils.kernel import put_kernel_messages_into_queue from .utils.kernel import put_kernel_messages_into_queue
from .i import configure_interpreter from .i import configure_interpreter
from interpreter import interpreter from interpreter import interpreter
import ngrok
from ..utils.accumulator import Accumulator from ..utils.accumulator import Accumulator
from .teach import teach from .teach import teach
from .utils.logs import setup_logging from .utils.logs import setup_logging
@ -31,6 +30,9 @@ app = FastAPI()
conversation_history_path = Path(__file__).parent / 'conversations' / 'user.json' conversation_history_path = Path(__file__).parent / 'conversations' / 'user.json'
SERVER_LOCAL_PORT = int(os.getenv('SERVER_LOCAL_PORT', 8000))
# This is so we only say() full sentences # This is so we only say() full sentences
def is_full_sentence(text): def is_full_sentence(text):
return text.endswith(('.', '!', '?')) return text.endswith(('.', '!', '?'))
@ -318,18 +320,6 @@ async def stream_tts_to_device(sentence):
return return
for chunk in stream_tts(sentence): for chunk in stream_tts(sentence):
await to_device.put(chunk) await to_device.put(chunk)
async def setup_ngrok(ngrok_auth_token, parsed_url):
# Set up Ngrok
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")
from uvicorn import Config, Server from uvicorn import Config, Server
@ -346,20 +336,11 @@ if __name__ == "__main__":
# Start watching the kernel if it's your job to do that # Start watching the kernel if it's your job to do that
if os.getenv('CODE_RUNNER') == "server": if os.getenv('CODE_RUNNER') == "server":
asyncio.create_task(put_kernel_messages_into_queue(from_computer)) asyncio.create_task(put_kernel_messages_into_queue(from_computer))
server_url = os.getenv('SERVER_URL')
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:
await setup_ngrok(ngrok_auth_token, parsed_url)
logger.info("Starting `server.py`...") # Start the server
logger.info("Starting `server.py`... on localhost:" + str(SERVER_LOCAL_PORT))
config = Config(app, host=parsed_url.hostname, port=parsed_url.port, lifespan='on') config = Config(app, host="localhost", port=SERVER_LOCAL_PORT, lifespan='on')
server = Server(config) server = Server(config)
await server.serve() await server.serve()

@ -1,33 +0,0 @@
The open-source language model computer.
```bash
pip install 01OS
```
```bash
01 # This will run a server + attempt to determine and run a client.
# (Behavior can be modified by changing the contents of `.env`)
```
**Expose an 01 server publically:**
```bash
01 --server --expose # This will print a URL that a client can point to.
```
**Run a specific client:**
```bash
01 --client macos # Options: macos, rpi
```
**Run locally:**
The current default uses OpenAI's services.
The `--local` flag will install and run the [whisper.cpp](https://github.com/ggerganov/whisper.cpp) STT and [Piper](https://github.com/rhasspy/piper) TTS models.
```bash
01 --local # Local client and server
01 --local --server --expose # Expose a local server
```

@ -56,8 +56,22 @@ fi
# Check if "--expose" is passed as an argument # Check if "--expose" is passed as an argument
if [[ "$@" == *"--expose"* ]]; then if [[ "$@" == *"--expose"* ]]; then
# If "--expose" is passed, set SERVER_EXPOSE_PUBLICALLY to True if [[ "$SERVER_START" != "True" ]]; then
export SERVER_EXPOSE_PUBLICALLY="True" echo "Error: Start script must be started with --serve for tunneling to work."
exit 1
else
export TUNNEL_START="True"
if [[ "$@" == *"--expose-with-bore"* ]]; then
export TUNNEL_METHOD="bore"
elif [[ "$@" == *"--expose-with-localtunnel"* ]]; then
export TUNNEL_METHOD="localtunnel"
elif [[ "$@" == *"--expose-with-ngrok"* ]]; then
export TUNNEL_METHOD="ngrok"
fi
echo "exposing server"
fi
fi fi
# Check if "--clear-local" is passed as an argument # Check if "--clear-local" is passed as an argument
@ -177,6 +191,14 @@ start_server() {
echo "Server started as process $SERVER_PID" echo "Server started as process $SERVER_PID"
} }
# Function to start tunnel service
start_tunnel() {
echo "Starting tunnel..."
./tunnel.sh &
TUNNEL_PID=$!
echo "Tunnel started as process $TUNNEL_PID"
}
stop_processes() { stop_processes() {
if [[ -n $CLIENT_PID ]]; then if [[ -n $CLIENT_PID ]]; then
echo "Stopping client..." echo "Stopping client..."
@ -186,6 +208,10 @@ stop_processes() {
echo "Stopping server..." echo "Stopping server..."
kill $SERVER_PID kill $SERVER_PID
fi fi
if [[ -n $TUNNEL_PID ]]; then
echo "Stopping tunnel..."
kill $TUNNEL_PID
fi
} }
# Trap SIGINT and SIGTERM to stop processes when the script is terminated # Trap SIGINT and SIGTERM to stop processes when the script is terminated
@ -203,9 +229,16 @@ if [[ "$CLIENT_START" == "True" ]]; then
start_client start_client
fi fi
# TUNNEL
# Start tunnel if TUNNEL_START is True
if [[ "$TUNNEL_START" == "True" ]]; then
start_tunnel
fi
# Wait for client and server processes to exit # Wait for client and server processes to exit
wait $CLIENT_PID wait $CLIENT_PID
wait $SERVER_PID wait $SERVER_PID
wait $TUNNEL_PID
# TTS, STT # TTS, STT

@ -0,0 +1,65 @@
#!/usr/bin/env bash
# Get tunnel method from TUNNEL_METHOD environment variable, but default to bore
# Possible options;
# - bore
# - localtunnel
# - ngrok
TUNNEL_METHOD=${TUNNEL_METHOD:-bore}
# Get the SERVER_PORT environment variable, but default to 8000
SERVER_LOCAL_PORT=${SERVER_LOCAL_PORT:-8000}
echo "Using $TUNNEL_METHOD to expose port $SERVER_LOCAL_PORT on localhost..."
# If the TUNNEL_METHOD is bore, then we need to check if the bore-cli is installed
if [[ "$TUNNEL_METHOD" == "bore" ]]; then
if ! command -v bore &> /dev/null; then
echo "The bore-cli command is not available. Please run 'cargo install bore-cli'."
echo "For more information, see https://github.com/ekzhang/bore"
exit 1
else
bore local $SERVER_LOCAL_PORT --to bore.pub | while IFS= read -r line; do
if [[ "$line" == *"listening at bore.pub:"* ]]; then
remote_port=$(echo "$line" | grep -o 'bore.pub:[0-9]*' | cut -d':' -f2)
echo "Please set your client env variable for SERVER_URL=ws://bore.pub:$remote_port"
break
fi
done
fi
elif [[ "$TUNNEL_METHOD" == "localtunnel" ]]; then
if ! command -v lt &> /dev/null; then
echo "The 'lt' command is not available."
echo "Please ensure you have Node.js installed, then run 'npm install -g localtunnel'."
echo "For more information, see https://github.com/localtunnel/localtunnel"
exit 1
else
npx localtunnel --port $SERVER_LOCAL_PORT | while IFS= read -r line; do
if [[ "$line" == *"your url is: https://"* ]]; then
remote_url=$(echo "$line" | grep -o 'https://[a-zA-Z0-9.-]*' | sed 's|https://||')
echo "Please set your client env variable for SERVER_URL=wss://$remote_url"
break
fi
done
fi
elif [[ "$TUNNEL_METHOD" == "ngrok" ]]; then
if ! command -v ngrok &> /dev/null; then
echo "The ngrok command is not available."
echo "Please install ngrok using the instructions at https://ngrok.com/docs/getting-started/"
exit 1
else
ngrok http $SERVER_LOCAL_PORT --log stdout | while IFS= read -r line; do
if [[ "$line" == *"started tunnel"* ]]; then
remote_url=$(echo "$line" | grep -o 'https://[a-zA-Z0-9.-]*' | sed 's|https://||')
echo "Please set your client env variable for SERVER_URL=wss://$remote_url"
break
fi
done
fi
fi

@ -35,11 +35,40 @@ pip install 01OS
# (Behavior can be modified by changing the contents of `.env`) # (Behavior can be modified by changing the contents of `.env`)
``` ```
**Expose an 01 server publically:** **Expose an 01 Server Publicly**
We currently support exposing the 01 server publicly via a couple of different tunnel services:
- **bore.pub** ([GitHub](https://github.com/ekzhang/bore))
- **Requirements:** Ensure that Rust is installed ([Rust Installation](https://www.rust-lang.org/tools/install)), then run:
```
cargo install bore-cli
```
- **To Expose:**
```bash
01 --server --expose-with-bore
```
- **localtunnel** ([GitHub](https://github.com/localtunnel/localtunnel))
- **Requirements:** Ensure that Node.js is installed ([Node.js Download](https://nodejs.org/en/download)), then run:
```
npm install -g localtunnel
```
- **To Expose:**
```bash
01 --server --expose-with-localtunnel
```
- **ngrok** ([Website](https://ngrok.com/))
- **Requirements:** Install ngrok ([Getting Started with ngrok](https://ngrok.com/docs/getting-started/)), and set up an ngrok account. Get your auth key from [ngrok dashboard](https://dashboard.ngrok.com/get-started/your-authtoken), then set it in your local configuration by running:
```
ngrok config add-authtoken your_auth_token_here
```
- **To Expose:**
```bash
01 --server --expose-with-ngrok
```
```bash
01 --server --expose # This will print a URL that a client can point to.
```
**Run a specific client:** **Run a specific client:**
@ -55,7 +84,7 @@ The `--local` flag will install and run the [whisper.cpp](https://github.com/gge
```bash ```bash
01 --local # Local client and server 01 --local # Local client and server
01 --local --server --expose # Expose a local server 01 --local --server --expose-with-bore # Expose the local server with a public tunnel
``` ```
**Teach Mode (experimental)** **Teach Mode (experimental)**

Loading…
Cancel
Save