gj / frontend /src /App.jsx
gijl's picture
Create frontend/src/App.jsx
cabe16f verified
Raw
History Blame Contribute Delete
3.22 kB
import { useState } from 'react'
const MAX_TOKENS_LIMIT = 60
const EXAMPLES = [
'العلم نور و',
'أفضل طريقة لتعلم البرمجة هي',
'في يوم من الأيام كان هناك',
'الطقس اليوم',
]
function App() {
const [prompt, setPrompt] = useState('')
const [maxTokens, setMaxTokens] = useState(20)
const [output, setOutput] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
async function handleGenerate() {
if (!prompt.trim()) {
setError('اكتب نصاً أولاً')
return
}
setLoading(true)
setError('')
setOutput('')
try {
const res = await fetch('/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt, max_new_tokens: maxTokens }),
})
const data = await res.json()
if (!res.ok) {
throw new Error(data.detail || 'حدث خطأ غير متوقَّع')
}
setOutput(data.output)
} catch (err) {
setError(err.message)
} finally {
setLoading(false)
}
}
function handleKeyDown(e) {
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
handleGenerate()
}
}
return (
<div className="page">
<div className="card">
<header>
<h1>HTDN</h1>
<p className="subtitle">نموذج لغوي عربي تجريبي (~350M معامل)</p>
</header>
<label className="field-label" htmlFor="prompt">
النص المبدئي — اكتب أي جملة تريد
</label>
<textarea
id="prompt"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="اكتب جملة ليكملها النموذج... (Ctrl/Cmd + Enter للتوليد)"
rows={4}
/>
<div className="examples">
{EXAMPLES.map((ex) => (
<button key={ex} className="example-chip" onClick={() => setPrompt(ex)}>
{ex}
</button>
))}
</div>
<div className="controls">
<label htmlFor="tokens">
عدد التوكِنات الجديدة: <strong>{maxTokens}</strong>
</label>
<input
id="tokens"
type="range"
min={1}
max={MAX_TOKENS_LIMIT}
value={maxTokens}
onChange={(e) => setMaxTokens(Number(e.target.value))}
/>
</div>
<button className="generate-btn" onClick={handleGenerate} disabled={loading}>
{loading ? 'جارٍ التوليد...' : 'ولّد النص'}
</button>
{error && <div className="error">{error}</div>}
{output && (
<div className="output">
<h2>الناتج</h2>
<p>{output}</p>
</div>
)}
<p className="note">
توليد greedy بسيط بلا KV-cache — قد يستغرق ثوانٍ، والنتائج أولية بحكم قصر
التدريب.
</p>
</div>
</div>
)
}
export default App