From 7b6f91c1170a293fb9a8ff7a22a81fdb72ee8fb5 Mon Sep 17 00:00:00 2001 From: Patrick_Pluto Date: Fri, 20 Sep 2024 15:46:02 +0200 Subject: [PATCH 1/5] fixed stuff with the backend and the pesky cpython cache --- .gitignore | 1 + py/ai.py | 4 ---- py/api.py | 15 ++++++++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index ea5d9c5..93a7e59 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ next-env.d.ts .idea/ venv/ +__pycache__/ key.pem cert.pem diff --git a/py/ai.py b/py/ai.py index c51f2d2..0a57b57 100644 --- a/py/ai.py +++ b/py/ai.py @@ -12,13 +12,9 @@ class AI: options={"temperature": 0.5}, ) - for i in messages: - print(i) - return_class.ai_response[access_token] = "" for chunk in stream: - print(chunk['message']['content']) return_class.ai_response[access_token] += chunk['message']['content'] @staticmethod diff --git a/py/api.py b/py/api.py index 7b09e1d..646af55 100644 --- a/py/api.py +++ b/py/api.py @@ -26,11 +26,16 @@ class API: def send_ai(): data = request.get_json() messages = data.get('messages') + model_type = data.get('model_type') ai_model = data.get('ai_model') access_token = data.get('access_token') if access_token not in self.ai_response: return jsonify({'status': 401, 'error': 'Invalid access token'}) - self.ai.process_local(ai_model, messages, self, access_token) + + if model_type == "local": + self.ai.process_local(ai_model, messages, self, access_token) + if model_type == "mistral": + self.ai.process_mistralai(ai_model, messages, self, access_token) return jsonify({'status': 200}) @self.app.route('/interstellar/api/ai_get', methods=['GET']) @@ -46,13 +51,13 @@ class API: data = request.args.get('data') if action == "create_account": self.db.add_user(data) - if action == "change_password": + elif action == "change_password": self.db.update_password(data) - if action == "get_data": + elif action == "get_data": self.db.get_data(data) - if action == "change_data": + elif action == "change_data": self.db.change_data(data) - if action == "check_credentials": + elif action == "check_credentials": self.db.check_credentials(data) email_address = "emailAddress" From 6ed98894f33ed364d13f646badd1cb990648629a Mon Sep 17 00:00:00 2001 From: Patrick_Pluto Date: Fri, 20 Sep 2024 15:48:25 +0200 Subject: [PATCH 2/5] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea5d9c5..93a7e59 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ next-env.d.ts .idea/ venv/ +__pycache__/ key.pem cert.pem From 579274000ce6c5e447a8b7ac0d2d5828ede1f394 Mon Sep 17 00:00:00 2001 From: Patrick_Pluto Date: Fri, 20 Sep 2024 15:48:43 +0200 Subject: [PATCH 3/5] Delete py/__pycache__/ai.cpython-312.pyc --- py/__pycache__/ai.cpython-312.pyc | Bin 1927 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 py/__pycache__/ai.cpython-312.pyc diff --git a/py/__pycache__/ai.cpython-312.pyc b/py/__pycache__/ai.cpython-312.pyc deleted file mode 100644 index a1c10a8f80335103a3b77aa85e3690ddecdfa8d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1927 zcmZ`)O=ufO6rR~X$@a>QWXFzwLRHr`75-~YBPfIhr}=RxHMrzr(XuSN>uA?2tvb6V zmXT>GJ_zbSOb>2P)v2^NhxXJSOHPGevcw=UZ6T0S=%FB20fSF{qt(iP>67-&%zJO% zo1OW-*XZIr_qj9H(vxeUjl+eqiPkS^?T zL2!mIaw+j|Hb`L_dEazBqS}jE;0<&u6txl?D1&vB;S65KTWGHpnGs;jofwNnJ|$3Y z{*D$dj73J^;o)ig1!@<07@DS7VU^GTZ3&gIj&)AwP5emMYvtJ#O85r)D2C9c=!s!? zN!)AY!f3lkK)P7sEGhIJww$gW%I6Odn_azdY;QI>#bQr{-Ji7+_Bjz04uxT`BxUPE7aH#|bV5m77 zaSER4CQUv=35B?CE{n9VvlW454r#MD-2p@czP z&w$EAQO(&xaaJ{F3Pl<#5T}{Zb~M%AxG;Zb=9GmUgZmk%Ptl+8f!*Pq;aXy#cJXqp z7xZZ5-6wsozvvJXon@)fjS@rU`QPRE!&e_H)Oi@yB{cU|S*}Ktel%Gb@uM@(FAkS) zvXJpFJN(3GBObXC%bG)kflRK2-+qZ=?AaNXx5@lGD!y5gm}n-TyUwX=0@KM zX0)xB*!*um0Xt&xhtrkb{n+@o@ml}D?#j-}7untXPX1~CMEUk1kGdybNGLH_8Q71f z%F?r; Date: Fri, 20 Sep 2024 16:06:40 +0200 Subject: [PATCH 4/5] It saves data now yay. --- py/api.py | 1 + py/db.py | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/py/api.py b/py/api.py index 646af55..b52870f 100644 --- a/py/api.py +++ b/py/api.py @@ -13,6 +13,7 @@ class API: self.ai_response = {} self.ai = AI() self.db = DB() + self.db.load_database() CORS(self.app) def run(self): diff --git a/py/db.py b/py/db.py index ef82111..76470c9 100644 --- a/py/db.py +++ b/py/db.py @@ -1,5 +1,5 @@ -import json import hashlib +import json class DB: @@ -26,6 +26,7 @@ class DB: return False self.database[username]['data'] = data + self.save_database() return True def update_password(self, data): @@ -36,6 +37,7 @@ class DB: hashed_new_password = self.hash_password(new_password) self.database[username].update({"hashed_password": hashed_new_password}) + self.save_database() return True def check_credentials(self, data): @@ -55,3 +57,14 @@ class DB: send_back = self.database[username].get['data'] return send_back + + def save_database(self): + with open("database.json", 'w') as file: + json.dump(self.database, file) + + def load_database(self): + try: + with open("database.json", 'r') as file: + self.database = json.load(file) + except FileNotFoundError: + pass From a8f9ba27bdd60d77be356edbec7eb5bf74e8ef5d Mon Sep 17 00:00:00 2001 From: Patrick_Pluto Date: Mon, 23 Sep 2024 11:01:39 +0200 Subject: [PATCH 5/5] Fixes and Multithreading --- py/ai.py | 34 +++++++++++++++++++++++++++------- py/api.py | 22 ++++++++++++++++------ py/requirements.txt | 1 + 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/py/ai.py b/py/ai.py index 0a57b57..bfde713 100644 --- a/py/ai.py +++ b/py/ai.py @@ -1,4 +1,5 @@ from mistralai import Mistral +from openai import OpenAI import ollama @@ -12,15 +13,15 @@ class AI: options={"temperature": 0.5}, ) - return_class.ai_response[access_token] = "" + with return_class.ai_response_lock: + return_class.ai_response[access_token] = "" for chunk in stream: - return_class.ai_response[access_token] += chunk['message']['content'] + with return_class.ai_response_lock: + return_class.ai_response[access_token] += chunk['message']['content'] @staticmethod - def process_mistralai(model, messages, return_class, access_token): - with open("api_key.txt", 'r') as f: - api_key = f.read().strip() + def process_mistralai(model, messages, return_class, access_token, api_key): client = Mistral(api_key=api_key) @@ -29,7 +30,26 @@ class AI: messages=messages ) - return_class.ai_response[access_token] = "" + with return_class.ai_response_lock: + return_class.ai_response[access_token] = "" for chunk in stream_response: - return_class.ai_response[access_token] += chunk.data.choices[0].delta.content + with return_class.ai_response_lock: + return_class.ai_response[access_token] += chunk.data.choices[0].delta.content + + @staticmethod + def process_openai(model, messages, return_class, access_token, api_key): + + client = OpenAI(api_key=api_key) + + stream_response = client.chat.completions.create( + model=model, + messages=messages + ) + + with return_class.ai_response_lock: + return_class.ai_response[access_token] = "" + + for chunk in stream_response: + with return_class.ai_response_lock: + return_class.ai_response[access_token] += chunk.choices[0].delta.content \ No newline at end of file diff --git a/py/api.py b/py/api.py index b52870f..386cd4f 100644 --- a/py/api.py +++ b/py/api.py @@ -1,6 +1,7 @@ from flask import Flask, request, jsonify from flask_cors import CORS import secrets +import threading from ai import AI from db import DB from OpenSSL import crypto @@ -8,12 +9,13 @@ from OpenSSL import crypto class API: def __init__(self): - self.crypt_size = 4096 + self.crypt_size = 1 self.app = Flask(__name__) self.ai_response = {} self.ai = AI() self.db = DB() self.db.load_database() + self.ai_response_lock = threading.Lock() CORS(self.app) def run(self): @@ -34,10 +36,18 @@ class API: return jsonify({'status': 401, 'error': 'Invalid access token'}) if model_type == "local": - self.ai.process_local(ai_model, messages, self, access_token) - if model_type == "mistral": - self.ai.process_mistralai(ai_model, messages, self, access_token) - return jsonify({'status': 200}) + thread = threading.Thread(target=self.ai.process_local, args=(ai_model, messages, self, access_token)) + thread.start() + thread.join() + return jsonify({'status': 200}) + elif model_type == "mistral": + api_key = data.get('api_key') + thread = threading.Thread(target=self.ai.process_mistralai, args=(ai_model, messages, self, access_token, api_key)) + thread.start() + thread.join() + return jsonify({'status': 200}) + + return jsonify({'status': 401, 'error': 'Invalid AI model type'}) @self.app.route('/interstellar/api/ai_get', methods=['GET']) def get_ai(): @@ -95,7 +105,7 @@ class API: f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8")) ssl_context = ("cert.pem", "key.pem") - self.app.run(debug=True, host='0.0.0.0', port=5000, ssl_context=ssl_context) + self.app.run(debug=True, host='0.0.0.0', port=5000) if __name__ == '__main__': diff --git a/py/requirements.txt b/py/requirements.txt index 144c571..3c2be3b 100644 --- a/py/requirements.txt +++ b/py/requirements.txt @@ -2,4 +2,5 @@ flask flask-cors ollama mistralai +openai pyOpenSSL \ No newline at end of file