diff --git a/app/backend/InputBackend.tsx b/app/backend/InputBackend.tsx new file mode 100644 index 0000000..a00ceeb --- /dev/null +++ b/app/backend/InputBackend.tsx @@ -0,0 +1,86 @@ +import React, { useState } from 'react'; +import InputFrontend from '../components/InputFrontend'; +import ConversationFrontend from '../components/ConversationFrontend'; +import { Mistral } from '@mistralai/mistralai'; + + + +const handleMicClick = () => { + console.log('Mic clicked!'); + // Do something when the mic button is clicked +}; + + +const handleResendClick = () => { + console.log('Resend button clicked'); + // Handle resend action +}; + +const handleEditClick = () => { + console.log('Edit button clicked'); + // Handle edit action +}; + +const handleCopyClick = () => { + console.log('Copy button clicked'); + // Handle copy action +}; + +const InputBackend: React.FC = () => { + async function prompt_mistral(model: string, prompt: string, system: string) { + const apiKey = "m3kZRjN8DRSIo88r8Iti9hmKGWIklrLY"; + + const client = new Mistral({ apiKey: apiKey }); + + var chatResponse = await client.chat.complete({ + model: model, + messages: [{ role: 'user', content: prompt }, { role: 'system', content: system, }], + }); + + if (chatResponse && chatResponse.choices && chatResponse.choices.length > 0) { + if (chatResponse.choices[0].message.content) { + addMessage('AI: ' + chatResponse.choices[0].message.content); + } + } else { + console.error('Error: Unexpected API response:', chatResponse); + } + } + + const handleSendClick = (message: string) => { + var system = "You are a helpful assistant. The following is the chat history." + for (let index = 0; index < messages.length; index++) { + system += messages[index] + " "; + }; + + addMessage('User: ' + message); + prompt_mistral("mistral-large-latest", message, system) + }; + + const [messages, setMessages] = useState([ + 'User: Hello!', + 'AI: Hi there!', + 'User: How are you?', + 'AI: I’m good, thank you!' + ]); + + const addMessage = (message: string) => { + setMessages((prevMessages) => [...prevMessages, message]); + }; + return ( +
+ + +
+ ); +}; + +export default InputBackend; diff --git a/app/backend/InputOutputHandler.tsx b/app/backend/InputOutputHandler.tsx index 02a227b..86bb594 100644 --- a/app/backend/InputOutputHandler.tsx +++ b/app/backend/InputOutputHandler.tsx @@ -3,28 +3,34 @@ import React, { useEffect, useRef, useState } from "react"; import ConversationFrontend from "../components/ConversationFrontend"; import InputFrontend from "../components/InputFrontend"; import axios from "axios"; -import { skip } from "node:test"; const InputOutputBackend: React.FC = () => { type Message = { role: string - content: string + content:string } const [accessToken, setAccessToken] = useState("") - const postWorkerRef = useRef(null) + const postWorkerRef = useRef(null) const getWorkerRef = useRef(null) - const [messages, setMessages] = useState([{ role: "assistant", content: "Hello! How can I help you?" }]) + const [messages, setMessages] = useState([{role:"assistant", content:"Hello! How can I help you?"}]) const [liveMessage, setLiveMessage] = useState("") - const [inputMessage, setInputMessage] = useState("") const [inputDisabled, setInputDisabled] = useState(false) - const [lastMessage, setLastMessage] = useState({ role: "user", content: "Not supposed to happen." }) console.log(messages); - + useEffect(() => { - getNewToken() + console.log("getting access"); + axios.get("http://localhost:5000/interstellar/api/ai_create") + .then(response => { + setAccessToken(response.data.access_token) + console.log(response.data.access_token); + }) + .catch(error => { + console.log("error:", error.message); + + }) postWorkerRef.current = new Worker(new URL("./threads/PostWorker.js", import.meta.url)) @@ -42,7 +48,7 @@ const InputOutputBackend: React.FC = () => { } } } - + return () => { if (postWorkerRef.current) { postWorkerRef.current.terminate() @@ -52,33 +58,20 @@ const InputOutputBackend: React.FC = () => { getWorkerRef.current.terminate() } } - }, []) - - const getNewToken = () => { - console.log("getting access"); - axios.get("http://localhost:5000/interstellar_ai/api/ai_create") - .then(response => { - setAccessToken(response.data.access_token) - console.log(response.data.access_token); - }) - .catch(error => { - console.log("error:", error.message); - - }) - } + },[]) const startGetWorker = () => { if (!getWorkerRef.current) { getWorkerRef.current = new Worker(new URL("./threads/GetWorker.js", import.meta.url)) - - getWorkerRef.current.postMessage({ action: "start", access_token: accessToken }) - - addMessage("assistant", "") + + getWorkerRef.current.postMessage({ action: "start", access_token:accessToken}) + + addMessage("assistant","") getWorkerRef.current.onmessage = (event) => { const data = event.data - + if (event.data == "error") { - setLiveMessage("error getting AI response: " + data.error) + setLiveMessage("error getting AI response: "+ data.error) } else { console.log("Received data:", data); editLastMessage(data.response) @@ -88,12 +81,12 @@ const InputOutputBackend: React.FC = () => { getWorkerRef.current.onerror = (error) => { console.error("Worker error:", error) } - } + } } const endGetWorker = () => { if (getWorkerRef.current) { - getWorkerRef.current.postMessage({ action: "terminate" }) + getWorkerRef.current.postMessage({action:"terminate"}) getWorkerRef.current.terminate() getWorkerRef.current = null console.log(messages); @@ -104,32 +97,31 @@ const InputOutputBackend: React.FC = () => { if (newContent == "") { newContent = "Generating answer..." } - setMessages((prevMessages) => { - const updatedMessages = prevMessages.slice(); // Create a shallow copy of the current messages - if (updatedMessages.length > 0) { - const lastMessage = updatedMessages[updatedMessages.length - 1]; - updatedMessages[updatedMessages.length - 1] = { - ...lastMessage, // Keep the existing role and other properties - content: newContent, // Update only the content - }; - } - return updatedMessages; // Return the updated array - }); - }; + setMessages((prevMessages) => { + const updatedMessages = prevMessages.slice(); // Create a shallow copy of the current messages + if (updatedMessages.length > 0) { + const lastMessage = updatedMessages[updatedMessages.length - 1]; + updatedMessages[updatedMessages.length - 1] = { + ...lastMessage, // Keep the existing role and other properties + content: newContent, // Update only the content + }; + } + return updatedMessages; // Return the updated array + }); +}; const addMessage = (role: string, content: string) => { - setMessages(previous => [...previous, { role, content }]) - } - const handleSendClick = (inputValue: string, override: boolean) => { + setMessages(previous => [...previous,{role,content}]) + } + const handleSendClick = (inputValue: string) => { if (inputValue != "") { - console.log(inputDisabled) - if (!inputDisabled || override) { + if (!inputDisabled) { setInputDisabled(true) if (postWorkerRef.current) { addMessage("user", inputValue) - console.log("input:", inputValue); - postWorkerRef.current.postMessage({ messages: [...messages, { role: "user", content: inputValue }], ai_model: "phi3.5", access_token: accessToken }) + console.log("input:",inputValue); + postWorkerRef.current.postMessage({messages:[...messages, { role: "user", content: inputValue }], ai_model:"phi3.5", access_token:accessToken}) startGetWorker() } } @@ -141,33 +133,18 @@ const InputOutputBackend: React.FC = () => { } const handleResendClick = () => { - var temporary_message = messages[messages.length - 2]['content'] - const updatedMessages = messages.slice(0, -2) - setMessages(updatedMessages) - endGetWorker() - getNewToken() - setInputDisabled(false) - handleSendClick(temporary_message, true) + // do stuff } const handleEditClick = () => { - setInputMessage(messages[messages.length - 2]['content']) - const updatedMessages = messages.slice(0, -2) - setMessages(updatedMessages) - endGetWorker() - getNewToken() - setInputDisabled(false) + // do stuff } - const handleCopyClick = async () => { - try { - await navigator.clipboard.writeText(messages[messages.length - 1]['content']); - } catch (err) { - console.error('Failed to copy: ', err); - } + const handleCopyClick = () => { + // do stuff } - return ( + return (
{ onCopyClick={handleCopyClick} />
- ) + ) } export default InputOutputBackend @@ -191,3 +168,4 @@ export default InputOutputBackend + \ No newline at end of file diff --git a/app/backend/threads/GetWorker.js b/app/backend/threads/GetWorker.js index e035407..fcdcc2f 100644 --- a/app/backend/threads/GetWorker.js +++ b/app/backend/threads/GetWorker.js @@ -3,8 +3,8 @@ import axios from "axios"; let accesstoken onmessage = (event) => { const { action, access_token } = event.data - accesstoken = access_token - + accesstoken=access_token + if (action === "start") { fetchData() } else if (action === "terminate") { @@ -15,20 +15,20 @@ console.log('starting get loop'); const fetchData = () => { console.log(accesstoken); - - - const apiURL = "http://localhost:5000/interstellar_ai/api/ai_get?access_token=" + accesstoken - + + + const apiURL = "http://localhost:5000/interstellar/api/ai_get?access_token="+accesstoken + axios.get(apiURL) .then(response => { const data = response.data console.log(data); postMessage(data) - setTimeout(fetchData, 100) + setTimeout(fetchData,100) }) .catch(error => { console.log('Error fetching data:', error); - postMessage({ error: "failed fetching data" }) - setTimeout(() => fetchData(), 1000) - }) + postMessage({error:"failed fetching data"}) + setTimeout(() => fetchData(),1000) + }) } \ No newline at end of file diff --git a/app/backend/threads/PostWorker.js b/app/backend/threads/PostWorker.js index 1127d0d..d6f6b04 100644 --- a/app/backend/threads/PostWorker.js +++ b/app/backend/threads/PostWorker.js @@ -7,23 +7,23 @@ onmessage = (e) => { const Message = { messages: messages, ai_model: "phi3.5", - model_type: "local", - access_token: access_token + model_type:"local", + access_token:access_token } console.log(Message); + - - axios.post("http://localhost:5000/interstellar_ai/api/ai_send", Message) + axios.post("http://localhost:5000/interstellar/api/ai_send",Message) .then(response => { const status = response.data.status console.log(status); postMessage({ status }) console.log('message posted'); - + }) .catch(error => { console.log("Error calling API:", error) - postMessage({ status: 500 }) - }) + postMessage({status:500}) + }) } \ No newline at end of file diff --git a/app/components/InputFrontend.tsx b/app/components/InputFrontend.tsx index e50e916..f22ee57 100644 --- a/app/components/InputFrontend.tsx +++ b/app/components/InputFrontend.tsx @@ -1,19 +1,16 @@ -import React, { useState, ForwardedRef, useEffect } from 'react'; +import React, { useState, ForwardedRef } from 'react'; interface InputProps { message: string; - onSendClick: (message: string, override: boolean) => void; + onSendClick: (message: string) => void; onMicClick: () => void; - inputDisabled: boolean + inputDisabled:boolean } const InputFrontend = React.forwardRef( ({ message, onSendClick, onMicClick, inputDisabled }, ref: ForwardedRef) => { const [inputValue, setInputValue] = useState(''); - - useEffect(() => { - setInputValue(message); - }, [message]); + const handleInputChange = (e: React.ChangeEvent) => { setInputValue(e.target.value); @@ -22,7 +19,7 @@ const InputFrontend = React.forwardRef( const handleKeyDown = (event: React.KeyboardEvent) => { if (!inputDisabled) { if (event.key === 'Enter') { - onSendClick(inputValue, false); // Call the function passed via props + onSendClick(inputValue); // Call the function passed via props setInputValue(''); // Optionally clear input after submission event.preventDefault(); // Prevent default action (e.g., form submission) } @@ -39,7 +36,7 @@ const InputFrontend = React.forwardRef( onChange={handleInputChange} onKeyDown={handleKeyDown} /> -