|
import React, { useState, useRef } from 'react'; |
|
import { useNavigate } from 'react-router-dom'; |
|
import Box from '@mui/material/Box'; |
|
import Slider from '@mui/material/Slider'; |
|
import Stack from '@mui/material/Stack'; |
|
import Button from '@mui/material/Button'; |
|
import IconButton from '@mui/material/IconButton'; |
|
import './IntialSetting.css'; |
|
import { FaTimes, FaEye, FaEyeSlash } from 'react-icons/fa'; |
|
|
|
function IntialSetting(props) { |
|
|
|
const [selectedProvider, setSelectedProvider] = useState("OpenAI"); |
|
const [modelTemperature, setModelTemperature] = useState(0.0); |
|
const [modelTopP, setModelTopP] = useState(1.0); |
|
const [showPassword, setShowPassword] = useState(false); |
|
|
|
|
|
const formRef = useRef(null); |
|
const navigate = useNavigate(); |
|
|
|
|
|
const modelOptions = { |
|
OpenAI: { |
|
"GPT 4o": "gpt-4o", |
|
"GPT 4o Latest": "gpt-4o-2024-11-20", |
|
"GPT 4o Mini": "gpt-4o-mini", |
|
"GPT 4.1": "gpt-4.1", |
|
"GPT 4.1 Mini": "gpt-4.1-mini", |
|
"GPT 4.1 Nano": "gpt-4.1-nano", |
|
"ChatGPT": "chatgpt-4o-latest" |
|
}, |
|
Anthropic: { |
|
"Claude 4 Opus": "claude-opus-4-20250514", |
|
"Claude Sonnet 4": "claude-sonnet-4-20250514", |
|
"Claude Sonnet 3.7": "claude-3-7-sonnet-20250219", |
|
"Claude Sonnet 3.5": "claude-3-5-sonnet-20241022", |
|
"Claude Haiku 3.5": "claude-3-5-haiku-20241022", |
|
"Claude Opus 3": "claude-3-opus-20240229", |
|
"Claude Sonnet 3": "claude-3-sonnet-20240229", |
|
"Claude Haiku 3": "claude-3-haiku-20240307" |
|
}, |
|
Google: { |
|
"Gemini 2.0 Flash Lite": "gemini-2.0-flash-lite", |
|
"Gemini 2.0 Flash": "gemini-2.0-flash", |
|
"Gemini 2.5 Flash Lite": "gemini-2.5-flash-lite-preview-06-17", |
|
"Gemini 2.5 Flash": "gemini-2.5-flash", |
|
"Gemini 2.5 Pro": "gemini-2.5-pro" |
|
}, |
|
XAI: { |
|
"Grok 2": "grok-2", |
|
"Grok 3 Mini": "grok-3-mini-latest", |
|
"Grok 3 Mini (Fast)": "grok-3-mini-fast-latest", |
|
"Grok 3": "grok-3-latest", |
|
"Grok 3 (Fast)": "grok-3-fast-latest" |
|
}, |
|
}; |
|
|
|
|
|
const handleReset = (e) => { |
|
e.preventDefault(); |
|
if (formRef.current) { |
|
formRef.current.reset(); |
|
} |
|
setSelectedProvider("OpenAI"); |
|
setModelTemperature(0.0); |
|
setModelTopP(1.0); |
|
}; |
|
|
|
|
|
const handleSave = async (e) => { |
|
e.preventDefault(); |
|
const form = formRef.current; |
|
|
|
|
|
const modelProvider = form.elements["model-provider"].value; |
|
const modelName = form.elements["model-name"].value; |
|
const modelAPIKeys = form.elements["model-api"].value; |
|
const braveAPIKey = form.elements["brave-api"].value; |
|
const proxyList = form.elements["proxy-list"].value; |
|
|
|
|
|
const missingFields = []; |
|
if (!modelProvider || modelProvider.trim() === "") missingFields.push("Model Provider"); |
|
if (!modelName || modelName.trim() === "") missingFields.push("Model Name"); |
|
if (!modelAPIKeys || modelAPIKeys.trim() === "") missingFields.push("Model API Key"); |
|
if (!braveAPIKey || braveAPIKey.trim() === "") missingFields.push("Brave Search API Key"); |
|
|
|
if (missingFields.length > 0) { |
|
props.openSnackbar( |
|
"Please fill in the following required fields: " + missingFields.join(", "), |
|
"error" |
|
); |
|
return; |
|
} |
|
|
|
|
|
const payload = { |
|
"Model_Provider": modelProvider.toLowerCase(), |
|
"Model_Name": modelName, |
|
"Model_API_Keys": modelAPIKeys, |
|
"Brave_Search_API_Key": braveAPIKey, |
|
"Model_Temperature": modelTemperature, |
|
"Model_Top_P": modelTopP, |
|
}; |
|
|
|
if (proxyList && proxyList.trim() !== "") { |
|
payload["Proxy_List"] = proxyList; |
|
} |
|
|
|
|
|
if (props.fromAiPage) { |
|
props.openSnackbar( |
|
<Box mt={1} display="flex" alignItems="center"> |
|
<Box className="re-applying-settings-custom-spinner" /> |
|
<Box ml={1} className="re-applying-settings-text"> |
|
<span>Re-applying settings. This may take a few minutes...</span> |
|
</Box> |
|
</Box>, |
|
"info" |
|
); |
|
} else { |
|
props.openSnackbar("Settings saved successfully!", "success"); |
|
if (props.onInitializationStart) { |
|
props.onInitializationStart(); |
|
} |
|
} |
|
|
|
|
|
try { |
|
const response = await fetch("/settings", { |
|
method: "POST", |
|
headers: { |
|
"Content-Type": "application/json", |
|
}, |
|
body: JSON.stringify(payload), |
|
}); |
|
|
|
if (response.ok) { |
|
const data = await response.json(); |
|
if (data.success === true) { |
|
if (props.fromAiPage) { |
|
props.openSnackbar("Settings saved successfully!", "success"); |
|
} |
|
navigate("/AiPage"); |
|
} else { |
|
props.openSnackbar("Error saving settings. Please try again.", "error"); |
|
} |
|
} else { |
|
props.openSnackbar("Error saving settings. Please try again.", "error"); |
|
} |
|
} catch (error) { |
|
console.error("Error saving settings:", error); |
|
props.openSnackbar("Error saving settings. Please try again.", "error"); |
|
} |
|
}; |
|
|
|
|
|
return props.trigger ? ( |
|
<div className="showSetting" onClick={() => props.setTrigger(false)}> |
|
<div className="showSetting-inner" onClick={(e) => e.stopPropagation()}> |
|
<label className="setting-size">Settings</label> |
|
<button className="close-btn" onClick={() => props.setTrigger(false)}> |
|
<FaTimes /> |
|
</button> |
|
<form ref={formRef}> |
|
<div className="form-group"> |
|
<label htmlFor="model-provider">Model Provider</label> |
|
<select |
|
id="model-provider" |
|
name="model-provider" |
|
value={selectedProvider} |
|
onChange={(e) => setSelectedProvider(e.target.value)} |
|
> |
|
{Object.keys(modelOptions).map(provider => ( |
|
<option key={provider} value={provider}> |
|
{provider} |
|
</option> |
|
))} |
|
</select> |
|
</div> |
|
<div className="form-group"> |
|
<label htmlFor="model-name">Model Name</label> |
|
<select id="model-name" name="model-name"> |
|
{Object.entries(modelOptions[selectedProvider]).map( |
|
([displayName, backendName]) => ( |
|
<option key={backendName} value={backendName}> |
|
{displayName} |
|
</option> |
|
) |
|
)} |
|
</select> |
|
</div> |
|
<div className="form-group"> |
|
<label htmlFor="model-api">Model API Key</label> |
|
<textarea |
|
id="model-api" |
|
name="model-api" |
|
placeholder="Enter API Key, one per line" |
|
></textarea> |
|
</div> |
|
<div className="form-group"> |
|
<label htmlFor="brave-api">Brave Search API Key</label> |
|
<input |
|
type="text" |
|
id="brave-api" |
|
name="brave-api" |
|
placeholder="Enter API Key" |
|
/> |
|
</div> |
|
<div className="form-group"> |
|
<label htmlFor="proxy-list">Proxy List</label> |
|
<textarea |
|
id="proxy-list" |
|
name="proxy-list" |
|
placeholder="Enter proxies, one per line" |
|
></textarea> |
|
</div> |
|
{/* Commented Neo4j configuration fields */} |
|
{/* <div className="form-group"> |
|
<label htmlFor="neo4j-url">Neo4j URL</label> |
|
<input |
|
type="text" |
|
id="neo4j-url" |
|
name="neo4j-url" |
|
placeholder="Enter Neo4j URL" |
|
/> |
|
</div> |
|
<div className="form-group"> |
|
<label htmlFor="neo4j-username">Neo4j Username</label> |
|
<input |
|
type="text" |
|
id="neo4j-username" |
|
name="neo4j-username" |
|
placeholder="Enter Username" |
|
/> |
|
</div> |
|
<div className="form-group"> |
|
<label htmlFor="neo4j-password">Neo4j Password</label> |
|
<div className="password-wrapper"> |
|
<input |
|
type={showPassword ? "text" : "password"} |
|
id="neo4j-password" |
|
name="neo4j-password" |
|
placeholder="Enter Password" |
|
/> |
|
<IconButton |
|
onClick={() => setShowPassword(prev => !prev)} |
|
className="password-toggle" |
|
sx={{ |
|
color: "white", |
|
p: 0, |
|
m: 0 |
|
}} |
|
> |
|
{showPassword ? <FaEyeSlash /> : <FaEye />} |
|
</IconButton> |
|
</div> |
|
</div> */} |
|
<div className="form-group"> |
|
<div className="sliders-container"> |
|
<div className="slider-item"> |
|
<label htmlFor="temperature">Temperature</label> |
|
<Slider |
|
id="temperature" |
|
value={modelTemperature} |
|
onChange={(e, newValue) => setModelTemperature(newValue)} |
|
step={0.05} |
|
min={0.0} |
|
max={1.0} |
|
valueLabelDisplay="auto" |
|
sx={{ width: '100%', color: 'success.main' }} |
|
/> |
|
</div> |
|
<div className="slider-item"> |
|
<label htmlFor="top-p">Top-P</label> |
|
<Slider |
|
id="top-p" |
|
value={modelTopP} |
|
onChange={(e, newValue) => setModelTopP(newValue)} |
|
step={0.05} |
|
min={0.0} |
|
max={1.0} |
|
valueLabelDisplay="auto" |
|
sx={{ width: '100%', color: 'success.main' }} |
|
/> |
|
</div> |
|
</div> |
|
</div> |
|
<Stack direction="row" spacing={2} sx={{ justifyContent: 'flex-end' }}> |
|
<Button |
|
type="button" |
|
className="reset-btn" |
|
sx={{ color: "#2196f3" }} |
|
onClick={handleReset} |
|
> |
|
Reset |
|
</Button> |
|
<Button |
|
type="button" |
|
variant="contained" |
|
color="success" |
|
className="save-btn" |
|
onClick={handleSave} |
|
> |
|
Save |
|
</Button> |
|
</Stack> |
|
</form> |
|
{props.children} |
|
</div> |
|
</div> |
|
) : null; |
|
} |
|
|
|
export default IntialSetting; |