Auxen Chat
++ Next.js + your own dedicated LLM endpoint on Auxen +
+
+ Set AUXEN_API_BASE and{" "}
+ AUXEN_API_KEY in your
+ environment, then say hi.
+
diff --git a/solutions/auxen-chatbot/.env.example b/solutions/auxen-chatbot/.env.example new file mode 100644 index 0000000000..d8dbe806cd --- /dev/null +++ b/solutions/auxen-chatbot/.env.example @@ -0,0 +1,10 @@ +# Per-instance base URL issued by the Auxen dashboard +# Looks like https://api.auxen.ai/v1/inst_xxx/v1 +AUXEN_API_BASE= + +# Per-instance API key issued by the Auxen dashboard (prefix: auxk_) +AUXEN_API_KEY= + +# Optional — overrides the default chat model. Must match the model your +# Auxen instance is provisioned to serve. Defaults to llama-3.1-8b. +# AUXEN_MODEL=llama-3.1-8b diff --git a/solutions/auxen-chatbot/.gitignore b/solutions/auxen-chatbot/.gitignore new file mode 100644 index 0000000000..e60aa4454d --- /dev/null +++ b/solutions/auxen-chatbot/.gitignore @@ -0,0 +1,9 @@ +node_modules +.next +out +.DS_Store +.env +.env.local +.env.*.local +*.tsbuildinfo +next-env.d.ts diff --git a/solutions/auxen-chatbot/README.md b/solutions/auxen-chatbot/README.md new file mode 100644 index 0000000000..0781a16948 --- /dev/null +++ b/solutions/auxen-chatbot/README.md @@ -0,0 +1,81 @@ +--- +name: Auxen Dedicated LLM Chatbot +slug: auxen-chatbot +publisher: Auxen +description: Next.js chatbot wired to your own dedicated LLM endpoint on Auxen. Per-minute GPU billing, no per-token fees, OpenAI-compatible API. +framework: Next.js +useCase: AI +css: Tailwind +deployUrl: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fauxen-ai%2Fauxen-nextjs-starter&env=AUXEN_API_BASE,AUXEN_API_KEY&envDescription=Per-instance%20base%20URL%20and%20API%20key%20issued%20by%20the%20Auxen%20dashboard&envLink=https%3A%2F%2Fauxen.ai +demoUrl: https://auxen.ai +--- + +# Auxen Dedicated LLM Chatbot + +A minimal Next.js chatbot wired to your own [Auxen](https://auxen.ai) dedicated LLM endpoint. Zero external SDK dependencies — just `fetch` against Auxen's OpenAI-compatible `/v1/chat/completions` API. + +## What is Auxen + +[Auxen](https://auxen.ai) hosts per-customer **dedicated** LLM endpoints (Llama 3.1/3.2, Qwen 2.5, Mistral, Gemma 2, Mixtral, Phi-3, Command R). Each instance is a dedicated GPU running one open-source model, billed per-minute of runtime — no per-token charges, no monthly minimums. + +## Demo + +The chatbot runs in your own browser against your own Auxen instance — provision one at [auxen.ai](https://auxen.ai) to try it. + +## How to Use + +You can choose from one of the following two methods to use this repository: + +### One-Click Deploy + +Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme): + +[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fauxen-ai%2Fauxen-nextjs-starter&env=AUXEN_API_BASE,AUXEN_API_KEY&envDescription=Per-instance%20base%20URL%20and%20API%20key%20issued%20by%20the%20Auxen%20dashboard&envLink=https%3A%2F%2Fauxen.ai) + +### Clone and Deploy + +```bash +git clone https://github.com/auxen-ai/auxen-nextjs-starter.git +cd auxen-nextjs-starter +npm install +cp .env.example .env.local # then fill in AUXEN_API_BASE and AUXEN_API_KEY +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) and start chatting. + +## Configuration + +| Env var | Description | +| ---------------- | -------------------------------------------------------------------------------------- | +| `AUXEN_API_BASE` | Per-instance base URL, e.g. `https://api.auxen.ai/v1/inst_xxx/v1` (from the dashboard) | +| `AUXEN_API_KEY` | Per-instance API key prefixed `auxk_` (from the dashboard) | +| `AUXEN_MODEL` | Optional — the model your instance is serving. Defaults to `llama-3.1-8b`. | + +## How it works + +The Edge route handler at `/api/chat` proxies messages to your Auxen instance and streams the OpenAI Chat Completions SSE response back to the browser: + +```ts +const upstream = await fetch(`${AUXEN_API_BASE}/chat/completions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${AUXEN_API_KEY}`, + }, + body: JSON.stringify({ model, messages, stream: true }), +}); +return new Response(upstream.body, { + headers: { "Content-Type": "text/event-stream" }, +}); +``` + +That's the whole integration. No AI SDK dependency — `fetch` + the browser's SSE parser handle everything. + +## Pricing + +Auxen bills per-minute of dedicated GPU runtime, not per token. See [auxen.ai/pricing](https://auxen.ai/pricing). + +## Source + +Canonical source repo: [github.com/auxen-ai/auxen-nextjs-starter](https://github.com/auxen-ai/auxen-nextjs-starter) diff --git a/solutions/auxen-chatbot/app/api/chat/route.ts b/solutions/auxen-chatbot/app/api/chat/route.ts new file mode 100644 index 0000000000..3ea745a024 --- /dev/null +++ b/solutions/auxen-chatbot/app/api/chat/route.ts @@ -0,0 +1,54 @@ +// Minimal proxy from the browser to your Auxen instance. Auxen exposes the +// OpenAI Chat Completions wire format on every instance, so the only thing +// this route does is forward the messages, add the bearer token, and stream +// the SSE response back to the client unchanged. + +export const runtime = "edge"; +export const maxDuration = 30; + +interface ChatRequest { + messages: Array<{ role: "system" | "user" | "assistant"; content: string }>; +} + +export async function POST(req: Request) { + const { messages }: ChatRequest = await req.json(); + + const base = process.env.AUXEN_API_BASE; + const key = process.env.AUXEN_API_KEY; + const model = process.env.AUXEN_MODEL ?? "llama-3.1-8b"; + + if (!base || !key) { + return new Response( + JSON.stringify({ + error: + "Auxen credentials missing. Set AUXEN_API_BASE and AUXEN_API_KEY env vars (get them from https://auxen.ai).", + }), + { status: 500, headers: { "Content-Type": "application/json" } }, + ); + } + + const upstream = await fetch(`${base.replace(/\/$/, "")}/chat/completions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${key}`, + }, + body: JSON.stringify({ model, messages, stream: true }), + }); + + if (!upstream.ok || !upstream.body) { + const text = await upstream.text(); + return new Response( + JSON.stringify({ error: text || `Auxen returned ${upstream.status}` }), + { status: upstream.status, headers: { "Content-Type": "application/json" } }, + ); + } + + return new Response(upstream.body, { + headers: { + "Content-Type": "text/event-stream; charset=utf-8", + "Cache-Control": "no-cache, no-transform", + Connection: "keep-alive", + }, + }); +} diff --git a/solutions/auxen-chatbot/app/globals.css b/solutions/auxen-chatbot/app/globals.css new file mode 100644 index 0000000000..e9c248d06e --- /dev/null +++ b/solutions/auxen-chatbot/app/globals.css @@ -0,0 +1,10 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, body { height: 100%; } +body { + font-family: ui-sans-serif, system-ui, -apple-system, sans-serif; + background: #0a0a0a; + color: #f5f5f5; +} diff --git a/solutions/auxen-chatbot/app/layout.tsx b/solutions/auxen-chatbot/app/layout.tsx new file mode 100644 index 0000000000..cf847d1939 --- /dev/null +++ b/solutions/auxen-chatbot/app/layout.tsx @@ -0,0 +1,20 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "Auxen Chat Starter", + description: + "Next.js + Vercel AI SDK chatbot starter wired to an Auxen dedicated LLM endpoint.", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + +
{children} + + ); +} diff --git a/solutions/auxen-chatbot/app/page.tsx b/solutions/auxen-chatbot/app/page.tsx new file mode 100644 index 0000000000..4bce76d0b2 --- /dev/null +++ b/solutions/auxen-chatbot/app/page.tsx @@ -0,0 +1,136 @@ +"use client"; + +import { useState, type FormEvent } from "react"; + +type Message = { role: "user" | "assistant"; content: string }; + +export default function Page() { + const [messages, setMessages] = useState+ Next.js + your own dedicated LLM endpoint on Auxen +
+
+ Set AUXEN_API_BASE and{" "}
+ AUXEN_API_KEY in your
+ environment, then say hi.
+