Multimodal-Agent / index.html
VethaNarayananG's picture
Update index.html
df0ccf3 verified
Raw
History Blame Contribute Delete
5.81 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Multimodal Assistant</title>
<style>
body { font-family: 'Segoe UI', sans-serif; max-width: 750px; margin: 30px auto; background:#0f0f0f; color:#eee; }
h2 { text-align:center; }
#chat { border: 1px solid #333; border-radius: 8px; padding: 15px; height: 450px; overflow-y: auto; background:#1a1a1a; }
.msg { margin: 10px 0; line-height:1.4; }
.msg b { color:#7dd3fc; }
.msg.user b { color:#fca5a5; }
.msg img { max-width: 250px; border-radius:6px; display:block; margin-top:6px; }
#controls { display:flex; gap:8px; margin-top:12px; flex-wrap:wrap; }
#userInput { flex:1; padding:10px; border-radius:6px; border:1px solid #333; background:#1a1a1a; color:#eee; min-width:200px; }
button, select { padding:10px 14px; border-radius:6px; border:none; background:#3b82f6; color:white; cursor:pointer; }
button:hover { background:#2563eb; }
#status { font-size:12px; color:#888; margin-top:6px; }
#tokenBar { display:flex; gap:8px; margin-bottom:12px; }
#tokenInput { flex:1; padding:8px; border-radius:6px; border:1px solid #333; background:#1a1a1a; color:#eee; }
</style>
</head>
<body>
<h2>🧠 My Multimodal Assistant</h2>
<div id="tokenBar">
<input type="password" id="tokenInput" placeholder="Paste your HF token here (not saved, session only)">
<button onclick="saveToken()">Set Token</button>
</div>
<div id="chat"></div>
<div id="controls">
<select id="mode">
<option value="chat">💬 Chat / Ask about image</option>
<option value="image">🎨 Generate an image</option>
</select>
<input type="text" id="userInput" placeholder="Type your message...">
<input type="file" id="imageInput" accept="image/*">
<button onclick="send()">Send</button>
</div>
<div id="status"></div>
<script>
let HF_TOKEN = ""; // set at runtime, never committed to the file
function saveToken() {
HF_TOKEN = document.getElementById("tokenInput").value.trim();
document.getElementById("tokenInput").value = "";
document.getElementById("tokenInput").placeholder = HF_TOKEN
? "✅ Token set for this session"
: "Paste your HF token here";
}
const chatBox = document.getElementById("chat");
const statusBox = document.getElementById("status");
let history = [];
function addMessage(role, html) {
const div = document.createElement("div");
div.className = "msg" + (role === "You" ? " user" : "");
div.innerHTML = `<b>${role}:</b> ${html}`;
chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
}
function toBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
async function send() {
if (!HF_TOKEN) {
alert("Please set your Hugging Face token first (top of the page).");
return;
}
const text = document.getElementById("userInput").value.trim();
const file = document.getElementById("imageInput").files[0];
const mode = document.getElementById("mode").value;
if (!text && !file) return;
if (mode === "image") {
await generateImage(text);
} else {
await chatWithModel(text, file);
}
document.getElementById("userInput").value = "";
document.getElementById("imageInput").value = "";
}
async function chatWithModel(text, file) {
let content = [{ type: "text", text: text || "Describe this image." }];
let userDisplay = text;
if (file) {
const base64 = await toBase64(file);
content.push({ type: "image_url", image_url: { url: base64 } });
userDisplay += `<img src="${base64}">`;
}
addMessage("You", userDisplay);
statusBox.textContent = "Thinking...";
const model = file
? "Qwen/Qwen2.5-VL-7B-Instruct"
: "meta-llama/Llama-3.3-70B-Instruct";
history.push({ role: "user", content: content });
try {
const res = await fetch("https://router.huggingface.co/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${HF_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ model: model, messages: history })
});
const data = await res.json();
if (data.error) throw new Error(data.error.message || JSON.stringify(data.error));
const reply = data.choices[0].message.content;
addMessage("AI", reply);
history.push({ role: "assistant", content: reply });
statusBox.textContent = "";
} catch (err) {
addMessage("AI", "⚠️ Error: " + err.message);
statusBox.textContent = "";
}
}
async function generateImage(prompt) {
addMessage("You", prompt);
statusBox.textContent = "Generating image (can take 10–30s)...";
try {
const res = await fetch(
"https://router.huggingface.co/hf-inference/models/black-forest-labs/FLUX.1-schnell",
{
method: "POST",
headers: {
"Authorization": `Bearer ${HF_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ inputs: prompt })
}
);
if (!res.ok) {
const errText = await res.text();
throw new Error(errText);
}
const blob = await res.blob();
const url = URL.createObjectURL(blob);
addMessage("AI", `<img src="${url}">`);
statusBox.textContent = "";
} catch (err) {
addMessage("AI", "⚠️ Error: " + err.message);
statusBox.textContent = "";
}
}
document.getElementById("userInput").addEventListener("keydown", e => {
if (e.key === "Enter") send();
});
</script>
</body>
</html>