Making UI progress; seeding lkml RAG
This commit is contained in:
parent
b25498f6a0
commit
1c56814a92
14
lkml/init.sh
Normal file
14
lkml/init.sh
Normal file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
fail() {
|
||||
echo "FAIL: ${*}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
for i in {8..16}; do
|
||||
if [[ -d "${i}" ]]; then
|
||||
echo "Skipping lkml/git/$i -- already exists"
|
||||
else
|
||||
cmd="git clone https://erol.kernel.org/lkml/git/$i"
|
||||
${cmd} || fail "cmd"
|
||||
fi
|
||||
done
|
@ -10,22 +10,13 @@ div {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.Container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: auto;
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
border: 1px solid green;
|
||||
max-width: 80%;
|
||||
height: 100vh;
|
||||
}
|
||||
.ChatBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
border: 1px solid red;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.Controls {
|
||||
|
@ -2,9 +2,8 @@ import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import FormGroup from '@mui/material/FormGroup';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
import Switch from '@mui/material/Switch';
|
||||
import Card from '@mui/material/Card';
|
||||
import CardHeader from '@mui/material/CardHeader';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import Snackbar, { SnackbarCloseReason } from '@mui/material/Snackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import Accordion from '@mui/material/Accordion';
|
||||
import AccordionActions from '@mui/material/AccordionActions';
|
||||
@ -13,7 +12,13 @@ import AccordionDetails from '@mui/material/AccordionDetails';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import Button from '@mui/material/Button';
|
||||
import Container from '@mui/material/Container';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Box from '@mui/material/Box';
|
||||
import CssBaseline from '@mui/material/CssBaseline';
|
||||
|
||||
import PropagateLoader from "react-spinners/PropagateLoader";
|
||||
import Markdown from 'react-markdown';
|
||||
@ -45,12 +50,15 @@ type Tool = {
|
||||
enabled: boolean
|
||||
};
|
||||
|
||||
type SeverityType = 'error' | 'info' | 'success' | 'warning' | undefined;
|
||||
|
||||
interface ControlsParams {
|
||||
sessionId: string,
|
||||
connectionBase: string
|
||||
connectionBase: string,
|
||||
setSnack: (snackMessage: string, snackSeverity?: SeverityType) => void
|
||||
};
|
||||
|
||||
const Controls = ({ sessionId, connectionBase }: ControlsParams) => {
|
||||
const Controls = ({ sessionId, connectionBase, setSnack }: ControlsParams) => {
|
||||
const [systemPrompt, setSystemPrompt] = useState<string>("");
|
||||
const [editSystemPrompt, setEditSystemPrompt] = useState<string>(systemPrompt);
|
||||
|
||||
@ -68,7 +76,6 @@ const Controls = ({ sessionId, connectionBase }: ControlsParams) => {
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
setSystemPrompt(data["system-prompt"]);
|
||||
setEditSystemPrompt(data["system-prompt"]);
|
||||
}
|
||||
@ -119,9 +126,11 @@ const Controls = ({ sessionId, connectionBase }: ControlsParams) => {
|
||||
console.log(data);
|
||||
if (data["system-prompt"] !== systemPrompt) {
|
||||
setSystemPrompt(data["system-prompt"].trim());
|
||||
setSnack("System prompt updated", "success");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fetch error:', error);
|
||||
setSnack("System prompt update failed", "error");
|
||||
}
|
||||
};
|
||||
|
||||
@ -142,6 +151,7 @@ const Controls = ({ sessionId, connectionBase }: ControlsParams) => {
|
||||
setEditSystemPrompt(systemPrompt)
|
||||
} catch (error) {
|
||||
console.error('Fetch error:', error);
|
||||
setSnack("Unable to fetch system prompt", "error");
|
||||
}
|
||||
};
|
||||
|
||||
@ -227,6 +237,19 @@ const App = () => {
|
||||
const [processing, setProcessing] = useState(false);
|
||||
const [sessionId, setSessionId] = useState<string | undefined>(undefined);
|
||||
const [loc,] = useState<Location>(window.location)
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
const [isClosing, setIsClosing] = useState(false);
|
||||
const [snackOpen, setSnackOpen] = useState(false);
|
||||
const [snackMessage, setSnackMessage] = useState("");
|
||||
const [snackSeverity, setSnackSeverity] = useState<SeverityType>("success");
|
||||
|
||||
useEffect(() => {
|
||||
if (snackMessage === "") {
|
||||
setSnackOpen(false);
|
||||
} else {
|
||||
setSnackOpen(true);
|
||||
}
|
||||
}, [snackMessage, setSnackOpen]);
|
||||
|
||||
// Scroll to bottom of conversation when conversation updates
|
||||
useEffect(() => {
|
||||
@ -269,6 +292,32 @@ const App = () => {
|
||||
|
||||
}, [setSessionId, loc]);
|
||||
|
||||
const setSnack = (message: string, severity: SeverityType = "success") => {
|
||||
setSnackMessage(message);
|
||||
setSnackSeverity(severity);
|
||||
}
|
||||
|
||||
const handleDrawerClose = () => {
|
||||
setIsClosing(true);
|
||||
setMobileOpen(false);
|
||||
};
|
||||
|
||||
const handleDrawerTransitionEnd = () => {
|
||||
setIsClosing(false);
|
||||
};
|
||||
|
||||
const handleDrawerToggle = () => {
|
||||
if (!isClosing) {
|
||||
setMobileOpen(!mobileOpen);
|
||||
}
|
||||
};
|
||||
|
||||
const drawer = (
|
||||
<>
|
||||
{sessionId !== undefined && <Controls setSnack={setSnack} sessionId={sessionId} connectionBase={getConnectionBase(loc)} />}
|
||||
</>
|
||||
);
|
||||
|
||||
const handleKeyPress = (event: any) => {
|
||||
if (event.key === 'Enter') {
|
||||
switch (event.target.id) {
|
||||
@ -298,6 +347,8 @@ const App = () => {
|
||||
const sendQuery = async () => {
|
||||
if (!query.trim()) return;
|
||||
|
||||
setSnack("Query sent", "info");
|
||||
|
||||
const userMessage = [{ role: 'user', content: query }];
|
||||
|
||||
// Add user message to conversation
|
||||
@ -431,6 +482,7 @@ const App = () => {
|
||||
setProcessing(false);
|
||||
} catch (error) {
|
||||
console.error('Fetch error:', error);
|
||||
setSnack("Unable to process query", "error");
|
||||
setConversation(prev => [
|
||||
...prev.filter(msg => !msg.isProcessing),
|
||||
{ role: 'assistant', type: 'error', content: `Error: ${error}` }
|
||||
@ -439,16 +491,80 @@ const App = () => {
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Container className="Container">
|
||||
const handleSnackClose = (
|
||||
event: React.SyntheticEvent | Event,
|
||||
reason?: SnackbarCloseReason,
|
||||
) => {
|
||||
setSnackMessage("");
|
||||
|
||||
<div className="ChatBox">
|
||||
<div className="Conversation" ref={conversationRef}>
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
|
||||
setSnackOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', height: 1 }}>
|
||||
<CssBaseline />
|
||||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
zIndex: (theme) => theme.zIndex.drawer + 1,
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
edge="start"
|
||||
onClick={handleDrawerToggle}
|
||||
sx={{ mr: 2 }}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" noWrap component="div">
|
||||
Ketr-Chat
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box
|
||||
component="nav"
|
||||
aria-label="mailbox folders"
|
||||
>
|
||||
{/* The implementation can be swapped with js to avoid SEO duplication of links. */}
|
||||
<Drawer
|
||||
container={window.document.body}
|
||||
variant="temporary"
|
||||
open={mobileOpen}
|
||||
onTransitionEnd={handleDrawerTransitionEnd}
|
||||
onClose={handleDrawerClose}
|
||||
sx={{
|
||||
display: 'block',
|
||||
'& .MuiDrawer-paper': { boxSizing: 'border-box' },
|
||||
}}
|
||||
slotProps={{
|
||||
root: {
|
||||
keepMounted: true, // Better open performance on mobile.
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toolbar />
|
||||
{drawer}
|
||||
</Drawer>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
component="main"
|
||||
sx={{ flexGrow: 1, p: 3, height: '100vh' }}
|
||||
className="ChatBox">
|
||||
<Toolbar />
|
||||
|
||||
<Box className="Conversation"
|
||||
sx={{ flexGrow: 1, p: 3 }}
|
||||
ref={conversationRef}>
|
||||
{conversation.map((message, index) => {
|
||||
const formattedContent = message.content
|
||||
.split("\n")
|
||||
.map((line) => line.replace(/^[^\s:]+:\s*/, ''))
|
||||
.join("\n");
|
||||
const formattedContent = message.content.trim();
|
||||
|
||||
return (
|
||||
<div key={index} className={message.role === 'user' ? 'user-message' : 'assistant-message'}>
|
||||
@ -491,9 +607,9 @@ const App = () => {
|
||||
data-testid="loader"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
<div className="Query" style={{ display: "flex", flexDirection: "row" }}>
|
||||
<Box className="Query" style={{ display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
disabled={processing}
|
||||
@ -509,11 +625,19 @@ const App = () => {
|
||||
<AccordionActions>
|
||||
<Button variant="contained" onClick={sendQuery}>Send</Button>
|
||||
</AccordionActions>
|
||||
</div>
|
||||
</div>
|
||||
{sessionId !== undefined && <Controls sessionId={sessionId} connectionBase={getConnectionBase(loc)} />}
|
||||
|
||||
</Container>
|
||||
</Box>
|
||||
</Box>
|
||||
<Snackbar open={snackOpen} autoHideDuration={snackSeverity === "success" ? 1500 : 6000} onClose={handleSnackClose}>
|
||||
<Alert
|
||||
onClose={handleSnackClose}
|
||||
severity={snackSeverity}
|
||||
variant="filled"
|
||||
sx={{ width: '100%' }}
|
||||
>
|
||||
{snackMessage}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</Box >
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -373,7 +373,6 @@ class WebServer:
|
||||
async def get_system_prompt(context_id: str):
|
||||
context = self.upsert_context(context_id)
|
||||
system_prompt = context["system"][0]["content"];
|
||||
logging.info(f"returning system prompt as '{system_prompt}'")
|
||||
return JSONResponse({ "system-prompt": system_prompt })
|
||||
|
||||
@self.app.post('/api/chat/{context_id}')
|
||||
|
Loading…
x
Reference in New Issue
Block a user