ling-3.0-flash / index.html
akhaliq's picture
akhaliq HF Staff
Use Inclusion AI logo image directly; drop nav links
224dd80
Raw
History Blame Contribute Delete
12.5 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Ling 3.0 Flash — Inclusion AI</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Instrument+Serif:ital@0;1&display=swap" rel="stylesheet">
<style>
:root{
--bg:#ffffff;
--bg-soft:#f7f8fa;
--bg-softer:#fbfcfd;
--panel:#ffffff;
--fg:#0b0d12;
--fg-muted:#5b6473;
--fg-faint:#9aa3b2;
--border:#e6e8ec;
--border-strong:#d4d8df;
--accent-1:#7BB8FF;
--accent-2:#3B82F6;
--user:#f3f5f9;
--assistant:#ffffff;
--reason:#f7faff;
--shadow:0 1px 2px rgba(15,18,30,.04), 0 8px 24px rgba(15,18,30,.04);
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0; font-family:"Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background:var(--bg); color:var(--fg);
display:flex; flex-direction:column;
-webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
/* Top nav */
header{
position:sticky; top:0; z-index:10;
padding:18px 28px;
display:flex; align-items:center; gap:36px;
background:rgba(255,255,255,.85);
backdrop-filter:saturate(180%) blur(12px);
-webkit-backdrop-filter:saturate(180%) blur(12px);
border-bottom:1px solid var(--border);
}
.brand{display:flex; align-items:center; gap:10px}
.brand-mark{height:28px; width:auto; display:block}
.spacer{flex:1}
.controls{display:flex; align-items:center; gap:14px}
.switch{display:flex; align-items:center; gap:8px; font-size:13px; color:var(--fg-muted); user-select:none; cursor:pointer}
.switch input{accent-color:var(--accent-2); width:14px; height:14px}
.btn{
appearance:none; border:1px solid var(--border-strong); background:var(--panel);
color:var(--fg); padding:8px 14px; border-radius:999px; font-size:13px; font-weight:500; cursor:pointer;
transition:background .15s, border-color .15s;
}
.btn:hover{background:var(--bg-soft); border-color:var(--fg-faint)}
.btn.primary{
background:linear-gradient(135deg,var(--accent-1),var(--accent-2));
color:#fff; border:none; padding:10px 18px; font-weight:600;
box-shadow:0 4px 14px rgba(59,130,246,.25);
}
.btn.primary:hover{filter:brightness(1.05)}
.btn:disabled{opacity:.5; cursor:not-allowed}
/* Hero (empty state) */
main{flex:1; overflow-y:auto; padding:24px 0 32px}
.wrap{max-width:760px; margin:0 auto; padding:0 24px; display:flex; flex-direction:column; gap:22px}
.hero{padding:80px 8px 40px; display:flex; flex-direction:column; align-items:flex-start; gap:14px}
.hero .plus{color:var(--fg-faint); font-size:18px; font-weight:500; letter-spacing:.02em}
.hero h1{
font-family:"Instrument Serif", "Times New Roman", serif;
font-weight:400; font-size:clamp(40px, 7vw, 72px); line-height:.98; letter-spacing:-.02em;
margin:0; color:var(--fg);
}
.hero h1 em{font-style:italic; font-family:"Instrument Serif", serif}
.hero .sub{font-size:22px; color:var(--fg-muted); font-weight:400; margin:6px 0 0}
.hero .accent{
background:linear-gradient(135deg,var(--accent-1),var(--accent-2));
-webkit-background-clip:text; background-clip:text; color:transparent;
}
.chips{display:flex; flex-wrap:wrap; gap:10px; margin-top:18px}
.chip{
background:var(--bg-soft); border:1px solid var(--border); color:var(--fg);
padding:9px 14px; border-radius:999px; font-size:13.5px; cursor:pointer;
transition:background .15s, border-color .15s;
}
.chip:hover{background:var(--user); border-color:var(--border-strong)}
/* Messages */
.msg{display:flex; flex-direction:column; gap:8px; max-width:100%}
.who{font-size:12px; color:var(--fg-faint); font-weight:500; padding:0 4px; letter-spacing:.02em}
.bubble{
padding:14px 18px; border-radius:16px; line-height:1.6; font-size:15.5px;
white-space:pre-wrap; word-wrap:break-word;
border:1px solid var(--border); background:var(--panel);
}
.user .bubble{background:var(--user); border-color:var(--border); border-top-right-radius:6px}
.assistant .bubble{background:var(--assistant); border-color:var(--border); border-top-left-radius:6px; box-shadow:var(--shadow)}
.reasoning{
background:var(--reason); border:1px solid var(--border);
border-radius:12px; padding:12px 16px; color:var(--fg-muted); font-size:13.5px; line-height:1.55;
}
.reasoning summary{cursor:pointer; color:var(--fg); font-weight:600; user-select:none; display:flex; align-items:center; gap:8px}
.reasoning summary::before{content:""; width:8px; height:8px; border-radius:50%; background:linear-gradient(135deg,var(--accent-1),var(--accent-2))}
.reasoning .rbody{margin-top:10px; white-space:pre-wrap; color:var(--fg-muted)}
.typing{display:inline-flex; gap:5px; padding:2px 0}
.typing span{width:7px; height:7px; border-radius:50%; background:var(--fg-faint); animation:bk 1s infinite}
.typing span:nth-child(2){animation-delay:.2s}.typing span:nth-child(3){animation-delay:.4s}
@keyframes bk{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
/* Composer */
footer{border-top:1px solid var(--border); background:rgba(255,255,255,.85); backdrop-filter:saturate(180%) blur(12px); padding:16px 24px}
.composer{max-width:760px; margin:0 auto; display:flex; gap:10px; align-items:flex-end}
.composer textarea{
flex:1; resize:none; max-height:180px; min-height:56px;
padding:16px 18px; border-radius:14px; border:1px solid var(--border-strong);
background:var(--panel); color:var(--fg); font:inherit; font-size:15px; outline:none;
transition:border-color .15s, box-shadow .15s;
}
.composer textarea:focus{border-color:var(--accent-2); box-shadow:0 0 0 3px rgba(59,130,246,.15)}
.err{color:#dc2626; font-size:13px; max-width:760px; margin:0 auto 6px; padding:0 24px}
@media (max-width:640px){
header{padding:14px 18px; gap:18px}
nav{display:none}
.hero{padding:48px 4px 28px}
}
</style>
</head>
<body>
<header>
<div class="brand">
<img class="brand-mark" src="https://www.inclusion-ai.org/img/logo_head.png" alt="Inclusion AI" />
</div>
<div class="spacer"></div>
<div class="controls">
<label class="switch"><input type="checkbox" id="reason-toggle" checked /> Reasoning</label>
<button class="btn" id="clear-btn">Clear</button>
</div>
</header>
<main><div class="wrap" id="chat">
<div class="hero" id="hero">
<div class="plus">+</div>
<h1>AI BUILT<br/>BY <span class="accent">EVERYONE</span></h1>
<div class="sub">For Everyone · Try Ling 3.0 Flash with reasoning.</div>
<div class="chips">
<div class="chip" data-q="How many r's are in the word 'strawberry'?">Count the r's in strawberry</div>
<div class="chip" data-q="Explain the Monty Hall problem in 3 lines.">Explain the Monty Hall problem</div>
<div class="chip" data-q="Write a haiku about recursion.">Haiku about recursion</div>
<div class="chip" data-q="What is 17 * 23? Show your reasoning step by step.">17 × 23 with reasoning</div>
</div>
</div>
</div></main>
<footer>
<div class="err" id="err"></div>
<div class="composer">
<textarea id="input" rows="1" placeholder="Ask Ling 3.0 Flash anything…"></textarea>
<button class="btn primary" id="send">Send</button>
</div>
</footer>
<script type="module">
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
const client = await Client.connect(window.location.origin);
const chatEl = document.getElementById("chat");
const input = document.getElementById("input");
const sendBtn = document.getElementById("send");
const reasonToggle = document.getElementById("reason-toggle");
const errEl = document.getElementById("err");
const clearBtn = document.getElementById("clear-btn");
// History is preserved across turns. Assistant turns carry reasoning_details
// so the model continues reasoning from where it left off.
const history = [];
let busy = false;
input.addEventListener("input", () => {
input.style.height = "auto";
input.style.height = Math.min(input.scrollHeight, 180) + "px";
});
input.addEventListener("keydown", (e) => {
if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); }
});
sendBtn.addEventListener("click", send);
clearBtn.addEventListener("click", () => {
history.length = 0;
renderHero();
});
document.querySelectorAll(".chip").forEach(c => {
c.addEventListener("click", () => {
input.value = c.dataset.q;
input.dispatchEvent(new Event("input"));
input.focus();
});
});
function renderHero(){
chatEl.innerHTML = `<div class="hero">
<div class="plus">+</div>
<h1>AI BUILT<br/>BY <span class="accent">EVERYONE</span></h1>
<div class="sub">For Everyone · Try Ling 3.0 Flash with reasoning.</div>
<div class="chips">
<div class="chip" data-q="How many r's are in the word 'strawberry'?">Count the r's in strawberry</div>
<div class="chip" data-q="Explain the Monty Hall problem in 3 lines.">Explain the Monty Hall problem</div>
<div class="chip" data-q="Write a haiku about recursion.">Haiku about recursion</div>
<div class="chip" data-q="What is 17 * 23? Show your reasoning step by step.">17 × 23 with reasoning</div>
</div>
</div>`;
chatEl.querySelectorAll(".chip").forEach(c => {
c.addEventListener("click", () => {
input.value = c.dataset.q;
input.dispatchEvent(new Event("input"));
input.focus();
});
});
}
function escapeHtml(s){
return String(s).replace(/[&<>"']/g, c =>
({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
}
function addMessage(role, content, reasoning){
const hero = chatEl.querySelector(".hero");
if (hero) hero.remove();
const msg = document.createElement("div");
msg.className = `msg ${role}`;
const who = role === "user" ? "YOU" : "LING 3.0 FLASH";
let rhtml = "";
if (reasoning){
rhtml = `<details class="reasoning"><summary>Reasoning</summary><div class="rbody">${escapeHtml(reasoning)}</div></details>`;
}
msg.innerHTML = `<div class="who">${who}</div>${rhtml}<div class="bubble">${escapeHtml(content)}</div>`;
chatEl.appendChild(msg);
chatEl.parentElement.scrollTop = chatEl.parentElement.scrollHeight;
return msg;
}
function setThinking(el){
el.innerHTML = `<div class="who">LING 3.0 FLASH</div><div class="bubble"><span class="typing"><span></span><span></span><span></span></span></div>`;
chatEl.parentElement.scrollTop = chatEl.parentElement.scrollHeight;
}
async function send(){
if (busy) return;
const text = input.value.trim();
if (!text) return;
errEl.textContent = "";
input.value = ""; input.style.height = "auto";
busy = true; sendBtn.disabled = true;
history.push({ role: "user", content: text });
addMessage("user", text);
const asstMsg = addMessage("assistant", "");
setThinking(asstMsg);
try {
const res = await client.predict("/chat", {
messages: history, reasoning: reasonToggle.checked,
});
const data = res.data[0];
const content = data.content || "";
const reasoning = data.reasoning || "";
let reasoningDetails = data.reasoning_details;
if (reasoningDetails && typeof reasoningDetails === "string"){
try { reasoningDetails = JSON.parse(reasoningDetails); } catch {}
}
let rhtml = "";
if (reasoning){
rhtml = `<details class="reasoning"><summary>Reasoning</summary><div class="rbody">${escapeHtml(reasoning)}</div></details>`;
}
asstMsg.innerHTML = `<div class="who">LING 3.0 FLASH</div>${rhtml}<div class="bubble">${escapeHtml(content)}</div>`;
history.push({
role: "assistant",
content,
reasoning_details: reasoningDetails,
});
chatEl.parentElement.scrollTop = chatEl.parentElement.scrollHeight;
} catch (e) {
errEl.textContent = "Error: " + (e?.message || String(e));
chatEl.removeChild(asstMsg);
history.pop();
} finally {
busy = false; sendBtn.disabled = false; input.focus();
}
}
input.focus();
</script>
</body>
</html>