feat(ai): refine chat UX and add AI roadmap view
This commit is contained in:
parent
113cade1b2
commit
370007813d
@ -126,26 +126,26 @@ export function fallbackServices() {
|
||||
name: "AI Chat",
|
||||
category: "ai",
|
||||
summary: "LLM chat (public beta)",
|
||||
link: "/ai",
|
||||
link: "/ai/chat",
|
||||
host: "chat.ai.bstein.dev",
|
||||
status: "live",
|
||||
},
|
||||
{
|
||||
name: "AI Image",
|
||||
category: "ai",
|
||||
summary: "Visualization tool - Planned",
|
||||
link: "/ai",
|
||||
host: "draw.ai.bstein.dev",
|
||||
status: "planned",
|
||||
},
|
||||
{
|
||||
name: "AI Speech",
|
||||
category: "ai",
|
||||
summary: "Live Translation - Planned",
|
||||
link: "/ai",
|
||||
host: "talk.ai.bstein.dev",
|
||||
status: "planned",
|
||||
},
|
||||
{
|
||||
name: "AI Image",
|
||||
category: "ai",
|
||||
summary: "Visualization tool - Planned",
|
||||
link: "/ai/roadmap",
|
||||
host: "draw.ai.bstein.dev",
|
||||
status: "planned",
|
||||
},
|
||||
{
|
||||
name: "AI Speech",
|
||||
category: "ai",
|
||||
summary: "Live Translation - Planned",
|
||||
link: "/ai/roadmap",
|
||||
host: "talk.ai.bstein.dev",
|
||||
status: "planned",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from "vue-router";
|
||||
import HomeView from "./views/HomeView.vue";
|
||||
import AboutView from "./views/AboutView.vue";
|
||||
import AiView from "./views/AiView.vue";
|
||||
import AiPlanView from "./views/AiPlanView.vue";
|
||||
import MoneroView from "./views/MoneroView.vue";
|
||||
|
||||
export default createRouter({
|
||||
@ -9,7 +10,9 @@ export default createRouter({
|
||||
routes: [
|
||||
{ path: "/", name: "home", component: HomeView },
|
||||
{ path: "/about", name: "about", component: AboutView },
|
||||
{ path: "/ai", name: "ai", component: AiView },
|
||||
{ path: "/ai", redirect: "/ai/chat" },
|
||||
{ path: "/ai/chat", name: "ai-chat", component: AiView },
|
||||
{ path: "/ai/roadmap", name: "ai-roadmap", component: AiPlanView },
|
||||
{ path: "/monero", name: "monero", component: MoneroView },
|
||||
],
|
||||
});
|
||||
|
||||
89
frontend/src/views/AiPlanView.vue
Normal file
89
frontend/src/views/AiPlanView.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<section class="card hero glass">
|
||||
<div>
|
||||
<p class="eyebrow">Atlas AI</p>
|
||||
<h1>Roadmap</h1>
|
||||
<p class="lede">
|
||||
Chat is live today. Image generation and speech / translation will roll out next. This page tracks what’s planned and
|
||||
what hardware it will land on.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card grid">
|
||||
<div class="track">
|
||||
<div class="pill mono">AI Image</div>
|
||||
<h3>Visualization</h3>
|
||||
<p class="text">
|
||||
Goal: small, fast image generation for diagrams, thumbnails, and mockups. Targeting Jetson nodes once stable. Output
|
||||
will be gated to members only.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Models: open-source SD/FLUX variants distilled for 16GB GPUs.</li>
|
||||
<li>Pipeline: upload prompt → queued job → signed URL in Nextcloud.</li>
|
||||
<li>Status: planned (no UI yet).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="track">
|
||||
<div class="pill mono">AI Speech</div>
|
||||
<h3>Voice + Translation</h3>
|
||||
<p class="text">
|
||||
Goal: low-latency ASR + TTS for meetings and media. Results should stream back into apps like Jitsi and Pegasus.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Models: whisper-style ASR, lightweight TTS with multilingual support.</li>
|
||||
<li>Targets: titan-20/21 Jetsons for acceleration; fall back to CPU-only if needed.</li>
|
||||
<li>Status: planned (no UI yet).</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h2>What’s live now?</h2>
|
||||
<p class="text">
|
||||
Atlas AI chat is running on local GPU hardware at <code>chat.ai.bstein.dev</code>. The chat page streams responses and
|
||||
reports latency per turn. As larger models come online on the Jetsons, the chat endpoint will be upgraded in-place.
|
||||
</p>
|
||||
<div class="pill mono">Next step: migrate chat to Jetsons when available</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 32px 22px 72px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
}
|
||||
|
||||
.track {
|
||||
border: 1px solid var(--card-border);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pill {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@ -5,8 +5,8 @@
|
||||
<p class="eyebrow">Atlas AI</p>
|
||||
<h1>Chat</h1>
|
||||
<p class="lede">
|
||||
Lightweight LLM running on titan-24 (RTX 3080, 8GB). Anyone can chat without auth. The client streams responses and
|
||||
shows round-trip latency for each turn.
|
||||
Lightweight LLM running on local GPU accelerated hardware. Anyone can chat without auth. The client streams responses
|
||||
and shows round-trip latency for each turn.
|
||||
</p>
|
||||
<div class="pill mono pill-live">Online</div>
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
</div>
|
||||
<div class="fact">
|
||||
<span class="label mono">GPU</span>
|
||||
<span class="value mono">titan-24 · 3080 (8GB)</span>
|
||||
<span class="value mono">local GPU (dynamic)</span>
|
||||
</div>
|
||||
<div class="fact">
|
||||
<span class="label mono">Endpoint</span>
|
||||
@ -30,7 +30,7 @@
|
||||
<div class="chat-window" ref="chatWindow">
|
||||
<div v-for="(msg, idx) in messages" :key="idx" :class="['chat-row', msg.role]">
|
||||
<div class="bubble" :class="{ streaming: msg.streaming }">
|
||||
<div class="role mono">{{ msg.role === 'assistant' ? 'ai' : 'you' }}</div>
|
||||
<div class="role mono">{{ msg.role === 'assistant' ? 'Atlas AI' : 'you' }}</div>
|
||||
<p>{{ msg.content }}</p>
|
||||
<div v-if="msg.streaming" class="meta mono typing">streaming…</div>
|
||||
<div v-else-if="msg.latency_ms" class="meta mono">{{ msg.latency_ms }} ms</div>
|
||||
@ -48,25 +48,17 @@
|
||||
v-model="draft"
|
||||
placeholder="Ask anything about the lab or general topics..."
|
||||
rows="3"
|
||||
@keydown="handleKeydown"
|
||||
:disabled="sending"
|
||||
/>
|
||||
<div class="actions">
|
||||
<span class="hint mono">Shift+Enter for newline</span>
|
||||
<span class="hint mono">Enter to send · Shift+Enter for newline</span>
|
||||
<button class="primary" type="submit" :disabled="sending || !draft.trim()">
|
||||
{{ sending ? "Sending..." : "Send" }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card info-card">
|
||||
<h2>Notes</h2>
|
||||
<ul>
|
||||
<li>Backend proxies requests to Ollama inside the cluster; no external calls are made.</li>
|
||||
<li>Short-term context: the chat history in this page is sent each turn. Refresh clears it.</li>
|
||||
<li>Future: swap in larger models on the Jetsons, add streaming and rate limits.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -80,7 +72,7 @@ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
const messages = ref([
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Hi! I'm the Titan Lab assistant running on titan-24. How can I help?",
|
||||
content: "Hi! I'm Atlas AI. How can I help?",
|
||||
},
|
||||
]);
|
||||
const draft = ref("");
|
||||
@ -162,6 +154,13 @@ async function typeReveal(entry, text) {
|
||||
}
|
||||
entry.streaming = false;
|
||||
}
|
||||
|
||||
function handleKeydown(e) {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
sendMessage();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user