Next.js App ထဲ AI Chatbot Feature ထည့်နည်း
LLM API key ကို server-side မှာ လုံခြုံစွာ ဖုံးကွယ်ပြီး Next.js Route Handler ကနေ AI model ကိုခေါ်၊ streaming response ကို frontend မှာပြသကာ rate limit/error handling အထိ chatbot feature တစ်ခုကို production-ready အဆင့် တည်ဆောက်ပါမယ်။
Problem
AI feature ကို frontend ကနေ တိုက်ရိုက်ခေါ်ရင် API key ပေါက်ကြားနိုင်ပြီး streaming, rate limiting, error handling မပါဘဲ ကျွေးလိုက်ရင် production မှာ cost spike နှင့် bad UX ဖြစ်တတ်ပါတယ်။
Requirements
- Next.js App Router project (local မှာ build အောင်မြင်ပြီးသား)
- OpenAI သို့မဟုတ် Anthropic API key
- Node.js 20 နှင့် pnpm/npm
- Environment variable အခြေခံ (.env.local) သိရှိမှု
API key ကို ရယူပြီး server-side မှာသာ ထားပါ
Provider dashboard (OpenAI Platform, Anthropic Console) မှာ API key တစ်ခု generate လုပ်ပါ။ Key ကို `.env.local` ထဲမှာပဲ ထားပြီး `NEXT_PUBLIC_` prefix လုံးဝ မသုံးပါနဲ့ — ဒီ prefix ပါရင် Next.js က browser bundle ထဲ ထည့်ပို့လိုက်ပြီး public ဖြစ်သွားပါတယ်။
AI_API_KEY=sk-...
# NEXT_PUBLIC_ prefix မသုံးပါနဲ့ -- client bundle ထဲ ပေါက်သွားနိုင်ပါတယ်Server-side Route Handler ဖန်တီးပါ
`app/api/chat/route.ts` ထဲမှာ POST handler တစ်ခု ဖန်တီးပါ — client ကနေ user message ကို လက်ခံပြီး key ကို server-side မှာပဲ သုံးကာ AI provider ကို ခေါ်ပါ။ Client ဘက်ကနေ API key ကို လုံးဝ မမြင်ရပါဘူး။
import "server-only";
export async function POST(request: Request) {
const apiKey = process.env.AI_API_KEY;
if (!apiKey) {
return new Response("AI_API_KEY is not configured", { status: 500 });
}
const { message } = await request.json();
if (!message || typeof message !== "string") {
return new Response("Invalid request body", { status: 400 });
}
const upstream = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-4o-mini",
stream: true,
messages: [{ role: "user", content: message }],
}),
});
if (!upstream.ok || !upstream.body) {
return new Response("Upstream AI request failed", { status: 502 });
}
return new Response(upstream.body, {
headers: { "Content-Type": "text/event-stream" },
});
}Frontend ကနေ streaming response ကို ဖတ်ပြပါ
Client component ထဲမှာ `fetch` နဲ့ route handler ကို ခေါ်ပြီး `ReadableStream` ကို token တစ်ခုချင်း ဖတ်ကာ UI ကို progressively update လုပ်ပါ — user က AI ရဲ့ အဖြေကို တစ်ခါတည်း စောင့်နေစရာ မလိုဘဲ real-time ရေးနေသလို မြင်ရပါတယ်။
async function sendMessage(message: string, onChunk: (text: string) => void) {
const response = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message }),
});
if (!response.body) return;
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
onChunk(decoder.decode(value, { stream: true }));
}
}Rate limiting, timeout နှင့် cost control ထည့်ပါ
Chatbot endpoint ကို public ထုတ်ပြီးရင် usage limit မရှိရင် bill ကနဦးမမျှော်လင့်ဘဲ မြင့်တက်နိုင်ပါတယ် (abuse, bot traffic)။ IP/user-per-minute request limit ထားပြီး upstream call ကို timeout နဲ့ wrap လုပ်ပါ — provider က ရေးနှေးနေရင် request တစ်ခု ထာဝရ ဆွဲထားခြင်းမျိုး မဖြစ်စေရပါဘူး။
Expected result
Key ကို client ဘက်ကနေ လုံးဝ မမြင်ရဘဲ user message ပို့လိုက်တာနဲ့ AI ရဲ့ အဖြေက token တစ်ခုချင်း real-time streaming ပြသနေတဲ့ chatbot feature တစ်ခု production-ready အဆင့်နဲ့ ရရှိပါမယ်။
Troubleshooting
- 'AI_API_KEY is not configured' error တက်ရင် .env.local ထဲ key ရှိမရှိနှင့် dev server ကို restart လုပ်ထားခြင်း (env var ပြောင်းတိုင်း restart လိုအပ်) ကိုစစ်ပါ။
- Streaming response က browser မှာ တစ်ခါတည်း block ပြီးမှ ပေါ်လာရင် Route Handler ရဲ့ Content-Type header နှင့် client ဘက် reader loop ကို ပြန်စစ်ပါ။
- 401/403 upstream error ရရင် key validity, model name spelling, provider dashboard ရဲ့ usage limit ကို တိုက်စစ်ပါ။
- Cost ရုတ်တရက်မြင့်တက်လာရင် rate limiting ကျန်ရှိနေခြင်း၊ bot traffic ရှိခြင်းကို logs ကနေ ရှာဖွေပါ။