Browse Source

set up quart (flask) webui

master
Hendrik Langer 2 years ago
parent
commit
cfdbb306bc
  1. 3
      README.md
  2. 0
      matrix_pygmalion_bot/connections/__init__.py
  3. 27
      matrix_pygmalion_bot/connections/templates/index.html
  4. 64
      matrix_pygmalion_bot/connections/webui.py
  5. 65
      matrix_pygmalion_bot/main.py
  6. 3
      requirements.txt

3
README.md

@ -32,3 +32,6 @@ python3 koboldcpp.py --unbantokens --smartcontext --stream models/pygmalion-6b-v
* runpod.io * runpod.io
* vast.ai * vast.ai
* stablehorde.net * stablehorde.net
## ToDo:
* https://python-poetry.org/

0
matrix_pygmalion_bot/connections/__init__.py

27
matrix_pygmalion_bot/connections/templates/index.html

@ -0,0 +1,27 @@
<script type="text/javascript">
const ws = new WebSocket(`ws://${location.host}/ws`);
ws.addEventListener('message', function (event) {
const li = document.createElement("li");
li.appendChild(document.createTextNode(event.data));
document.getElementById("messages").appendChild(li);
});
function send(event) {
const message = (new FormData(event.target)).get("message");
if (message) {
ws.send(message);
}
event.target.reset();
return false;
}
</script>
<div style="display: flex; height: 100%; flex-direction: column">
<ul id="messages" style="flex-grow: 1; list-style-type: none"></ul>
<form onsubmit="return send(event)">
<input type="text" name="message" minlength="1" />
<button type="submit">Send</button>
</form>
</div>

64
matrix_pygmalion_bot/connections/webui.py

@ -0,0 +1,64 @@
import asyncio
from typing import AsyncGenerator
from quart import Quart, render_template, websocket
import logging
logger = logging.getLogger(__name__)
app = Quart(__name__)
connections = set()
@app.route("/")
async def index():
return await render_template("index.html")
@app.route("/api")
async def json():
return {"hello": "world"}
async def _send() -> None:
connection = asyncio.Queue()
connections.add(connection)
try:
while True:
message = await connection.get()
await websocket.send(message)
finally:
connections.remove(connection)
async def _receive() -> None:
while True:
message = await websocket.receive()
for connection in connections:
await connection.put(message)
@app.websocket("/ws")
async def ws() -> None:
producer = asyncio.create_task(_send())
consumer = asyncio.create_task(_receive())
await asyncio.gather(producer, consumer)
#await websocket.send_json({"hello": "world"})
class WebUI(object):
"""The Web interface."""
def __init__(self):
self.shutdown_event = asyncio.Event()
self.task = None
app.config["PROPAGATE_EXCEPTIONS"] = True
pass
def run_task(self):
return app.run_task(port=5000, debug=True, shutdown_trigger=self.shutdown_event.wait)
async def stop(self):
self.shutdown_event.set()
self.task.cancel() # or close?

65
matrix_pygmalion_bot/main.py

@ -5,7 +5,10 @@ import json
from .utilities.config_parser import read_config from .utilities.config_parser import read_config
from .bot.core import ChatBot from .bot.core import ChatBot
from .connections.matrix import ChatClient from .connections.matrix import ChatClient
from .connections.webui import WebUI
import traceback import traceback
import signal
import functools
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -13,6 +16,7 @@ logger = logging.getLogger(__name__)
DATA_DIR = './.data' DATA_DIR = './.data'
bots = [] bots = []
async def main() -> None: async def main() -> None:
config = read_config('bot.conf') config = read_config('bot.conf')
if config.has_option('DEFAULT', 'log_level'): if config.has_option('DEFAULT', 'log_level'):
@ -28,6 +32,10 @@ async def main() -> None:
elif log_level == 'CRITICAL': elif log_level == 'CRITICAL':
logging.basicConfig(level=logging.CRITICAL) logging.basicConfig(level=logging.CRITICAL)
# loop = asyncio.get_event_loop()
loop = asyncio.get_running_loop()
loop.set_debug(True)
os.makedirs(DATA_DIR, exist_ok=True) os.makedirs(DATA_DIR, exist_ok=True)
for section in config.sections(): for section in config.sections():
@ -59,38 +67,69 @@ async def main() -> None:
await bot.connect() await bot.connect()
bots.append(bot) bots.append(bot)
try: webui = WebUI()
async def shutdown(signal, loop):
"""Cleanup tasks and shut down"""
logger.info(f"Received exit signal {signal.name} ...")
await webui.stop()
for bot in bots:
await bot.disconnect()
tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
[task.cancel() for task in tasks]
logging.info(f"Cancelling {len(tasks)} outstanding tasks")
await asyncio.gather(*tasks, return_exceptions=True)
logging.info(f"Flushing metrics")
loop.stop()
# loop = asyncio.get_running_loop()
#
# for signame in {'SIGINT', 'SIGTERM'}: # for signame in {'SIGINT', 'SIGTERM'}:
# loop.add_signal_handler( # loop.add_signal_handler(
# getattr(signal, signame), # getattr(signal, signame),
# functools.partial(ask_exit, signame, loop)) # functools.partial(shutdown, signame, loop))
for s in {signal.SIGHUP, signal.SIGTERM, signal.SIGINT}:
loop.add_signal_handler(
s, lambda s=s: asyncio.create_task(shutdown(s, loop)))
try:
if sys.version_info[0] == 3 and sys.version_info[1] < 11: if sys.version_info[0] == 3 and sys.version_info[1] < 11:
tasks = [] tasks = []
for bot in bots: for bot in bots:
task = asyncio.create_task(bot.connection.sync_forever(timeout=180000, full_state=True)) # 30000 task = asyncio.create_task(bot.connection.sync_forever(timeout=180000, full_state=True)) # 30000
tasks.append(task) tasks.append(task)
webui.task = asyncio.create_task(webui.run_task())
tasks.append(webui.task)
await asyncio.gather(*tasks) await asyncio.gather(*tasks)
else: else:
async with asyncio.TaskGroup() as tg: async with asyncio.TaskGroup() as tg:
for bot in bots: for bot in bots:
task = tg.create_task(bot.connection.sync_forever(timeout=180000, full_state=True)) # 30000 task = tg.create_task(bot.connection.sync_forever(timeout=180000, full_state=True)) # 30000
webui.task = tg.create_task(webui.run_task())
except Exception: # except Exception:
print(traceback.format_exc()) # print(traceback.format_exc())
sys.exit(1) # sys.exit(1)
except (asyncio.CancelledError, KeyboardInterrupt): except (asyncio.CancelledError, KeyboardInterrupt):
print("Received keyboard interrupt.") print("Received keyboard interrupt.")
for bot in bots: # webui.task.cancel()
await bot.disconnect() # for bot in bots:
sys.exit(0) # await bot.disconnect()
# sys.exit(0)
finally:
pass
#loop.close()
#def ask_exit(signame, loop):
# print("got signal %s: exit" % signame)
# loop.stop()
if __name__ == "__main__": if __name__ == "__main__":

3
requirements.txt

@ -14,4 +14,5 @@ humanize
psutil psutil
#git+https://github.com/suno-ai/bark.git #git+https://github.com/suno-ai/bark.git
#SpeechRecognition #SpeechRecognition
#TTS #(Coqui-TTS or Uberduck ??) #TTS #(Coqui-TTS or Uberduck ??) TorToiSe??
quart

Loading…
Cancel
Save