forked from React-Group/interstellar_ai
		
	Merge pull request 'main' (#116) from YasinOnm08/interstellar_ai:main into main
Reviewed-on: https://interstellardevelopment.org/code/code/React-Group/interstellar_ai/pulls/116
This commit is contained in:
		
						commit
						c40d816325
					
				
					 5 changed files with 131 additions and 55 deletions
				
			
		|  | @ -1,30 +1,28 @@ | ||||||
| 
 | 
 | ||||||
| type Message = { | // type Message = {
 | ||||||
|     role: string; | //     role: string;
 | ||||||
|     content:string | //     content:string
 | ||||||
| } | // }
 | ||||||
| 
 | 
 | ||||||
| type Chat = { | // type Chat = {
 | ||||||
|     name: string; | //     name: string;
 | ||||||
|     messages: Message[]; | //     messages: Message[];
 | ||||||
|     timestamp: number; | //     timestamp: number;
 | ||||||
| }; | // };
 | ||||||
| 
 | 
 | ||||||
| export let chatHistory: Chat[] = []; | // export function addMessageToHistory(index: number, chat: Chat): void {
 | ||||||
|  | //     if (index >= 0 && index < chatHistory.length) {
 | ||||||
|  | //         chatHistory[index] = chat;
 | ||||||
|  | //         chatHistory.sort((a, b) => b.timestamp - a.timestamp)  
 | ||||||
|  | //     }
 | ||||||
|  | // }
 | ||||||
| 
 | 
 | ||||||
| export function addMessageToHistory(index: number, chat: Chat): void { | // export function removeMessageFromHistory(timestamp: number): void {
 | ||||||
|     if (index >= 0 && index < chatHistory.length) { | //     const index = chatHistory.findIndex((msg) => msg.timestamp === timestamp);
 | ||||||
|         chatHistory[index] = chat; | //     if (index > -1) {
 | ||||||
|         chatHistory.sort((a, b) => b.timestamp - a.timestamp) | //         chatHistory.splice(index, 1);
 | ||||||
|     } | //         console.log(`Removed message with timestamp: ${timestamp}`);
 | ||||||
| } | //     } else {
 | ||||||
| 
 | //         console.log(`Message not found with timestamp: ${timestamp}`);
 | ||||||
| export function removeMessageFromHistory(timestamp: number): void { | //     }
 | ||||||
|     const index = chatHistory.findIndex((msg) => msg.timestamp === timestamp); | // }
 | ||||||
|     if (index > -1) { |  | ||||||
|         chatHistory.splice(index, 1); |  | ||||||
|         console.log(`Removed message with timestamp: ${timestamp}`); |  | ||||||
|     } else { |  | ||||||
|         console.log(`Message not found with timestamp: ${timestamp}`); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -5,34 +5,26 @@ import InputFrontend from "../components/InputFrontend"; | ||||||
| import { sendToVoiceRecognition } from "./voice_backend" | import { sendToVoiceRecognition } from "./voice_backend" | ||||||
| import axios from "axios"; | import axios from "axios"; | ||||||
| import { changeHistory, checkCredentials, getHistory } from './database'; | import { changeHistory, checkCredentials, getHistory } from './database'; | ||||||
| import { addMessageToHistory, removeMessageFromHistory } from "./ChatHistory"; | import { useChatHistory } from '../hooks/useChatHistory'; | ||||||
| 
 | 
 | ||||||
| interface InputOutputHandlerProps { | const InputOutputBackend: React.FC = () => { | ||||||
|   selectedIndex: number; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const InputOutputBackend: React.FC<InputOutputHandlerProps> = ({selectedIndex}) => { |  | ||||||
|   // # variables
 |   // # variables
 | ||||||
|   type Message = { |   type Message = { | ||||||
|     role: string |     role: string | ||||||
|     content: string |     content: string | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   type Chat = { |  | ||||||
|     name?: string |  | ||||||
|     messages: Message[] |  | ||||||
|     timestamp: string |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // Define state variables for user preferences and messages
 |   // Define state variables for user preferences and messages
 | ||||||
|  |   const [chatHistory, setChatHistory, setSelectedIndex] = useChatHistory() | ||||||
|   const [preferredCurrency, setPreferredCurrency] = useState<string>("USD"); |   const [preferredCurrency, setPreferredCurrency] = useState<string>("USD"); | ||||||
|   const [preferredLanguage, setPreferredLanguage] = useState<string>("english"); |   const [preferredLanguage, setPreferredLanguage] = useState<string>("english"); | ||||||
|   const [timeFormat, setTimeFormat] = useState<string>("24-hour"); |   const [timeFormat, setTimeFormat] = useState<string>("24-hour"); | ||||||
|   const [preferredMeasurement, setPreferredMeasurement] = useState<string>("metric"); |   const [preferredMeasurement, setPreferredMeasurement] = useState<string>("metric"); | ||||||
|   const [timeZone, setTimeZone] = useState<string>("GMT"); |   const [timeZone, setTimeZone] = useState<string>("GMT"); | ||||||
|   const [dateFormat, setDateFormat] = useState<string>("DD-MM-YYYY"); |   const [dateFormat, setDateFormat] = useState<string>("DD-MM-YYYY"); | ||||||
|   const [messages, setMessages] = useState<Message[]>([]); |   const [messages, setMessages] = useState<Message[]>(chatHistory.chats[chatHistory.selectedIndex]?.messages || []); | ||||||
|   const [myBoolean, setMyBoolean] = useState<boolean>(false); |   const [myBoolean, setMyBoolean] = useState<boolean>(false); | ||||||
|  |   const [systemMessage, setSystemMessage] = useState<string>("You are a helpful assistant") | ||||||
|   const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_create") |   const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_create") | ||||||
|   if (typeof window !== 'undefined') { |   if (typeof window !== 'undefined') { | ||||||
|     apiURL.hostname = window.location.hostname; |     apiURL.hostname = window.location.hostname; | ||||||
|  | @ -40,6 +32,23 @@ const InputOutputBackend: React.FC<InputOutputHandlerProps> = ({selectedIndex}) | ||||||
|     apiURL.hostname = "localhost" |     apiURL.hostname = "localhost" | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  | 
 | ||||||
|  |     console.log("History", chatHistory); | ||||||
|  |     console.log("Messages", messages); | ||||||
|  | 
 | ||||||
|  |     // Get the current chat's messages
 | ||||||
|  |     const currentMessages = chatHistory.chats[chatHistory.selectedIndex]?.messages || []; | ||||||
|  | 
 | ||||||
|  |     // If currentMessages is not empty, update messages only if it's not the same
 | ||||||
|  |     if (currentMessages.length > 0 && JSON.stringify(currentMessages) !== JSON.stringify(messages)) { | ||||||
|  |         setMessages(currentMessages); | ||||||
|  |     } else if (messages.length === 0) { | ||||||
|  |         setMessages([{ role: "system", content: systemMessage }, { role: "assistant", content: "Hello! How can I help you?" }]); | ||||||
|  |     } | ||||||
|  | }, [chatHistory, setSelectedIndex]); | ||||||
|  | 
 | ||||||
|   // Update messages when any of the settings change
 |   // Update messages when any of the settings change
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (typeof localStorage !== 'undefined') { |     if (typeof localStorage !== 'undefined') { | ||||||
|  | @ -51,11 +60,14 @@ const InputOutputBackend: React.FC<InputOutputHandlerProps> = ({selectedIndex}) | ||||||
|       setDateFormat(localStorage.getItem("dateFormat") || "DD-MM-YYYY"); |       setDateFormat(localStorage.getItem("dateFormat") || "DD-MM-YYYY"); | ||||||
|       setMyBoolean(localStorage.getItem('myBoolean') === 'true'); |       setMyBoolean(localStorage.getItem('myBoolean') === 'true'); | ||||||
|     } |     } | ||||||
|  |   },[]) | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|     const measurementString = (preferredMeasurement == "Metric") |     const measurementString = (preferredMeasurement == "Metric") | ||||||
|       ? "All measurements follow the metric system. Refuse to use any other measurement system." |       ? "All measurements follow the metric system. Refuse to use any other measurement system." | ||||||
|       : "All measurements follow the imperial system. Refuse to use any other measurement system."; |       : "All measurements follow the imperial system. Refuse to use any other measurement system."; | ||||||
| 
 | 
 | ||||||
|     const systemMessage = myBoolean |     const newSystemMessage = myBoolean | ||||||
|       ? `You are operating in the timezone: ${timeZone}. Use the ${timeFormat} time format and ${dateFormat} for dates. 
 |       ? `You are operating in the timezone: ${timeZone}. Use the ${timeFormat} time format and ${dateFormat} for dates. 
 | ||||||
|       ${measurementString}  |       ${measurementString}  | ||||||
|       The currency is ${preferredCurrency}.  |       The currency is ${preferredCurrency}.  | ||||||
|  | @ -63,12 +75,20 @@ const InputOutputBackend: React.FC<InputOutputHandlerProps> = ({selectedIndex}) | ||||||
|       You are only able to change language if the user specifically states you must.  |       You are only able to change language if the user specifically states you must.  | ||||||
|       Do not answer in multiple languages or multiple measurement systems under any circumstances other than the user requesting it.` |       Do not answer in multiple languages or multiple measurement systems under any circumstances other than the user requesting it.` | ||||||
|       : `You are a helpful assistant`; |       : `You are a helpful assistant`; | ||||||
|     setMessages([ | 
 | ||||||
|       { role: "system", content: systemMessage }, |     setSystemMessage(newSystemMessage) | ||||||
|       { role: "assistant", content: "Hello! How may I help you?" }, |  | ||||||
|     ]); |  | ||||||
|   }, [preferredCurrency, preferredLanguage, timeFormat, preferredMeasurement, timeZone, dateFormat, myBoolean]); |   }, [preferredCurrency, preferredLanguage, timeFormat, preferredMeasurement, timeZone, dateFormat, myBoolean]); | ||||||
| 
 | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     const updateSystemprompt = (prompt: string) => { | ||||||
|  |       setMessages(prevMessages => { | ||||||
|  |         const newMessage = { role: "system", content: prompt } | ||||||
|  |         return [newMessage, ...prevMessages] | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |     updateSystemprompt | ||||||
|  |   },[systemMessage]) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|   const conversationRef = useRef<HTMLDivElement>(null) |   const conversationRef = useRef<HTMLDivElement>(null) | ||||||
|   const [copyClicked, setCopyClicked] = useState(false) |   const [copyClicked, setCopyClicked] = useState(false) | ||||||
|  | @ -180,7 +200,11 @@ const InputOutputBackend: React.FC<InputOutputHandlerProps> = ({selectedIndex}) | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const addMessage = (role: string, content: string) => { |   const addMessage = (role: string, content: string) => { | ||||||
|     setMessages(previous => [...previous, { role, content }]) |     const newMessage: Message = { role: role, content: content } | ||||||
|  |     setMessages((prevMessages) => [...prevMessages, newMessage]) | ||||||
|  |     const updatedChats = [...chatHistory.chats] | ||||||
|  |     updatedChats[chatHistory.selectedIndex].messages.push(newMessage) | ||||||
|  |     setChatHistory({...chatHistory, chats:updatedChats}) | ||||||
|   } |   } | ||||||
|   const handleSendClick = (inputValue: string, override: boolean) => { |   const handleSendClick = (inputValue: string, override: boolean) => { | ||||||
|     if (inputValue != "") { |     if (inputValue != "") { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ import React, { ForwardedRef, useState, useEffect, useRef } from 'react'; | ||||||
| import Markdown from 'react-markdown' | import Markdown from 'react-markdown' | ||||||
| import rehypeRaw from 'rehype-raw'; | import rehypeRaw from 'rehype-raw'; | ||||||
| import remarkGfm from 'remark-gfm'; | import remarkGfm from 'remark-gfm'; | ||||||
|  | import { useChatHistory } from '../hooks/useChatHistory'; | ||||||
| 
 | 
 | ||||||
| type Message = { | type Message = { | ||||||
|   role: string |   role: string | ||||||
|  | @ -21,6 +22,7 @@ const ConversationFrontend = React.forwardRef<HTMLDivElement, ConversationProps> | ||||||
|   ({ messages, onStopClick, onResendClick, onEditClick, onCopyClick, isClicked }, ref: ForwardedRef<HTMLDivElement>) => { |   ({ messages, onStopClick, onResendClick, onEditClick, onCopyClick, isClicked }, ref: ForwardedRef<HTMLDivElement>) => { | ||||||
|     const [isScrolling, setIsScrolling] = useState(true); |     const [isScrolling, setIsScrolling] = useState(true); | ||||||
|     const messagesEndRef = useRef<HTMLDivElement | null>(null); |     const messagesEndRef = useRef<HTMLDivElement | null>(null); | ||||||
|  |     const [chatHistory, setChatHistory, setSelectedIndex] = useChatHistory() | ||||||
| 
 | 
 | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|       const observer = new IntersectionObserver( |       const observer = new IntersectionObserver( | ||||||
|  | @ -61,7 +63,7 @@ const ConversationFrontend = React.forwardRef<HTMLDivElement, ConversationProps> | ||||||
|     return ( |     return ( | ||||||
|       <div className="output" ref={ref}> |       <div className="output" ref={ref}> | ||||||
|         <div className="conversation resize" id="conversation"> |         <div className="conversation resize" id="conversation"> | ||||||
|           {messages.map((message, index) => { |           {chatHistory.chats[chatHistory.selectedIndex].messages.map((message, index) => { | ||||||
|             if (index >= 1) { |             if (index >= 1) { | ||||||
| 
 | 
 | ||||||
|               return ( |               return ( | ||||||
|  |  | ||||||
|  | @ -1,11 +1,8 @@ | ||||||
| import React, { useState } from 'react'; | import React, { useState } from 'react'; | ||||||
|  | import { useChatHistory } from '../hooks/useChatHistory'; | ||||||
| 
 | 
 | ||||||
| interface HistoryProps{ | const History: React.FC = () => { | ||||||
|   selectedIndex: number; |   const [chatHistory, setChatHistory, setSelectedIndex] = useChatHistory() | ||||||
|   setSelectedIndex: (index: number) => void; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const History: React.FC<HistoryProps> = ({selectedIndex, setSelectedIndex}) => { |  | ||||||
| 
 | 
 | ||||||
|   const handleHistoryClick = (index: number) => { |   const handleHistoryClick = (index: number) => { | ||||||
|     setSelectedIndex(index) |     setSelectedIndex(index) | ||||||
|  | @ -16,9 +13,9 @@ const History: React.FC<HistoryProps> = ({selectedIndex, setSelectedIndex}) => { | ||||||
|       <div className="history"> |       <div className="history"> | ||||||
|         <ul> |         <ul> | ||||||
|           {/* Populate with history items */} |           {/* Populate with history items */} | ||||||
|           {Array.from({ length: 20 }, (_, index) => ( |           {chatHistory.chats.map((chats, index) => ( | ||||||
|             <li key={index}> |             <li key={index}> | ||||||
|               <a href="#" onClick={()=>handleHistoryClick(index)}>history{index + 1}</a> |               <a href="#" onClick={() => handleHistoryClick(index)}>{chatHistory.chats[index].name}</a> | ||||||
|             </li> |             </li> | ||||||
|           ))} |           ))} | ||||||
|         </ul> |         </ul> | ||||||
|  |  | ||||||
							
								
								
									
										55
									
								
								app/hooks/useChatHistory.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								app/hooks/useChatHistory.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | import { useEffect, useState } from "react" | ||||||
|  | 
 | ||||||
|  | interface Message { | ||||||
|  |     role: string | ||||||
|  |     content:string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface ChatMessages { | ||||||
|  |     name: string | ||||||
|  |     messages: Message[] | ||||||
|  |     timestamp: number | ||||||
|  |      | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface GlobalChatHistory { | ||||||
|  |     chats: ChatMessages[] | ||||||
|  |     selectedIndex: number | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | let globalChatHistory: GlobalChatHistory = { | ||||||
|  |     chats: [ | ||||||
|  |         { name: "Chat 1", messages: [], timestamp: 4 } | ||||||
|  |     ], | ||||||
|  |     selectedIndex:0 | ||||||
|  | } | ||||||
|  | let listeners: ((state: GlobalChatHistory) => void)[] = [] | ||||||
|  | 
 | ||||||
|  | const setGlobalState = (newState: GlobalChatHistory): void => { | ||||||
|  |     globalChatHistory = newState; | ||||||
|  |     listeners.forEach((listener) => listener(globalChatHistory)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const useChatHistory = (): [GlobalChatHistory, (newState:GlobalChatHistory) => void, (index:number)=>void] => { | ||||||
|  |     const [state, setState] = useState<GlobalChatHistory>(globalChatHistory) | ||||||
|  | 
 | ||||||
|  |     useEffect(() => { | ||||||
|  |         console.log("help", globalChatHistory); | ||||||
|  |          | ||||||
|  |         const listener = (newState: GlobalChatHistory) => { | ||||||
|  |             setState(newState) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         listeners.push(listener) | ||||||
|  | 
 | ||||||
|  |         return () => { | ||||||
|  |             listeners = listeners.filter((l) => l!== listener) | ||||||
|  |         } | ||||||
|  |     }, []) | ||||||
|  | 
 | ||||||
|  |     const setSelectedIndex = (index: number) => { | ||||||
|  |         setGlobalState({...state,selectedIndex:index}) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return [state, setGlobalState, setSelectedIndex] | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue