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…
Reference in a new issue