diff --git a/.gitignore b/.gitignore index bb3b79a..ea5d9c5 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ venv/ key.pem cert.pem +api_key.txt diff --git a/app/backend/InputOutputHandler.tsx b/app/backend/InputOutputHandler.tsx index cee1d44..ed09bb4 100644 --- a/app/backend/InputOutputHandler.tsx +++ b/app/backend/InputOutputHandler.tsx @@ -27,30 +27,30 @@ const handleCopyClick = () => { const InputOutputBackend: React.FC = () => { const [accessToken, setAccessToken] = useState("") const workerRef = useRef(null) + type Message = { + role: string + content: string + } - const handleSendClick = (message: string) => { - var system = "You give really short answers (maximum of 30 sentences). The following is the chat history." - for (let index = 0; index < messages.length; index++) { - system += messages[index] + " "; - }; + const handleSendClick = (message:string) => { + var system:Message = {role:"system" ,content:"You are a helpful assistant."} - HandlePostRequest(message, "phi3.5", system) - - addMessage('User: ' + message); + addMessage("user", message); + console.log("added User Message") + + HandlePostRequest([...messages, { role: "user", content: message }], "phi3.5", system); }; const [messages, setMessages] = useState([ - 'User: Hello!', - 'AI: Hi there!', - 'User: How are you?', - 'AI: I’m good, thank you!' + { role:"assistant", content:'Hello. I\'m Your AI Virtual Assistant' } ]); - const addMessage = (message: string) => { - setMessages((prevMessages) => [...prevMessages, message]); + const addMessage = (role:string ,content: string) => { + setMessages((prevMessages) => [...prevMessages, {role,content}]); }; + useEffect(() => { workerRef.current = new Worker(new URL("./ProcessAPI.js", import.meta.url)) workerRef.current.postMessage({}) @@ -64,21 +64,12 @@ const InputOutputBackend: React.FC = () => { } } },[]) - - const HandleGetRequest = (message: string, ai_model: string, system_prompt: string) => { - if (workerRef.current) { - workerRef.current.postMessage({ functionName: "getResponse", access_token: accessToken, message: message, ai_model: ai_model, system_prompt: system_prompt }) + + const HandlePostRequest = (messages: Message[], ai_model: string, system_prompt: Message) => { + if (workerRef.current) { + workerRef.current.postMessage({ functionName: "postRequest", access_token: accessToken, messages: messages, ai_model: ai_model, system_prompt: system_prompt }) workerRef.current.onmessage = (e) => { - addMessage("AI: " + e.data) - } - } - } - - const HandlePostRequest = (message: string, ai_model: string, system_prompt: string) => { - if (workerRef.current) { - workerRef.current.postMessage({ functionName: "postRequest", access_token: accessToken, message: message, ai_model: ai_model, system_prompt: system_prompt }) - workerRef.current.onmessage = (e) => { - HandleGetRequest(message,ai_model,system_prompt) + addMessage("assistant",e.data) } } } @@ -97,7 +88,7 @@ const InputOutputBackend: React.FC = () => { onMicClick={handleMicClick} /> - ); + ) } export default InputOutputBackend diff --git a/app/backend/ProcessAPI.js b/app/backend/ProcessAPI.js index c161c62..d02861b 100644 --- a/app/backend/ProcessAPI.js +++ b/app/backend/ProcessAPI.js @@ -1,37 +1,49 @@ import axios from 'axios' +import { type } from 'os'; onmessage = function (e) { - const { functionName = "getAccess", access_token = "", message = "", ai_model = "phi3.5", system_prompt = "You are a helpful assistant" } = e.data - const data = { - "ai_model": ai_model, - "message": message, - "system_prompt": system_prompt, - "access_token": access_token + const { functionName = "getAccess", access_token = "", messages = [], ai_model = "phi3.5", system_prompt = {role:"system" ,content: "You are a helpful assistant that gives short answers"}} = e.data + + let data = { + ai_model: ai_model, + messages: messages, + access_token: access_token }; - switch (functionName) { - case "getAccess": - axios.get('https://127.0.0.1:5000/interstellar/api/ai_create') - .then(Response => { - postMessage(Response.data.access_token) - }).catch(error => { - console.error("Error with GET Token request:", error) - }) - break - case "postRequest": - axios.post('https://127.0.0.1:5000/interstellar/api/ai_send', data) - .then(Response => { - postMessage(Response.data) - }).catch(error => { - console.error("Error:", error) - }) - break - case "getResponse": - axios.get('https://127.0.0.1:5000/interstellar/api/ai_get?access_token=' + access_token) + + const getResponse = () => { + messageComplete:boolean = false + while(!messageComplete) + axios.get('https://localhost:5000/interstellar/api/ai_get?access_token=' + access_token) .then(Response => { postMessage(Response.data.response) + if (Response.data.status == 200) { + messageComplete = true + } }).catch(error => { console.error("Error with GET response request:", error) }) + } + + switch (functionName) { + case "getAccess": + console.log("getting access...") + axios.get('https://localhost:5000/interstellar/api/ai_create') + .then(Response => { + postMessage(Response.data.access_token) + }).catch(error => { + console.error("Error with GET Token request:", error) + }) + break + case "postRequest": + messages.unshift(system_prompt) + console.log("sending...") + console.log(messages) + axios.post('https://localhost:5000/interstellar/api/ai_send', data) + .then(Response => { + getResponse() + }).catch(error => { + console.error("Error:", error) + }) break } diff --git a/app/components/ConversationFrontend.tsx b/app/components/ConversationFrontend.tsx index 80cf49b..00948db 100644 --- a/app/components/ConversationFrontend.tsx +++ b/app/components/ConversationFrontend.tsx @@ -1,7 +1,12 @@ import React, { ForwardedRef, useEffect, useRef } from 'react'; +type Message = { + role: string + content: string +} + interface ConversationProps { - messages: string[]; + messages: Message[]; onResendClick: () => void; onEditClick: () => void; onCopyClick: () => void; @@ -22,14 +27,16 @@ const ConversationFrontend = React.forwardRef
{messages.map((message, index) => { - const isUserMessage = message.startsWith('User:'); - console.log(messages) + let isUserMessage + if (message.role == "user") { + isUserMessage = message + } return (
-

{message}

+

{message.content}

); })} diff --git a/app/components/InputFrontend.tsx b/app/components/InputFrontend.tsx index c3cdea8..cf9dffc 100644 --- a/app/components/InputFrontend.tsx +++ b/app/components/InputFrontend.tsx @@ -14,19 +14,28 @@ const InputFrontend = React.forwardRef( setInputValue(e.target.value); }; + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + onSendClick(inputValue); // Call the function passed via props + setInputValue(''); // Optionally clear input after submission + event.preventDefault(); // Prevent default action (e.g., form submission) + } + }; + return ( -
+
- -
diff --git a/py/.idea/.gitignore b/py/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/py/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/py/.idea/inspectionProfiles/profiles_settings.xml b/py/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/py/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/py/.idea/misc.xml b/py/.idea/misc.xml deleted file mode 100644 index 3671ece..0000000 --- a/py/.idea/misc.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/py/.idea/modules.xml b/py/.idea/modules.xml deleted file mode 100644 index 3a65488..0000000 --- a/py/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/py/.idea/py.iml b/py/.idea/py.iml deleted file mode 100644 index 49f4c24..0000000 --- a/py/.idea/py.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/py/.idea/vcs.xml b/py/.idea/vcs.xml deleted file mode 100644 index 6c0b863..0000000 --- a/py/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/py/__pycache__/ai.cpython-312.pyc b/py/__pycache__/ai.cpython-312.pyc new file mode 100644 index 0000000..a1c10a8 Binary files /dev/null and b/py/__pycache__/ai.cpython-312.pyc differ diff --git a/py/ai.py b/py/ai.py new file mode 100644 index 0000000..c51f2d2 --- /dev/null +++ b/py/ai.py @@ -0,0 +1,39 @@ +from mistralai import Mistral +import ollama + + +class AI: + @staticmethod + def process_local(model, messages, return_class, access_token): + stream = ollama.chat( + model=model, + messages=messages, + stream=True, + 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 + def process_mistralai(model, messages, return_class, access_token): + with open("api_key.txt", 'r') as f: + api_key = f.read().strip() + + client = Mistral(api_key=api_key) + + stream_response = client.chat.stream( + model=model, + messages=messages + ) + + return_class.ai_response[access_token] = "" + + for chunk in stream_response: + return_class.ai_response[access_token] += chunk.data.choices[0].delta.content diff --git a/py/api.py b/py/api.py index 9cf2e63..a5d2a97 100644 --- a/py/api.py +++ b/py/api.py @@ -1,22 +1,8 @@ from flask import Flask, request, jsonify from flask_cors import CORS -import ollama import secrets - - -class AI: - @staticmethod - def process_local(model, messages, return_class, access_token): - stream = ollama.chat( - model=model, - messages=messages, - stream=True, - options={"temperature": 0}, - ) - - for chunk in stream: - print(chunk['message']['content']) - return_class.ai_response[access_token] += chunk['message']['content'] +from ai import AI +from db import DB class API: @@ -24,6 +10,7 @@ class API: self.app = Flask(__name__) self.ai_response = {} self.ai = AI() + self.db = DB() CORS(self.app) def run(self): @@ -51,6 +38,13 @@ class API: return jsonify({'status': 401, 'error': 'Invalid access token'}) return jsonify({'status': 200, 'response': self.ai_response[data]}) + @self.app.route('/interstellar/api/db', methods=['POST']) + def db_manipulate(): + action = request.args.get('action') + if action == "create_account": + print("ahh") + + ssl_context = ('cert.pem', 'key.pem') self.app.run(debug=True, host='0.0.0.0', port=5000, ssl_context=ssl_context) @@ -58,4 +52,3 @@ class API: if __name__ == '__main__': api = API() api.run() - diff --git a/py/db.py b/py/db.py new file mode 100644 index 0000000..5116a93 --- /dev/null +++ b/py/db.py @@ -0,0 +1,41 @@ +import json +import hashlib + + +class DB: + def __init__(self): + self.database = {} + + def _hash_password(self, password: str) -> str: + salt = "your_secret_salt" + hashed_password = hashlib.sha256((password + salt).encode()).hexdigest() + return hashed_password + + def add_user(self, username: str, password: str) -> None: + hashed_password = self._hash_password(password) + user_data = {"hashed_password": hashed_password} + self.database[username] = user_data + + def update_password(self, username: str, old_password: str, new_password: str) -> bool: + if not self.check_credentials(username, old_password): + return False + + hashed_new_password = self._hash_password(new_password) + self.database[username].update({"hashed_password": hashed_new_password}) + return True + + def check_credentials(self, username: str, password: str) -> bool: + if username not in self.database: + return False + + stored_hashed_password = self.database[username]["hashed_password"] + entered_hashed_password = self._hash_password(password) + return stored_hashed_password == entered_hashed_password + + def get_additional_info(self, username: str, password: str) -> dict | None: + if not self.check_credentials(username, password): + return None + + send_back = self.database[username] + del send_back['hashed_password'] + return send_back \ No newline at end of file diff --git a/py/requirements.txt b/py/requirements.txt index 1e95d6f..b4f811a 100644 --- a/py/requirements.txt +++ b/py/requirements.txt @@ -1,3 +1,4 @@ flask flask-cors -ollama \ No newline at end of file +ollama +mistralai \ No newline at end of file