Switching to CRUD instead of ws://
This commit is contained in:
parent
1343557f3d
commit
2393c74890
@ -1,2 +1,3 @@
|
|||||||
*
|
*
|
||||||
!src
|
!src
|
||||||
|
**/node_modules
|
||||||
|
@ -9,6 +9,23 @@ div {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ChatBox {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: "row";
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Controls {
|
||||||
|
display: flex;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
border: 1px solid #E0E0E0;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 10px;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@ -42,14 +59,13 @@ div {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversation {
|
.Conversation {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #F5F5F5;
|
background-color: #F5F5F5;
|
||||||
border: 1px solid #E0E0E0;
|
border: 1px solid #E0E0E0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin-bottom: 20px;
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,14 +2,31 @@ import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|||||||
import PropagateLoader from "react-spinners/PropagateLoader";
|
import PropagateLoader from "react-spinners/PropagateLoader";
|
||||||
import Markdown from 'react-markdown';
|
import Markdown from 'react-markdown';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import remarkGfm from 'remark-gfm'
|
|
||||||
import rehypeKatex from 'rehype-katex'
|
import rehypeKatex from 'rehype-katex'
|
||||||
import remarkMath from 'remark-math'
|
import remarkMath from 'remark-math'
|
||||||
import 'katex/dist/katex.min.css' // `rehype-katex` does not import the CSS for you
|
import 'katex/dist/katex.min.css' // `rehype-katex` does not import the CSS for you
|
||||||
|
|
||||||
const welcome_message = "Welcome to Ketr-Chat. I have real-time access to a lot of information. Ask things like 'What are the headlines from cnn.com?' or 'What is the weather in Portland, OR?'";
|
const welcome_message = "Welcome to Ketr-Chat. I have real-time access to a lot of information. Ask things like 'What are the headlines from cnn.com?' or 'What is the weather in Portland, OR?'";
|
||||||
|
|
||||||
const url: string = "https://ai.ketrenos.com"
|
//const url: string = "https://ai.ketrenos.com"
|
||||||
|
|
||||||
|
const getConnectionBase = (url: string): string => {
|
||||||
|
console.log(url);
|
||||||
|
if (!url.match(/.*battle-linux.*/)) {
|
||||||
|
return url;
|
||||||
|
} else {
|
||||||
|
return 'battle-linux.ketrenos.com:5000';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Controls = () => {
|
||||||
|
const tools = ["get_stock_price", "get_weather", "site_summary", "RAG JPK", "RAG LKML"]
|
||||||
|
return (<div className="Controls">{
|
||||||
|
tools.map((tool, index) => {
|
||||||
|
return (<div key={index}>{tool}</div>);
|
||||||
|
})
|
||||||
|
}</div>);
|
||||||
|
}
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
@ -20,9 +37,7 @@ const App = () => {
|
|||||||
const [loaded, setLoaded] = useState<boolean>(false);
|
const [loaded, setLoaded] = useState<boolean>(false);
|
||||||
const [connection, setConnection] = useState<any | undefined>(undefined);
|
const [connection, setConnection] = useState<any | undefined>(undefined);
|
||||||
const [sessionId, setSessionId] = useState<string | undefined>(undefined);
|
const [sessionId, setSessionId] = useState<string | undefined>(undefined);
|
||||||
const [users, setUsers] = useState<string[]>([]);
|
const [loc,] = useState<Location>(window.location)
|
||||||
const [user, setUser] = useState<string>("");
|
|
||||||
const [userChange, setUserChange] = useState<string>("");
|
|
||||||
|
|
||||||
// Scroll to bottom of conversation when conversation updates
|
// Scroll to bottom of conversation when conversation updates
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -37,7 +52,12 @@ const App = () => {
|
|||||||
|
|
||||||
if (!pathParts.length) {
|
if (!pathParts.length) {
|
||||||
console.log("No session id -- creating a new session")
|
console.log("No session id -- creating a new session")
|
||||||
fetch('/api/session')
|
fetch(loc.protocol + "//" + getConnectionBase(loc.host) + `/api/context`, {
|
||||||
|
method: 'CREATE',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log(`Session id: ${data.id} -- returned from server`)
|
console.log(`Session id: ${data.id} -- returned from server`)
|
||||||
@ -50,7 +70,7 @@ const App = () => {
|
|||||||
setSessionId(pathParts[0]);
|
setSessionId(pathParts[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [setSessionId]);
|
}, [setSessionId, loc.host, loc.protocol]);
|
||||||
|
|
||||||
const onWsOpen = (event: any) => {
|
const onWsOpen = (event: any) => {
|
||||||
console.log(`ws: open`);
|
console.log(`ws: open`);
|
||||||
@ -101,22 +121,6 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'user':
|
|
||||||
if (!loaded) {
|
|
||||||
setLoaded(true);
|
|
||||||
}
|
|
||||||
setUser(data.update);
|
|
||||||
console.log(`user = ${data.update}`)
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'users':
|
|
||||||
if (!loaded) {
|
|
||||||
setLoaded(true);
|
|
||||||
}
|
|
||||||
setUsers(data.update);
|
|
||||||
console.log(`users = ${data.update}`)
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'processing':
|
case 'processing':
|
||||||
console.log(`processing = ${data.value}`)
|
console.log(`processing = ${data.value}`)
|
||||||
setProcessing(data.value);
|
setProcessing(data.value);
|
||||||
@ -185,14 +189,14 @@ const App = () => {
|
|||||||
let socket = ws;
|
let socket = ws;
|
||||||
|
|
||||||
if (!socket && !connection) {
|
if (!socket && !connection) {
|
||||||
let loc = window.location, new_uri;
|
let new_uri;
|
||||||
if (loc.protocol === "https:") {
|
if (loc.protocol === "https:") {
|
||||||
new_uri = "wss://";
|
new_uri = "wss://";
|
||||||
} else {
|
} else {
|
||||||
new_uri = "ws://";
|
new_uri = "ws://";
|
||||||
}
|
}
|
||||||
new_uri += loc.host + `/api/ws/${sessionId}`;
|
let host = getConnectionBase(loc.host)
|
||||||
//new_uri += `battle-linux.ketrenos.com:5000/api/ws/${sessionId}`;
|
new_uri += host + `/api/ws/${sessionId}`;
|
||||||
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
console.log(`Attempting WebSocket connection to ${new_uri}`);
|
||||||
socket = new WebSocket(new_uri)
|
socket = new WebSocket(new_uri)
|
||||||
setWs(socket);
|
setWs(socket);
|
||||||
@ -223,7 +227,7 @@ const App = () => {
|
|||||||
ws.removeEventListener('message', cbMessage);
|
ws.removeEventListener('message', cbMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [ setWs, connection, setConnection, sessionId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
|
}, [setWs, connection, setConnection, sessionId, ws, refWsOpen, refWsMessage, refWsClose, refWsError, loc.host, loc.protocol]);
|
||||||
|
|
||||||
const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
@ -231,9 +235,6 @@ const App = () => {
|
|||||||
case 'query-input':
|
case 'query-input':
|
||||||
sendQuery();
|
sendQuery();
|
||||||
break;
|
break;
|
||||||
case 'user-input':
|
|
||||||
sendUserChange();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -267,7 +268,7 @@ const App = () => {
|
|||||||
try {
|
try {
|
||||||
setProcessing(true);
|
setProcessing(true);
|
||||||
// Send query to server
|
// Send query to server
|
||||||
const response = await fetch(`/api/chat/${sessionId}`, {
|
const response = await fetch(loc.protocol + "//" + getConnectionBase(loc.host) + `/api/chat/${sessionId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -291,78 +292,60 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendUserChange = async () => {
|
|
||||||
if (!userChange.trim()) return;
|
|
||||||
|
|
||||||
setUserChange('');
|
|
||||||
|
|
||||||
connection.send(JSON.stringify({
|
|
||||||
session: sessionId,
|
|
||||||
type: 'user-change',
|
|
||||||
value: userChange
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container" style={{ display: "flex", flexDirection: "column" }}>
|
<div className="container" style={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
|
||||||
<div className="conversation" ref={conversationRef}>
|
<div className="ChatBox">
|
||||||
{conversation.map((message, index) => {
|
<div className="Conversation" ref={conversationRef}>
|
||||||
const formattedContent = message.content
|
{conversation.map((message, index) => {
|
||||||
.split("\n")
|
const formattedContent = message.content
|
||||||
.map((line) => line.replace(/^[^\s:]+:\s*/, ''))
|
.split("\n")
|
||||||
.join("\n");
|
.map((line) => line.replace(/^[^\s:]+:\s*/, ''))
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index} className={message.role === 'user' ? 'user-message' : 'assistant-message'}>
|
<div key={index} className={message.role === 'user' ? 'user-message' : 'assistant-message'}>
|
||||||
{message.metadata ? (
|
{message.metadata ? (
|
||||||
<>
|
<>
|
||||||
<div className="metadata">{message.metadata.title}</div>
|
<div className="metadata">{message.metadata.title}</div>
|
||||||
{message.user && (
|
|
||||||
<div>{message.user}</div>
|
|
||||||
)}
|
|
||||||
{message.role === 'assistant' ? (
|
|
||||||
<div className="markdown-content">
|
|
||||||
<Markdown remarkPlugins={[remarkMath]} rehypePlugins={[rehypeKatex]} children={formattedContent} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div>{formattedContent}</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{message.user && (
|
{message.user && (
|
||||||
<div>{message.user}</div>
|
<div>{message.user}</div>
|
||||||
)}
|
)}
|
||||||
{message.role === 'assistant' ? (
|
{message.role === 'assistant' ? (
|
||||||
<div className="markdown-content">
|
<div className="markdown-content">
|
||||||
<Markdown remarkPlugins={[remarkMath]} rehypePlugins={[rehypeKatex]} children={formattedContent} />
|
<Markdown remarkPlugins={[remarkMath]} rehypePlugins={[rehypeKatex]} children={formattedContent} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>{formattedContent}</div>
|
<div>{formattedContent}</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
) : (
|
||||||
</div>
|
<>
|
||||||
);
|
{message.user && (
|
||||||
})}
|
<div>{message.user}</div>
|
||||||
<div style={{ justifyContent: "center", display: "flex", paddingBottom: "0.5rem" }}>
|
)}
|
||||||
<PropagateLoader
|
{message.role === 'assistant' ? (
|
||||||
size="10px"
|
<div className="markdown-content">
|
||||||
loading={processing}
|
<Markdown remarkPlugins={[remarkMath]} rehypePlugins={[rehypeKatex]} children={formattedContent} />
|
||||||
aria-label="Loading Spinner"
|
</div>
|
||||||
data-testid="loader"
|
) : (
|
||||||
/>
|
<div>{formattedContent}</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</>
|
||||||
|
)}
|
||||||
<div className="users" style={{ display: "flex", flexDirection: "row" }}>
|
</div>
|
||||||
<div>Users in this session: </div>
|
);
|
||||||
{users.map((name, index) => (
|
})}
|
||||||
<div key={index} className={user === name ? `user-active` : `user`}>
|
<div style={{ justifyContent: "center", display: "flex", paddingBottom: "0.5rem" }}>
|
||||||
{name}
|
<PropagateLoader
|
||||||
|
size="10px"
|
||||||
|
loading={processing}
|
||||||
|
aria-label="Loading Spinner"
|
||||||
|
data-testid="loader"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
</div>
|
||||||
|
<Controls />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="query-box">
|
<div className="query-box">
|
||||||
@ -377,19 +360,6 @@ const App = () => {
|
|||||||
/>
|
/>
|
||||||
<button onClick={sendQuery}>Send</button>
|
<button onClick={sendQuery}>Send</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="user-box">
|
|
||||||
<input
|
|
||||||
disabled={connection ? false : true}
|
|
||||||
type="text"
|
|
||||||
value={userChange}
|
|
||||||
onChange={(e) => setUserChange(e.target.value)}
|
|
||||||
onKeyDown={handleKeyPress}
|
|
||||||
placeholder="Change your name..."
|
|
||||||
id="user-input"
|
|
||||||
/>
|
|
||||||
<button onClick={sendUserChange}>Send</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,9 @@ body {
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user