File size: 4,898 Bytes
d85712e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>MEPLIFEOS | FUGTH AI Gateway</title>
  <style>
    :root{color-scheme:dark;font-family:system-ui,-apple-system,Segoe UI,sans-serif}
    *{box-sizing:border-box}body{margin:0;background:#071525;color:#e8f2fc}
    main{max-width:850px;margin:0 auto;padding:36px 18px}
    h1{font-size:clamp(26px,5vw,38px);margin:6px 0}p{color:#a9bfd0;line-height:1.5}
    .top{display:flex;align-items:center;gap:10px;color:#6ee7d7;font-weight:650;letter-spacing:.06em}
    .panel{background:#102237;border:1px solid #294358;border-radius:18px;padding:22px;margin:22px 0}
    .grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}@media(max-width:650px){.grid{grid-template-columns:1fr}}
    label{display:block;font-size:13px;font-weight:650;color:#c0d3e4;margin-bottom:7px}
    input,textarea,select{width:100%;padding:12px;border:1px solid #3a556c;border-radius:9px;background:#08192a;color:white;font:inherit}
    textarea{resize:vertical;min-height:85px}button{background:#33d3bf;color:#032327;border:0;border-radius:10px;padding:12px 20px;font:inherit;font-weight:750;cursor:pointer}
    button:disabled{opacity:.6;cursor:wait}pre{white-space:pre-wrap;overflow-wrap:anywhere;background:#07192a;border:1px solid #334b60;border-radius:10px;padding:15px;min-height:70px;line-height:1.5}
    small{color:#97b3c7}a{color:#66e0cf}.status{font-size:14px;margin:12px 0}
  </style>
</head>
<body><main>
  <div class="top">● FUGTH MANAGEMENT OS / AI INFRASTRUCTURE</div>
  <h1>MEPLIFEOS AI Gateway</h1>
  <p>Two Qwen GGUF models, CPU inference, shared FIFO queue, and request-specific reference context. This is a developer test console, not a public customer chat.</p>
  <div class="panel">
    <h2>Service health</h2>
    <div class="status" id="health">Checking service…</div>
    <button type="button" id="refresh">Refresh status</button>
  </div>
  <div class="panel">
    <h2>Test generation</h2>
    <p>Enter your Space secret <code>FUGTH_API_KEY</code> locally to test. The page does not store it.</p>
    <div class="grid">
      <div><label for="key">API key</label><input id="key" type="password" autocomplete="off" placeholder="Secret from Space settings" /></div>
      <div><label for="model">Model</label><select id="model"><option value="1.5b">Qwen2.5 1.5B (quality)</option><option value="0.5b">Qwen2.5 0.5B (faster)</option></select></div>
      <div><label for="business">Business name</label><input id="business" value="Example Hair Studio" maxlength="120" /></div>
      <div><label for="message">Customer question</label><input id="message" value="What time do you close on Saturday?" maxlength="1200" /></div>
    </div>
    <p><label for="context">Reference information (simulates retrieved RAG context)</label>
    <textarea id="context" maxlength="4000">Opening hours: Monday-Friday 9AM-6PM. Saturday 10AM-3PM. Sunday closed. Walk-ins accepted.</textarea></p>
    <button type="button" id="send">Send test request</button>
    <p><small>Generation may be slow on 2-vCPU free hardware. Requests wait in a bounded queue. For real customers, your FUGTH backend must hold the secret and handle authentication/rate limits.</small></p>
    <h3>Response</h3><pre id="reply">No request yet.</pre>
  </div>
  <p><a href="/docs">API documentation</a> · <a href="https://huggingface.co/spaces/fugthchat/MEPLIFEOS">Space repository</a></p>
</main><script>
  const el = id => document.getElementById(id);
  async function updateHealth(){
    try {
      const r=await fetch('/health',{cache:'no-store'});
      const j=await r.json();
      el('health').textContent=`${j.ready?'READY':'NOT READY'} · Models: ${j.loaded_models.join(', ')||'none'} · In progress: ${j.active_model||'none'} · Waiting: ${j.queued}/${j.max_queue_size} · Key configured: ${j.api_key_configured?'yes':'no'}`;
    }catch(e){el('health').textContent=`Unable to reach service: ${e.message}`;}
  }
  el('refresh').addEventListener('click',updateHealth);
  el('send').addEventListener('click', async ()=>{
    const button=el('send');button.disabled=true;el('reply').textContent='Sending…';
    try {
      const r=await fetch('/v1/chat',{
        method:'POST',
        headers:{'Content-Type':'application/json','X-API-Key':el('key').value},
        body:JSON.stringify({model:el('model').value,business_name:el('business').value,message:el('message').value,context:el('context').value,max_tokens:128})
      });
      const j=await r.json();
      el('reply').textContent=r.ok?`${j.answer}\n\nModel: ${j.model} · Queue: ${j.queue_ms}ms · Inference: ${j.inference_ms}ms`:JSON.stringify(j,null,2);
    }catch(e){el('reply').textContent=`Connection error: ${e.message}`;}
    finally{button.disabled=false;updateHealth();}
  });
  updateHealth();
</script></body></html>