Sunhey Cho
Add frontend source code structure for direct development
9aee46b
raw
history blame
4.12 kB
import React, { useState } from 'react';
import {
Paper,
Typography,
Grid,
TextField,
Button,
Divider
} from '@material-ui/core';
function OpenAIChat() {
const [model, setModel] = useState('gpt-4o-mini');
const [apiKey, setApiKey] = useState('');
const [system, setSystem] = useState('You are a helpful assistant.');
const [prompt, setPrompt] = useState('');
const [response, setResponse] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const onSend = async () => {
setError('');
setResponse('');
const p = (prompt || '').trim();
if (!p) { setError('Please enter a question.'); return; }
setLoading(true);
try {
const res = await fetch('/api/openai/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
prompt: p,
model: (model || '').trim() || 'gpt-4o-mini',
api_key: (apiKey || undefined),
system: (system || undefined)
})
});
if (!res.ok) {
let txt = await res.text();
try { txt = JSON.stringify(JSON.parse(txt), null, 2); } catch {}
throw new Error(txt);
}
const data = await res.json();
const meta = `Model: ${data.model} | Latency: ${data.latency_sec}s` + (data.usage ? ` | Usage: ${JSON.stringify(data.usage)}` : '');
setResponse((data.response || '(Empty response)') + '\n\n---\n' + meta);
} catch (e) {
setError('Error: ' + e.message);
} finally {
setLoading(false);
}
};
const onClear = () => {
setPrompt('');
setResponse('');
setError('');
};
return (
<Paper style={{ padding: 16 }}>
<Typography variant="h5" gutterBottom>
OpenAI Chat (OpenAI API)
</Typography>
<Typography variant="body2" color="textSecondary" gutterBottom>
If the server env var OPENAI_API_KEY is set, the API Key field is optional.
</Typography>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<TextField
label="Model"
value={model}
onChange={(e) => setModel(e.target.value)}
fullWidth
variant="outlined"
size="small"
/>
</Grid>
<Grid item xs={12} md={6}>
<TextField
label="OpenAI API Key (optional)"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
fullWidth
variant="outlined"
size="small"
type="password"
placeholder="sk-..."
/>
</Grid>
<Grid item xs={12}>
<TextField
label="System Prompt (optional)"
value={system}
onChange={(e) => setSystem(e.target.value)}
fullWidth
variant="outlined"
size="small"
/>
</Grid>
<Grid item xs={12}>
<TextField
label="User Question"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
fullWidth
multiline
rows={4}
variant="outlined"
/>
</Grid>
{error && (
<Grid item xs={12}>
<Typography color="error">{error}</Typography>
</Grid>
)}
<Grid item xs={12}>
<div style={{ display: 'flex', gap: 8 }}>
<Button color="primary" variant="contained" onClick={onSend} disabled={loading}>
{loading ? 'Sending...' : 'Send Question'}
</Button>
<Button variant="outlined" onClick={onClear}>Clear</Button>
</div>
</Grid>
<Grid item xs={12}>
<Divider style={{ margin: '12px 0' }} />
<Typography variant="subtitle2" color="textSecondary">Response</Typography>
<pre style={{ whiteSpace: 'pre-wrap', fontFamily: 'ui-monospace, monospace' }}>{response}</pre>
</Grid>
</Grid>
</Paper>
);
}
export default OpenAIChat;