import React, { useState, useEffect, ReactElement } from 'react'; // import FormGroup from '@mui/material/FormGroup'; // import FormControlLabel from '@mui/material/FormControlLabel'; // import Switch from '@mui/material/Switch'; // import Divider from '@mui/material/Divider'; // import TextField from '@mui/material/TextField'; import Accordion from '@mui/material/Accordion'; import AccordionActions from '@mui/material/AccordionActions'; import AccordionSummary from '@mui/material/AccordionSummary'; import AccordionDetails from '@mui/material/AccordionDetails'; import Typography from '@mui/material/Typography'; // import Button from '@mui/material/Button'; // import Box from '@mui/material/Box'; // import ResetIcon from '@mui/icons-material/History'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { connectionBase } from '../utils/Global'; import { BackstoryPageProps } from '../components/BackstoryTab'; interface ServerTunables { system_prompt: string, tools: Tool[], rags: Tool[] }; type Tool = { type: string, enabled: boolean name: string, description: string, parameters?: any, returns?: any }; type GPUInfo = { name: string, memory: number, discrete: boolean } type SystemInfo = { "Installed RAM": string, "Graphics Card": GPUInfo[], "CPU": string }; const SystemInfoComponent: React.FC<{ systemInfo: SystemInfo | undefined }> = ({ systemInfo }) => { const [systemElements, setSystemElements] = useState([]); const convertToSymbols = (text: string) => { return text .replace(/\(R\)/g, '®') // Replace (R) with the ® symbol .replace(/\(C\)/g, '©') // Replace (C) with the © symbol .replace(/\(TM\)/g, '™'); // Replace (TM) with the ™ symbol }; useEffect(() => { if (systemInfo === undefined) { return; } const elements = Object.entries(systemInfo).flatMap(([k, v]) => { // If v is an array, repeat for each card if (Array.isArray(v)) { return v.map((card, index) => (
{convertToSymbols(k)} {index}
{convertToSymbols(card.name)} {card.discrete ? `w/ ${Math.round(card.memory / (1024 * 1024 * 1024))}GB RAM` : "(integrated)"}
)); } // If it's not an array, handle normally return (
{convertToSymbols(k)}
{convertToSymbols(String(v))}
); }); setSystemElements(elements); }, [systemInfo]); return
{systemElements}
; }; const ControlsPage = (props: BackstoryPageProps) => { const { setSnack } = props; const [editSystemPrompt, setEditSystemPrompt] = useState(""); const [systemInfo, setSystemInfo] = useState(undefined); const [tools, setTools] = useState([]); const [rags, setRags] = useState([]); const [systemPrompt, setSystemPrompt] = useState(""); const [messageHistoryLength, setMessageHistoryLength] = useState(5); const [serverTunables, setServerTunables] = useState(undefined); useEffect(() => { if (serverTunables === undefined || systemPrompt === serverTunables.system_prompt || !systemPrompt.trim()) { return; } const sendSystemPrompt = async (prompt: string) => { try { const response = await fetch(connectionBase + `/api/1.0/tunables`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ "system_prompt": prompt }), }); const tunables = await response.json(); serverTunables.system_prompt = tunables.system_prompt; console.log(tunables); setSystemPrompt(tunables.system_prompt) setSnack("System prompt updated", "success"); } catch (error) { console.error('Fetch error:', error); setSnack("System prompt update failed", "error"); } }; sendSystemPrompt(systemPrompt); }, [systemPrompt, setSnack, serverTunables]); const reset = async (types: ("rags" | "tools" | "history" | "system_prompt")[], message: string = "Update successful.") => { try { const response = await fetch(connectionBase + `/api/1.0/reset/`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ "reset": types }), }); if (!response.ok) { throw new Error(`Server responded with ${response.status}: ${response.statusText}`); } if (!response.body) { throw new Error('Response body is null'); } const data = await response.json(); if (data.error) { throw Error(data.error); } for (const [key, value] of Object.entries(data)) { switch (key) { case "rags": setRags(value as Tool[]); break; case "tools": setTools(value as Tool[]); break; case "system_prompt": setSystemPrompt((value as ServerTunables)["system_prompt"].trim()); break; case "history": console.log('TODO: handle history reset'); break; } } setSnack(message, "success"); } catch (error) { console.error('Fetch error:', error); setSnack("Unable to restore defaults", "error"); } }; // Get the system information useEffect(() => { if (systemInfo !== undefined) { return; } const fetchSystemInfo = async () => { try { const response = await fetch(connectionBase + `/api/1.0/system-info`, { method: 'GET', headers: { 'Content-Type': 'application/json', }, }) if (!response.ok) { throw new Error(`Server responded with ${response.status}: ${response.statusText}`); } if (!response.body) { throw new Error('Response body is null'); } const data = await response.json(); if (data.error) { throw Error(data.error); } setSystemInfo(data); } catch (error) { console.error('Error obtaining system information:', error); setSnack("Unable to obtain system information.", "error"); }; } fetchSystemInfo(); }, [systemInfo, setSystemInfo, setSnack]) useEffect(() => { if (!systemPrompt) { return; } setEditSystemPrompt(systemPrompt.trim()); }, [systemPrompt, setEditSystemPrompt]); const toggleRag = async (tool: Tool) => { tool.enabled = !tool.enabled try { const response = await fetch(connectionBase + `/api/1.0/tunables`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ "rags": [{ "name": tool?.name, "enabled": tool.enabled }] }), }); const tunables: ServerTunables = await response.json(); setRags(tunables.rags) setSnack(`${tool?.name} ${tool.enabled ? "enabled" : "disabled"}`); } catch (error) { console.error('Fetch error:', error); setSnack(`${tool?.name} ${tool.enabled ? "enabling" : "disabling"} failed.`, "error"); tool.enabled = !tool.enabled } }; const toggleTool = async (tool: Tool) => { tool.enabled = !tool.enabled try { const response = await fetch(connectionBase + `/api/1.0/tunables`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ "tools": [{ "name": tool.name, "enabled": tool.enabled }] }), }); const tunables: ServerTunables = await response.json(); setTools(tunables.tools) setSnack(`${tool.name} ${tool.enabled ? "enabled" : "disabled"}`); } catch (error) { console.error('Fetch error:', error); setSnack(`${tool.name} ${tool.enabled ? "enabling" : "disabling"} failed.`, "error"); tool.enabled = !tool.enabled } }; // If the systemPrompt has not been set, fetch it from the server useEffect(() => { if (serverTunables !== undefined) { return; } const fetchTunables = async () => { try { // Make the fetch request with proper headers const response = await fetch(connectionBase + `/api/1.0/tunables`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, }); const data = await response.json(); // console.log("Server tunables: ", data); setServerTunables(data); setSystemPrompt(data["system_prompt"]); setTools(data["tools"]); setRags(data["rags"]); } catch (error) { console.error('Fetch error:', error); setSnack("System prompt update failed", "error"); } } fetchTunables(); }, [setServerTunables, setSystemPrompt, setMessageHistoryLength, serverTunables, setTools, setRags, setSnack]); const toggle = async (type: string, index: number) => { switch (type) { case "rag": if (rags === undefined) { return; } toggleRag(rags[index]) break; case "tool": if (tools === undefined) { return; } toggleTool(tools[index]); } }; const handleKeyPress = (event: any) => { if (event.key === 'Enter' && event.ctrlKey) { setSystemPrompt(editSystemPrompt); } }; return (
{/* You can change the information available to the LLM by adjusting the following settings: }> System Prompt setEditSystemPrompt(e.target.value)} onKeyDown={handleKeyPress} placeholder="Enter the new system prompt.." /> }> Tunables setMessageHistoryLength(e.target.value)} slotProps={{ htmlInput: { min: 0 }, inputLabel: { shrink: true, }, }} /> }> Tools These tools can be made available to the LLM for obtaining real-time information from the Internet. The description provided to the LLM is provided for reference. { (tools || []).map((tool, index) => } onChange={() => toggle("tool", index)} label={tool.name} /> {tool.description} ) } }> RAG These RAG databases can be enabled / disabled for adding additional context based on the chat request. { (rags || []).map((rag, index) => } onChange={() => toggle("rag", index)} label={rag.name} /> {rag.description} ) } */} }> System Information The server is running on the following hardware: {/* */}
); } export { ControlsPage };