Error connecting, please try again.
"); - + AsyncWebServerResponse *response = request->beginResponse(200, "text/html", htmlContent); response->addHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // Prevent caching of this page request->send(response); @@ -622,7 +622,7 @@ void InitI2SSpeakerOrMic(int mode) #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 1, 0) .communication_format = I2S_COMM_FORMAT_STAND_I2S, // Set the format of the communication. -#else +#else .communication_format = I2S_COMM_FORMAT_I2S, #endif .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, @@ -779,17 +779,17 @@ void setup() { Serial.begin(115200); // Initialize serial communication at 115200 baud rate. // Attempt to reconnect to WiFi using stored credentials. // Check if WiFi is connected but the server URL isn't stored - + Serial.setTxBufferSize(1024); // Set the transmit buffer size for the Serial object. WiFi.mode(WIFI_AP_STA); // Set WiFi mode to both AP and STA. - + // delay(100); // Short delay to ensure mode change takes effect // WiFi.softAPConfig(localIP, gatewayIP, subnetMask); // WiFi.softAP(ssid, password); startSoftAccessPoint(ssid, password, localIP, gatewayIP); setUpDNSServer(dnsServer, localIP); - + setUpWebserver(server, localIP); tryReconnectWiFi(); // Print a welcome message to the Serial port. @@ -823,7 +823,7 @@ void loop() if ((millis() - last_dns_ms) > DNS_INTERVAL) { last_dns_ms = millis(); // seems to help with stability, if you are doing other things in the loop this may not be needed dnsServer.processNextRequest(); // I call this atleast every 10ms in my other projects (can be higher but I haven't tested it for stability) - } + } // Check WiFi connection status if (WiFi.status() == WL_CONNECTED && !hasSetupWebsocket) @@ -865,4 +865,4 @@ void loop() M5.update(); webSocket.loop(); } -} \ No newline at end of file +} diff --git a/software/source/clients/esp32/src/client/platformio.ini b/software/source/clients/esp32/src/client/platformio.ini index 6061e13a..d1011e28 100644 --- a/software/source/clients/esp32/src/client/platformio.ini +++ b/software/source/clients/esp32/src/client/platformio.ini @@ -10,7 +10,7 @@ platform = espressif32 framework = arduino monitor_speed = 115200 upload_speed = 1500000 -monitor_filters = +monitor_filters = esp32_exception_decoder time build_flags = @@ -23,7 +23,7 @@ board = esp32dev [env:m5echo] extends = esp32common -lib_deps = +lib_deps = m5stack/M5Atom @ ^0.1.2 links2004/WebSockets @ ^2.4.1 ;esphome/ESPAsyncWebServer-esphome @ ^3.1.0 diff --git a/software/source/clients/linux/device.py b/software/source/clients/linux/device.py index a9a79c02..0fa0fed2 100644 --- a/software/source/clients/linux/device.py +++ b/software/source/clients/linux/device.py @@ -2,9 +2,11 @@ device = Device() + def main(server_url): device.server_url = server_url device.start() + if __name__ == "__main__": main() diff --git a/software/source/clients/mac/device.py b/software/source/clients/mac/device.py index a9a79c02..0fa0fed2 100644 --- a/software/source/clients/mac/device.py +++ b/software/source/clients/mac/device.py @@ -2,9 +2,11 @@ device = Device() + def main(server_url): device.server_url = server_url device.start() + if __name__ == "__main__": main() diff --git a/software/source/clients/rpi/device.py b/software/source/clients/rpi/device.py index 279822f9..fe0250bd 100644 --- a/software/source/clients/rpi/device.py +++ b/software/source/clients/rpi/device.py @@ -2,8 +2,10 @@ device = Device() + def main(): device.start() + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/software/source/clients/windows/device.py b/software/source/clients/windows/device.py index a9a79c02..0fa0fed2 100644 --- a/software/source/clients/windows/device.py +++ b/software/source/clients/windows/device.py @@ -2,9 +2,11 @@ device = Device() + def main(server_url): device.server_url = server_url device.start() + if __name__ == "__main__": main() diff --git a/software/source/server/llm.py b/software/source/server/llm.py index ba761a30..430e58ad 100644 --- a/software/source/server/llm.py +++ b/software/source/server/llm.py @@ -1,4 +1,5 @@ from dotenv import load_dotenv + load_dotenv() # take environment variables from .env. import os @@ -8,7 +9,7 @@ ### LLM SETUP # Define the path to a llamafile -llamafile_path = Path(__file__).parent / 'model.llamafile' +llamafile_path = Path(__file__).parent / "model.llamafile" # Check if the new llamafile exists, if not download it if not os.path.exists(llamafile_path): @@ -25,4 +26,4 @@ subprocess.run(["chmod", "+x", llamafile_path], check=True) # Run the new llamafile -subprocess.run([str(llamafile_path)], check=True) \ No newline at end of file +subprocess.run([str(llamafile_path)], check=True) diff --git a/software/source/server/services/llm/litellm/llm.py b/software/source/server/services/llm/litellm/llm.py index 906308bf..f4093e4a 100644 --- a/software/source/server/services/llm/litellm/llm.py +++ b/software/source/server/services/llm/litellm/llm.py @@ -1,6 +1,5 @@ class Llm: def __init__(self, config): - # Litellm is used by OI by default, so we just modify OI interpreter = config["interpreter"] @@ -10,6 +9,3 @@ def __init__(self, config): setattr(interpreter, key.replace("-", "_"), value) self.llm = interpreter.llm.completions - - - diff --git a/software/source/server/services/llm/llamaedge/llm.py b/software/source/server/services/llm/llamaedge/llm.py index fa77abf6..7894f544 100644 --- a/software/source/server/services/llm/llamaedge/llm.py +++ b/software/source/server/services/llm/llamaedge/llm.py @@ -3,29 +3,54 @@ import requests import json + class Llm: def __init__(self, config): self.install(config["service_directory"]) def install(self, service_directory): LLM_FOLDER_PATH = service_directory - self.llm_directory = os.path.join(LLM_FOLDER_PATH, 'llm') - if not os.path.isdir(self.llm_directory): # Check if the LLM directory exists + self.llm_directory = os.path.join(LLM_FOLDER_PATH, "llm") + if not os.path.isdir(self.llm_directory): # Check if the LLM directory exists os.makedirs(LLM_FOLDER_PATH, exist_ok=True) # Install WasmEdge - subprocess.run(['curl', '-sSf', 'https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh', '|', 'bash', '-s', '--', '--plugin', 'wasi_nn-ggml']) + subprocess.run( + [ + "curl", + "-sSf", + "https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh", + "|", + "bash", + "-s", + "--", + "--plugin", + "wasi_nn-ggml", + ] + ) # Download the Qwen1.5-0.5B-Chat model GGUF file MODEL_URL = "https://huggingface.co/second-state/Qwen1.5-0.5B-Chat-GGUF/resolve/main/Qwen1.5-0.5B-Chat-Q5_K_M.gguf" - subprocess.run(['curl', '-LO', MODEL_URL], cwd=self.llm_directory) - + subprocess.run(["curl", "-LO", MODEL_URL], cwd=self.llm_directory) + # Download the llama-api-server.wasm app APP_URL = "https://github.com/LlamaEdge/LlamaEdge/releases/latest/download/llama-api-server.wasm" - subprocess.run(['curl', '-LO', APP_URL], cwd=self.llm_directory) + subprocess.run(["curl", "-LO", APP_URL], cwd=self.llm_directory) # Run the API server - subprocess.run(['wasmedge', '--dir', '.:.', '--nn-preload', 'default:GGML:AUTO:Qwen1.5-0.5B-Chat-Q5_K_M.gguf', 'llama-api-server.wasm', '-p', 'llama-2-chat'], cwd=self.llm_directory) + subprocess.run( + [ + "wasmedge", + "--dir", + ".:.", + "--nn-preload", + "default:GGML:AUTO:Qwen1.5-0.5B-Chat-Q5_K_M.gguf", + "llama-api-server.wasm", + "-p", + "llama-2-chat", + ], + cwd=self.llm_directory, + ) print("LLM setup completed.") else: @@ -33,17 +58,11 @@ def install(self, service_directory): def llm(self, messages): url = "http://localhost:8080/v1/chat/completions" - headers = { - 'accept': 'application/json', - 'Content-Type': 'application/json' - } - data = { - "messages": messages, - "model": "llama-2-chat" - } - with requests.post(url, headers=headers, data=json.dumps(data), stream=True) as response: + headers = {"accept": "application/json", "Content-Type": "application/json"} + data = {"messages": messages, "model": "llama-2-chat"} + with requests.post( + url, headers=headers, data=json.dumps(data), stream=True + ) as response: for line in response.iter_lines(): if line: yield json.loads(line) - - diff --git a/software/source/server/services/stt/local-whisper/whisper-rust/.gitignore b/software/source/server/services/stt/local-whisper/whisper-rust/.gitignore index 71ab9a43..73fab072 100644 --- a/software/source/server/services/stt/local-whisper/whisper-rust/.gitignore +++ b/software/source/server/services/stt/local-whisper/whisper-rust/.gitignore @@ -7,4 +7,4 @@ target/ **/*.rs.bk # MSVC Windows builds of rustc generate these, which store debugging information -*.pdb \ No newline at end of file +*.pdb diff --git a/software/source/server/services/stt/local-whisper/whisper-rust/Cargo.toml b/software/source/server/services/stt/local-whisper/whisper-rust/Cargo.toml index f1726929..c3daf687 100644 --- a/software/source/server/services/stt/local-whisper/whisper-rust/Cargo.toml +++ b/software/source/server/services/stt/local-whisper/whisper-rust/Cargo.toml @@ -11,4 +11,4 @@ clap = { version = "4.4.18", features = ["derive"] } cpal = "0.15.2" hound = "3.5.1" whisper-rs = "0.10.0" -whisper-rs-sys = "0.8.0" \ No newline at end of file +whisper-rs-sys = "0.8.0" diff --git a/software/source/server/services/stt/local-whisper/whisper-rust/src/main.rs b/software/source/server/services/stt/local-whisper/whisper-rust/src/main.rs index 0688c89e..52965388 100644 --- a/software/source/server/services/stt/local-whisper/whisper-rust/src/main.rs +++ b/software/source/server/services/stt/local-whisper/whisper-rust/src/main.rs @@ -10,7 +10,7 @@ struct Args { /// This is the model for Whisper STT #[arg(short, long, value_parser, required = true)] model_path: PathBuf, - + /// This is the wav audio file that will be converted from speech to text #[arg(short, long, value_parser, required = true)] file_path: Optiongk(*nG6_q=^VO{)x0`lqq2GV~}@c!>8{Rh%N*#!Md
zcK;8gf67wupJn>jNdIgNpZR|v@cIA03H<+(hK<+%dm4_({I~3;yCGk?+3uu{%&A)1
zP|cr?l KFzaTY@vvKH7%3fMd5>K7Hf1!``V7EA{
z1wfp4Pd!A;Kstvm^z=AAQ1*5zEXWGy2d _m_Cz!aI|OA~=>rP%zF{{H>1(kb7
z4)}@b!KeU2)@MzR_YE%3o4g*xJG?EcRK5kXSbz@E+m@qx9_R7a^9cb
UB)$2x>!>nfd_<&42MzO_oU^Cuw3W1U>C8k4Z-;I)Hwz}clprW*1#cN9Eb
zc+)>qHS%7}9^t&jOjsczIIrb)IhH|7_FvnJ#3iry6`pc8JS^|zdc`sIrW~1v44uAu
z4cXW$3L?~kE9>1tR}nrfv_T83-xr!;EgYul%$1fy>9C%r0(M(5`Ww>Z8eY8jc)$22
z79&%(H(PfzKGg~3+n=o
f0^4m~AUeAv={cet7m*{2|~6vVAM=vpL?8r|>+7ZfuT;*FKMLJGNyc
z)!M?FJlzd>mzyrCJi3SQM$eUS@xCJioofaUwqrzeQ%S|R`Aa6u$h3~pn3ge8H;U0%
z+Z~w$tX*TF3?Bia(5OK1--uI#gzJ;b5uLoH{ZFw&E0w}REn0XA!4#HLjdvE}GHCBT
zMj7g$9;PwAHTUKI5ZL0?jTRutws}W@-^ZQvY+I`RRUq^H(;hro2sF&qX0$Sn8yjq1
zS-XgbgdmyQukGKXhM9c#5rJ(q^!e2^A|dvfiB5oGPSLeAt5%D5*PeG3-*&*guZuuC
zJBU$e7TQYCv=P5Uu*IQUHW?0y%33xDZpbd98PO};2E)HxOQKujAq3if83>i5Pu
zYMyimE!m+Pmb_Cldje-6xU_|0Y~>W12^QzJUQ%KCfn-h(j9E~e3Rza5+0iCjw=GkR
zllb*}Z;86cW~@;2#H$^c?SJZ&~V2j?k
zG|`DtuOZxpw-AY`^ORuoHM0{}8K&Q|>4z}_GxXGN26MhH(*yL)Wh#Wq)~aU7Y+-t>
z2Gi$X&&c{>T-F`5Id&^R_U(!2wJTKOCLLzNOV-BSUQ;j8Q_q&Bo)TCfrbifrN`A(C
zsH8<9&qKAN7yoI|fj4+LZmmi
8H<#Jdj6-1?y&;5J~8X2
zz7CuJk}fVIaFPY~et#fWJ{T*j#nWee)9-McpR-W6OkCGj*gu<&Tv=bu3J1H0#ve0mwiSZ6
zR0Vwj+-m(w-WooXk=Hkl)m~qjKbT<&y0h$2gl8Qr#(JfoEZLZWVuB->i=`_OmFHed!L&*^B0azpeu!a9XuMHX{b&M!monL+>QR!DW>6J%bs#d@QG;{2YEo5Y(^V;Uy
z_b_1qCEf|3;9iHmuGY95K{bnX7xa3=-`mF=o3?L4=9R3>c=4mL>B#bz{#SeUWZv?0
z=KN~};zrBgYL+nvThul&KZEWEVP|W-y}cPR2_$}&STL(mApmvKJ<~J$X4q5Hs;B)<
z2zC8XG(ZSDGCX}5fI+FWsbTyn4H4;{n*E!X?ij*{AgF!A%UUgV1oP)^=;?8qoFDcd
z#g?mHMJx1268mZ>*8tZI!nW1e(wyt0RIhQq))G}VpHbmv9WmDVzbjCy6uC=K50C!o
zxBqxI8B1Eug2U