diff --git a/backend/app.py b/backend/app.py index e2b1aec..6d1454a 100644 --- a/backend/app.py +++ b/backend/app.py @@ -36,7 +36,7 @@ AI_CHAT_SYSTEM_PROMPT = os.getenv( AI_CHAT_TIMEOUT_SEC = float(os.getenv("AI_CHAT_TIMEOUT_SEC", "20")) AI_NODE_NAME = os.getenv("AI_CHAT_NODE_NAME") or os.getenv("AI_NODE_NAME") or "ai-cluster" AI_GPU_DESC = os.getenv("AI_CHAT_GPU_DESC") or "local GPU (dynamic)" -AI_PUBLIC_ENDPOINT = os.getenv("AI_PUBLIC_CHAT_ENDPOINT", "https://chat.ai.bstein.dev/api/ai/chat") +AI_PUBLIC_ENDPOINT = os.getenv("AI_PUBLIC_CHAT_ENDPOINT", "https://chat.ai.bstein.dev/api/chat") AI_K8S_LABEL = os.getenv("AI_K8S_LABEL", "app=ollama") AI_K8S_NAMESPACE = os.getenv("AI_K8S_NAMESPACE", "ai") AI_MODEL_ANNOTATION = os.getenv("AI_MODEL_ANNOTATION", "ai.bstein.dev/model") @@ -154,6 +154,7 @@ def lab_status() -> Any: return jsonify(payload) +@app.route("/api/chat", methods=["POST"]) @app.route("/api/ai/chat", methods=["POST"]) def ai_chat() -> Any: payload = request.get_json(silent=True) or {} @@ -190,6 +191,7 @@ def ai_chat() -> Any: return jsonify({"error": str(exc)}), 502 +@app.route("/api/chat/info", methods=["GET"]) @app.route("/api/ai/info", methods=["GET"]) def ai_info() -> Any: meta = _discover_ai_meta() @@ -205,7 +207,7 @@ def _discover_ai_meta() -> dict[str, str]: "node": AI_NODE_NAME, "gpu": AI_GPU_DESC, "model": AI_CHAT_MODEL, - "endpoint": AI_PUBLIC_ENDPOINT or "/api/ai/chat", + "endpoint": AI_PUBLIC_ENDPOINT or "/api/chat", } # Only attempt k8s if we're in-cluster and credentials exist. diff --git a/frontend/src/components/TopBar.vue b/frontend/src/components/TopBar.vue index 82cc73c..6248950 100644 --- a/frontend/src/components/TopBar.vue +++ b/frontend/src/components/TopBar.vue @@ -51,6 +51,8 @@ const goAbout = () => router.push("/about"); .avatar { width: 44px; height: 44px; + aspect-ratio: 1 / 1; + flex-shrink: 0; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.14); overflow: hidden; @@ -63,6 +65,8 @@ const goAbout = () => router.push("/about"); width: 100%; height: 100%; object-fit: cover; + display: block; + border-radius: 50%; } .name { diff --git a/frontend/src/data/sample.js b/frontend/src/data/sample.js index 9ae5c3f..b6f598c 100644 --- a/frontend/src/data/sample.js +++ b/frontend/src/data/sample.js @@ -118,34 +118,34 @@ export function fallbackServices() { { name: "Jitsi", category: "conferencing", - summary: "Video Conferencing - Planned", + summary: "Video conferencing", link: "https://meet.bstein.dev", - status: "degraded", + status: "live", + }, + { + name: "AI Chat", + category: "ai", + summary: "LLM chat (public beta)", + link: "/ai/chat", + host: "chat.ai.bstein.dev", + status: "live", + }, + { + 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", }, - { - name: "AI Chat", - category: "ai", - summary: "LLM chat (public beta)", - link: "/ai/chat", - host: "chat.ai.bstein.dev", - status: "live", - }, - { - 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", - }, ], }; } diff --git a/frontend/src/views/AiView.vue b/frontend/src/views/AiView.vue index daef4f6..7e3fbc1 100644 --- a/frontend/src/views/AiView.vue +++ b/frontend/src/views/AiView.vue @@ -5,8 +5,7 @@

Atlas AI

Chat

- Lightweight LLM running on local GPU accelerated hardware. Anyone can chat without auth. The client streams responses, - shows round-trip latency for each turn, and we're training an Atlas-aware model steeped in Titan Lab context. + Talk with Atlas AI. It knows a surprising amount about technology!

Online
@@ -22,7 +21,7 @@
Endpoint
@@ -62,39 +61,22 @@ - -
-

API quick start

-

- The UI hits /api/ai/chat on the same host. External callers can hit the public endpoint - https://chat.ai.bstein.dev/api/ai/chat. POST JSON with a message and optional - history. -

-
-curl -X POST https://chat.ai.bstein.dev/api/ai/chat \
-  -H 'content-type: application/json' \
-  -d '{"message":"hi, what is your name?"}'
-

- Responses stream in the UI. API callers get either a JSON body { reply, latency_ms } or a streamed text - body if available. -

-