Spaces:
Running
on
A10G
Running
on
A10G
GitLab CI
commited on
Commit
·
3d7f69e
1
Parent(s):
9e4dc76
Update game build from GitLab CI
Browse files- server/ActionProcessor.py +20 -6
- server/AudioTranscriber.py +1 -2
- server/StandaloneApplication.py +19 -0
- server/__main__.py +12 -26
- server/static/godot/index.pck +0 -0
server/ActionProcessor.py
CHANGED
@@ -1,15 +1,32 @@
|
|
1 |
from threading import Thread
|
2 |
-
from
|
3 |
from typing import Dict, Any
|
4 |
import json
|
5 |
import re
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
|
8 |
class ActionProcessor(Thread):
|
9 |
-
def __init__(
|
|
|
|
|
|
|
|
|
|
|
10 |
super().__init__()
|
11 |
self.text_queue = text_queue
|
12 |
self.action_queue = action_queue
|
|
|
13 |
self.daemon = True # Thread will exit when main program exits
|
14 |
|
15 |
def process_text(self, text: str) -> Dict[str, Any] | None:
|
@@ -48,9 +65,6 @@ class ActionProcessor(Thread):
|
|
48 |
if action:
|
49 |
self.action_queue.put(json.dumps(action))
|
50 |
|
51 |
-
# Mark the text as processed
|
52 |
-
self.text_queue.task_done()
|
53 |
-
|
54 |
except Exception as e:
|
55 |
-
|
56 |
continue
|
|
|
1 |
from threading import Thread
|
2 |
+
from multiprocessing import Queue
|
3 |
from typing import Dict, Any
|
4 |
import json
|
5 |
import re
|
6 |
+
import logging
|
7 |
+
import sys
|
8 |
+
|
9 |
+
# Configure logging
|
10 |
+
logging.basicConfig(
|
11 |
+
level=logging.INFO,
|
12 |
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
13 |
+
handlers=[logging.StreamHandler(sys.stdout)],
|
14 |
+
)
|
15 |
+
|
16 |
+
logger = logging.getLogger(__name__)
|
17 |
|
18 |
|
19 |
class ActionProcessor(Thread):
|
20 |
+
def __init__(
|
21 |
+
self,
|
22 |
+
text_queue: "Queue[str]",
|
23 |
+
action_queue: "Queue[str]",
|
24 |
+
mistral_api_key: str,
|
25 |
+
):
|
26 |
super().__init__()
|
27 |
self.text_queue = text_queue
|
28 |
self.action_queue = action_queue
|
29 |
+
self.mistral_api_key = mistral_api_key
|
30 |
self.daemon = True # Thread will exit when main program exits
|
31 |
|
32 |
def process_text(self, text: str) -> Dict[str, Any] | None:
|
|
|
65 |
if action:
|
66 |
self.action_queue.put(json.dumps(action))
|
67 |
|
|
|
|
|
|
|
68 |
except Exception as e:
|
69 |
+
logger.error(f"Error processing text: {str(e)}")
|
70 |
continue
|
server/AudioTranscriber.py
CHANGED
@@ -45,8 +45,7 @@ class AudioTranscriber(threading.Thread):
|
|
45 |
self.action_queue.put(segment.text)
|
46 |
# Still print for debugging
|
47 |
logger.info(
|
48 |
-
f"[
|
49 |
-
% (segment.start, segment.end, segment.text)
|
50 |
)
|
51 |
|
52 |
except Empty:
|
|
|
45 |
self.action_queue.put(segment.text)
|
46 |
# Still print for debugging
|
47 |
logger.info(
|
48 |
+
f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}"
|
|
|
49 |
)
|
50 |
|
51 |
except Empty:
|
server/StandaloneApplication.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gunicorn.app.base
|
2 |
+
from flask import Flask
|
3 |
+
|
4 |
+
|
5 |
+
from typing import Any, Dict
|
6 |
+
|
7 |
+
|
8 |
+
class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
9 |
+
def __init__(self, app: Flask, options: Optional[Dict[str, Any]] = None):
|
10 |
+
self.options = options or {}
|
11 |
+
self.application = app
|
12 |
+
super().__init__()
|
13 |
+
|
14 |
+
def load_config(self):
|
15 |
+
for key, value in self.options.items():
|
16 |
+
self.cfg.set(key.lower(), value)
|
17 |
+
|
18 |
+
def load(self):
|
19 |
+
return self.application
|
server/__main__.py
CHANGED
@@ -1,18 +1,17 @@
|
|
1 |
import io
|
2 |
-
import
|
3 |
-
from flask import Flask, send_from_directory, jsonify, request, abort
|
4 |
import os
|
5 |
-
import gunicorn.app.base
|
6 |
from flask_cors import CORS
|
7 |
from multiprocessing import Queue
|
8 |
import base64
|
9 |
-
from typing import Any,
|
10 |
-
from
|
11 |
import logging
|
12 |
import sys
|
13 |
|
14 |
from server.AudioTranscriber import AudioTranscriber
|
15 |
from server.ActionProcessor import ActionProcessor
|
|
|
16 |
|
17 |
# Configure logging
|
18 |
logging.basicConfig(
|
@@ -42,7 +41,7 @@ _ = CORS(
|
|
42 |
|
43 |
|
44 |
@app.after_request
|
45 |
-
def add_header(response):
|
46 |
# Add permissive CORS headers
|
47 |
response.headers["Access-Control-Allow-Origin"] = "*"
|
48 |
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
|
@@ -90,7 +89,6 @@ def get_data():
|
|
90 |
|
91 |
@app.route("/api/process", methods=["POST"])
|
92 |
def process_data():
|
93 |
-
logger.info("Processing data")
|
94 |
try:
|
95 |
# Check content type
|
96 |
content_type = request.headers.get("Content-Type", "")
|
@@ -145,7 +143,7 @@ def process_data():
|
|
145 |
|
146 |
|
147 |
@app.route("/api/actions", methods=["GET"])
|
148 |
-
def get_actions() -> Tuple[
|
149 |
"""Retrieve and clear all pending actions from the queue"""
|
150 |
actions: List[Dict[str, Any]] = []
|
151 |
|
@@ -156,7 +154,7 @@ def get_actions() -> Tuple[Dict[str, Any], int]:
|
|
156 |
except Exception:
|
157 |
break
|
158 |
|
159 |
-
return jsonify({"actions":
|
160 |
|
161 |
|
162 |
@app.route("/<path:path>")
|
@@ -167,23 +165,7 @@ def serve_static(path: str):
|
|
167 |
abort(404, description=f"File {path} not found in static folder")
|
168 |
|
169 |
|
170 |
-
class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
171 |
-
def __init__(self, app: Flask, options: Optional[Dict[str, Any]] = None):
|
172 |
-
self.options = options or {}
|
173 |
-
self.application = app
|
174 |
-
super().__init__()
|
175 |
-
|
176 |
-
def load_config(self):
|
177 |
-
for key, value in self.options.items():
|
178 |
-
self.cfg.set(key.lower(), value)
|
179 |
-
|
180 |
-
def load(self):
|
181 |
-
return self.application
|
182 |
-
|
183 |
-
|
184 |
if __name__ == "__main__":
|
185 |
-
logger.info(f"Static folder path: {app.static_folder}")
|
186 |
-
logger.info(f"Static folder exists: {os.path.exists(app.static_folder)}")
|
187 |
if os.path.exists(app.static_folder):
|
188 |
logger.info(f"Static folder contents: {os.listdir(app.static_folder)}")
|
189 |
|
@@ -194,7 +176,11 @@ if __name__ == "__main__":
|
|
194 |
transcriber.start()
|
195 |
|
196 |
# Start the action processor thread
|
197 |
-
|
|
|
|
|
|
|
|
|
198 |
action_processor.start()
|
199 |
|
200 |
options: Any = {
|
|
|
1 |
import io
|
2 |
+
from flask import Flask, Response, send_from_directory, jsonify, request, abort
|
|
|
3 |
import os
|
|
|
4 |
from flask_cors import CORS
|
5 |
from multiprocessing import Queue
|
6 |
import base64
|
7 |
+
from typing import Any, List, Dict, Tuple
|
8 |
+
from multiprocessing import Queue
|
9 |
import logging
|
10 |
import sys
|
11 |
|
12 |
from server.AudioTranscriber import AudioTranscriber
|
13 |
from server.ActionProcessor import ActionProcessor
|
14 |
+
from server.StandaloneApplication import StandaloneApplication
|
15 |
|
16 |
# Configure logging
|
17 |
logging.basicConfig(
|
|
|
41 |
|
42 |
|
43 |
@app.after_request
|
44 |
+
def add_header(response: Response):
|
45 |
# Add permissive CORS headers
|
46 |
response.headers["Access-Control-Allow-Origin"] = "*"
|
47 |
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
|
|
|
89 |
|
90 |
@app.route("/api/process", methods=["POST"])
|
91 |
def process_data():
|
|
|
92 |
try:
|
93 |
# Check content type
|
94 |
content_type = request.headers.get("Content-Type", "")
|
|
|
143 |
|
144 |
|
145 |
@app.route("/api/actions", methods=["GET"])
|
146 |
+
def get_actions() -> Tuple[Response, int]:
|
147 |
"""Retrieve and clear all pending actions from the queue"""
|
148 |
actions: List[Dict[str, Any]] = []
|
149 |
|
|
|
154 |
except Exception:
|
155 |
break
|
156 |
|
157 |
+
return jsonify({"actions": actions, "status": "success"}), 200
|
158 |
|
159 |
|
160 |
@app.route("/<path:path>")
|
|
|
165 |
abort(404, description=f"File {path} not found in static folder")
|
166 |
|
167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
if __name__ == "__main__":
|
|
|
|
|
169 |
if os.path.exists(app.static_folder):
|
170 |
logger.info(f"Static folder contents: {os.listdir(app.static_folder)}")
|
171 |
|
|
|
176 |
transcriber.start()
|
177 |
|
178 |
# Start the action processor thread
|
179 |
+
MISTRAL_API_KEY = os.getenv("MISTRAL_API_KEY")
|
180 |
+
if not MISTRAL_API_KEY:
|
181 |
+
raise ValueError("MISTRAL_API_KEY is not set")
|
182 |
+
|
183 |
+
action_processor = ActionProcessor(text_queue, action_queue, MISTRAL_API_KEY)
|
184 |
action_processor.start()
|
185 |
|
186 |
options: Any = {
|
server/static/godot/index.pck
CHANGED
Binary files a/server/static/godot/index.pck and b/server/static/godot/index.pck differ
|
|