diff --git a/backend/Dockerfile b/backend/Dockerfile
index 5525a4f..25081a5 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -1,28 +1,88 @@
-FROM python:3.12
+#FROM python:3.12
+FROM ubuntu
RUN apt-get update
-RUN apt-get install -y firefox-esr
+RUN apt-get install -y python3
+RUN apt-get install -y python3-pip
+
+
+#on debian:
+#RUN apt-get install -y firefox-esr
+RUN apt-get install -y firefox
+
RUN apt-get install -y ffmpeg
RUN apt-get install -y espeak
RUN apt-get install -y flite
+#COPY "amdgpu-install_6.1.60103-1_all.deb" "amdgpu-install_6.1.60103-1_all.deb"
+#RUN dpkg -i "amdgpu-install_6.1.60103-1_all.deb"
+#RUN amdgpu-install -y
+#RUN apt-get -y install rocm-device-libs
+
+
+#install "apt-add-repository" command:
+RUN apt-get -y install software-properties-common dirmngr apt-transport-https lsb-release ca-certificates
+RUN apt-add-repository -r ppa:graphics-drivers/ppa
+RUN add-apt-repository ppa:oibaf/graphics-drivers
+
+
+#RUN apt install hipsolver rocm-gdb -y
+
+#RUN apt-get -y install wget
+#RUN apt-get update -y --allow-unauthenticated
+#RUN wget https://repo.radeon.com/amdgpu-install/6.1.1/ubuntu/jammy/amdgpu-install_6.1.60101-1_all.deb
+#RUN apt-get install ./amdgpu-install_6.1.60101-1_all.deb -y
+#RUN amdgpu-install --usecase=rocm
+
+
+#RUN wget https://repo.radeon.com/amdgpu-install/6.1.1/ubuntu/jammy/amdgpu-install_6.1.60101-1_all.deb
+#RUN apt install ./amdgpu-install_6.1.60101-1_all.deb -y
+#RUN amdgpu-install --usecase=graphics,rocm -y
+#RUN usermod -a -G render,video $LOGNAME
+
+
+#RUN wget https://repo.radeon.com/amdgpu-install/6.1.1/ubuntu/jammy/amdgpu-install_6.1.60101-1_all.deb
+#RUN apt install ./amdgpu-install_6.1.60101-1_all.deb -y
+#RUN amdgpu-install --usecase=graphics,rocm -y
+
+
+#RUN echo "deb http://deb.debian.org/debian/ bookworm main contrib non-free-firmware" > /etc/apt/sources.list
+#RUN echo "deb http://deb.debian.org/debian/ bookworm main contrib non-free" > /etc/apt/sources.list
+
+#RUN apt-add-repository contrib
+#RUN apt-add-repository non-free
+#RUN apt update -y
+
+#RUN apt install nvidia-driver -y
+#RUN apt-get install firmware-amd-graphics libgl1-mesa-dri libglx-mesa0 mesa-vulkan-drivers xserver-xorg-video-all -y
+
+RUN apt-get update -y --allow-unauthenticated
+RUN apt-get upgrade -y --allow-unauthenticated
+RUN apt-get autoremove -y
+RUN apt-get autoclean -y
+
#RUN curl https://ollama.ai/install.sh | sh
#RUN ollama run llama2
WORKDIR /code
COPY requirements.txt /code/requirements.txt
#RUN pip3 install --no-cache-dir --upgrade -r requirements.txt
-RUN pip3 install --no-cache-dir -r requirements.txt
+
+RUN pip3 install --no-cache-dir -r requirements.txt --break-system-packages
RUN pip3 freeze > current_requirements.txt
COPY . .
ENTRYPOINT ["python3", "/code/app.py"]
-#ENTRYPOINT ["fastapi", "run", "main.py", "--port", "8000"]
#gunicorn -w 4 -b 0.0.0.0 'hello:create_app()'
#ENTRYPOINT ["gunicorn", "-w", "1", "-b", "0.0.0.0", "app:create_app()"]
-
#ENTRYPOINT ["gunicorn", "-w", "1", "-b", "0.0.0.0:5000", "app:create_app()"]
#gunicorn app:app --worker-class eventlet -w 1 --bind 0.0.0.0:5000 --reload
+
+#ENTRYPOINT ["fastapi", "run", "main.py", "--port", "8000"]
+
+#ENTRYPOINT ["uvicorn", "main:app", "--port", "8000", "--host", "0.0.0.0"]
+
+
diff --git a/backend/amdgpu-install_6.1.60103-1_all.deb b/backend/amdgpu-install_6.1.60103-1_all.deb
new file mode 100644
index 0000000..7c0b124
Binary files /dev/null and b/backend/amdgpu-install_6.1.60103-1_all.deb differ
diff --git a/backend/app.py b/backend/app.py
index c67df6a..0fed00d 100644
--- a/backend/app.py
+++ b/backend/app.py
@@ -6,17 +6,16 @@ OpenAPI access via http://localhost:5000/openapi/ on local docker-compose deploy
#------std lib modules:-------
import os, sys, json, time
import os.path
-from typing import Any, Tuple, List, Dict, Any, Callable, Optional
+from typing import Any, Tuple, List, Dict, Any, Callable, Optional, Union
from datetime import datetime, date
-#from collections import namedtuple
-import hashlib, traceback, logging
+import logging
from functools import wraps
-import base64
#-------ext libs--------------
-from elasticsearch import NotFoundError, Elasticsearch # for normal read/write without vectors
-from elasticsearch_dsl import Search, A, Document, Date, Integer, Keyword, Float, Long, Text, connections
+#from elasticsearch import NotFoundError, Elasticsearch # for normal read/write without vectors
+#from elasticsearch_dsl import A, Document, Date, Integer, Keyword, Float, Long, Text, connections
+from elasticsearch_dsl import connections
from pydantic import BaseModel, Field
import jwt as pyjwt
@@ -172,10 +171,10 @@ def sockcon(data):
class SocketMessage(BaseModel):
- room: str = Field(None, description="Status Code")
question: str = Field(None, description="Status Code")
system_prompt: str = Field(None, description="Status Code")
bot_id: str = Field(None, description="Status Code")
+ room: Union[str, None] # = Field(None, description="Status Code")
#TODO: pydantic message type validation
diff --git a/backend/lib/elastictools.py b/backend/lib/elastictools.py
index 86850a1..d4c6399 100644
--- a/backend/lib/elastictools.py
+++ b/backend/lib/elastictools.py
@@ -67,19 +67,11 @@ def get_type_schema():
def wait_for_elasticsearch():
- #TODO: find a clean way to wait without exceptions!
- #Wait for elasticsearch to start up!
- #elastic_url = os.getenv("ELASTIC_URI")
- #assert elastic_url
i = 1
while True:
try:
- #client = Elasticsearch(hosts=elastic_url)
client = connections.get_connection()
client.indices.get_alias(index="*")
- #connections.create_connection(hosts=app.config['elastic_uri'])
- #connections.get_connection().cluster.health(wait_for_status='yellow')
- #init_indicies()
print("Elasticsearch found! Run Flask-app!", flush=True)
return
except ConnectionError:
diff --git a/backend/lib/mail.py b/backend/lib/mail.py
index 75ca1fa..bab70d1 100644
--- a/backend/lib/mail.py
+++ b/backend/lib/mail.py
@@ -1,7 +1,6 @@
from smtplib import *
from email.mime.text import MIMEText
-
def send_mail(target_mail, subject, sender_mail, msg):
msg = MIMEText(msg)
diff --git a/backend/lib/webbot.py b/backend/lib/webbot.py
index e0a3c11..42f5f4b 100644
--- a/backend/lib/webbot.py
+++ b/backend/lib/webbot.py
@@ -7,11 +7,9 @@ from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
#from selenium.webdriver.chrome.options import Options
-
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.firefox.service import Service as FirefoxService
-
from tempfile import mkdtemp
from time import sleep
from bs4 import BeautifulSoup
diff --git a/backend/main.py b/backend/main.py
index 96b8355..18caf5b 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,119 +1,151 @@
+
+
+"""
+OpenAPI access via http://localhost:5000/openapi/ on local docker-compose deployment
+"""
+
+#------std lib modules:-------
+import os, sys, json, time
+import os.path
+from typing import Any, Tuple, List, Dict, Any, Callable, Optional
+from datetime import datetime, date
+import logging
+from functools import wraps
+
+#-------ext libs--------------
+
+from elasticsearch_dsl import connections
+
+from pydantic import BaseModel, Field
+import jwt as pyjwt
+
+import asyncio
+
+#----------home grown--------------
+from lib.funcs import group_by
+from lib.elastictools import get_by_id, wait_for_elasticsearch
+from lib.models import init_indicies, Chatbot, User, Text
+from lib.chatbot import ask_bot, ask_bot2, train_text, download_llm
+from lib.speech import text_to_speech
+from lib.mail import send_mail
+from lib.user import hash_password, create_user, create_default_users
+
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
+from fastapi_socketio import SocketManager
+
from jinja2 import Environment, FileSystemLoader
-from pydantic import BaseModel
-
-from neo4j import GraphDatabase
-
-import os, sys
-from multiprocessing import Pool
-from bs4 import BeautifulSoup
-import requests
-from webbot import * #Bot, innerHTML
-from xing import *
-env = Environment(loader=FileSystemLoader('templates'))
+BOT_ROOT_PATH = os.getenv("BOT_ROOT_PATH")
+assert BOT_ROOT_PATH
+
+ollama_url = os.getenv("OLLAMA_URI")
+assert ollama_url
+
+elastic_url = os.getenv("ELASTIC_URI")
+assert elastic_url
+
+jwt_secret = os.getenv("SECRET")
+assert jwt_secret
+
+
+
app = FastAPI()
+socket_manager = SocketManager(app=app)
+
+
+
+@app.sio.on('connect')
+async def sockcon(sid, data):
+ """
+ put every connection into it's own room
+ to avoid broadcasting messages
+ answer in callback only to room with sid
+ """
+ room = request.sid + request.remote_addr
+ join_room(room)
+ await app.sio.emit('backend response', {'msg': f'Connected to room {room} !', "room": room}) # looks like iOS needs an answer
+
+
+
+@app.sio.on('client message')
+async def handle_message(sid, message):
+
+ #try:
+ room = message["room"]
+ question = message["question"]
+ system_prompt = message["system_prompt"]
+ bot_id = message["bot_id"]
+
+ start = datetime.now().timestamp()
+ d = ask_bot2(system_prompt + " " + question, bot_id)
+
+ def get_scores(*args):
+ score_docs = d["get_score_docs"]()
+ return score_docs
+
+
+ def do_streaming(*args):
+ start_stream = datetime.now().timestamp()
+ for chunk in d["answer_generator"]():
+ socket.emit('backend token', {'data': chunk, "done": False}, to=room)
+ stream_duration = round(datetime.now().timestamp() - start_stream, 2)
+ print("Stream duration: ", stream_duration, flush=True)
+
+
+
+ [score_docs, _] = await asyncio.gather(
+ asyncio.to_thread(get_scores, 1,2,3),
+ asyncio.to_thread(do_streaming, 1,2,3)
+ )
+
+
+ await app.sio.emit.emit('backend token', {
+ 'done': True,
+ "score_docs": score_docs
+ }, to=room)
+
+ duration = round(datetime.now().timestamp() - start, 2)
+ print("Total duration: ", duration, flush=True)
+
+
+
+
+
+#@app.sio.on('join')
+#async def handle_join(sid, *args, **kwargs):
+# await app.sio.emit('lobby', 'User joined')
+
+
+#@sm.on('leave')
+#async def handle_leave(sid, *args, **kwargs):
+# await sm.emit('lobby', 'User left')
+
+
+
+
+
+
+
+
class JobSearch(BaseModel):
location: str
language: str
-
-def xing_job_search(location: str, radius: int) -> list:
- with Bot() as bot:
- vars_ = {
- "page": 1,
- "filter.industry%5B%5D": 90000,
- "filter.type%5B%5D": "FULL_TIME",
- "filter.level%5B%5D": 2,
- "location": location,
- "radius": radius
- }
- start_url = "https://www.xing.com/jobs/search?" + "&".join([k + "=" + str(v) for k, v in vars_.items()])
-
-
- def kill_cookie_questions():
- bot.click_id("consent-accept-button")
-
-
- def next_page():
- nav = bot.get_elements_by_tag_name("nav")[1]
- next_site_link = get_elements_by_tag_name(nav, "a")[-1]
- bot.click(next_site_link)
-
- def get_nr_pages():
- nav = bot.get_elements_by_tag_name("nav")[1]
- return int(get_elements_by_tag_name(nav, "a")[-2].text)
-
- def get_items():
- rs = []
- for article in bot.get_elements_by_tag_name("article"):
- rs.append( get_children(article)[0].get_attribute("href") )
- return rs
-
- return collect_pagination_items(bot, start_url, next_page, get_nr_pages, get_items, kill_cookie_questions)
-
-
-
-
-
-"""
-pwd = "neo4j2"
-proto = "bolt"
-host = "192.168.99.101"
-
-driver = GraphDatabase.driver("%s://%s:7687" % (proto, host), auth=("neo4j", pwd), encrypted=False)
-
-def add_friend(tx, name, friend_name):
- tx.run("MERGE (a:Person {name: $name}) "
- "MERGE (a)-[:KNOWS]->(friend:Person {name: $friend_name})",
- name=name, friend_name=friend_name)
-
-def print_friends(tx, name):
- for record in tx.run("MATCH (a:Person)-[:KNOWS]->(friend) WHERE a.name = $name "
- "RETURN friend.name ORDER BY friend.name", name=name):
- print(record["friend.name"])
-
-with driver.session() as session:
- session.write_transaction(add_friend, "Arthur", "Guinevere")
- session.write_transaction(add_friend, "Arthur", "Lancelot")
- session.write_transaction(add_friend, "Arthur", "Merlin")
- session.read_transaction(print_friends, "Arthur")
-
-driver.close()
-"""
-
-
@app.post("/search")
def job_search(js: JobSearch):
-
#https://berlinstartupjobs.com/?s=python&page=3
location = "Berlin"
radius = 50
- with Bot() as bot:
- vars_ = {
- "page": 1,
- "filter.industry%5B%5D": 90000,
- "filter.type%5B%5D": "FULL_TIME",
- "filter.level%5B%5D": 2,
- "location": location,
- "radius": radius
- }
- start_url = "https://www.xing.com/jobs/search?" + "&".join([k + "=" + str(v) for k, v in vars_.items()])
-
- bot.set_url(start_url)
- return bot.get_page_content()
-
-
@app.get("/")
diff --git a/backend/public/index.html b/backend/public/index.html
index fb7b440..32dbe0a 100644
--- a/backend/public/index.html
+++ b/backend/public/index.html
@@ -182,6 +182,8 @@
+
+
@@ -270,11 +272,13 @@
+