AI SDK အသုံးပြု၍ Web UI တည်ဆောက်ခြင်း - Tutorial A developer built a web-based AI agent using TypeScript, Vercel AI SDK, OpenRouter, and Next.js, converting a terminal-only agent into a full web app with streaming responses, a React chat interface, conversation history, and multiple chat sessions. The architecture shifts from a terminal-to-agent flow to a browser-to-React-to-Next.js API route-to-agent pipeline, with conversations stored as JSON files. The tutorial covers setting up the project, installing necessary packages, and configuring environment variables. ပြီးခဲ့တဲ့ သင်ခန်းစာမှာ https://gist.github.com/eimg/3856a76ec56848a0054518b09a1b804f TypeScript, Vercel AI SDK နဲ့ OpenRouter တို့ကို အသုံးပြုပြီး AI agent တစ်ခုကို တည်ဆောက်ခဲ့ကြပါတယ်။ ကျွန်တော်တို့ရဲ့ Agent က - - Language model ခေါ်ယူခြင်း - Tool များအသုံးပြုခြင်း - Agent Loop လုပ်ဆောင်ခြင်း - Memory ယာယီသိမ်းဆည်းခြင်း - Subagent များအသုံးပြုခြင်း - Sequential Tasks များလုပ်ဆောင်ခြင်း - Parallel Tasks များလုပ်ဆောင်ခြင်း တို့ကို လုပ်ဆောင်နိုင်ခဲ့ပါတယ်။ ဒါပေမဲ့ အဲ့ဒီ Agent ဟာ Terminal ထဲမှာပဲ အလုပ်လုပ်တာ ဖြစ်ပါတယ်။ ဒီ သင်ခန်းစာမှာတော့ အဲ့ဒီ Agent ကို Web App အသေးလေးတစ်ခုအဖြစ် ပြောင်းလဲတည်ဆောက်သွားမှာ ဖြစ်ပါတယ်။ သင်ခန်းစာ ပြီးဆုံးသွားတဲ့အခါ ကျွန်တော်တို့ရဲ့ App ဟာ - - Streaming responses - React Chat interface - Conversation history - Multiple chat sessions - Old conversations - Creating new conversations - Basic state management - Better error handling - Stopping a streaming response စတဲ့ အခြေခံလုပ်ဆောင်ချက် ပြည့်ပြည့်စုံစုံကို ရရှိသွားမှာ ဖြစ်ပါတယ်။ အသုံးပြုသွားမယ့် နည်းပညာတွေကတော့ အရင်အတိုင်းပဲ - - TypeScript - npm - Vercel AI SDK - OpenRouter - Zod Web APP အတွက်တော့ Next.js ကို အသုံးပြုသွားမှာပါ။ Database တွေဘာတွေတော့ မသုံးသေးဘဲ Conversation တွေကို JSON ဖိုင်လေးတွေအနေနဲ့ပဲ သိမ်းဆည်းသွားပါမယ်။ အရင်တုန်းက Architecture က ဒီလိုပါ - User ↓ Terminal ↓ Agent ↓ OpenRouter ↓ Language model အသစ်ပြောင်းလဲမယ့် Architecture ကတော့ ဒီလို ဖြစ်သွားပါမယ် - Browser ↓ React chat interface ↓ Next.js API route ↓ AI agent ↓ OpenRouter ↓ Language model File storage လည်း ထည့်သွင်းပါမယ် - Browser ↓ Chat API ↓ Agent ↓ JSON conversation files Language model က JSON ဖိုင်တွေကို တိုက်ရိုက်ဖတ်တာ ရေးတာ မလုပ်ပါဘူး။ ကျွန်တော်တို့ရဲ့ TypeScript ကုဒ်ကပဲ သိမ်းဆည်းတဲ့အပိုင်းကို လုပ်သွားမှာပါ။ Next.js application အသစ်တစ်ခုကို အခုလို တည်ဆောက်ပါ - npx create-next-app@latest my-agent-web Setup လုပ်တဲ့အခါ မေးခွန်းတွေ မေးလာရင် အောက်ပါအတိုင်း ရွေးချယ်ပေးပါ - Would you like to use the recommended Next.js defaults? Yes, use recommended defaults ပြီးရင် Project directory ထဲကို ဝင်ပါ - cd my-agent-web လိုအပ်တဲ့ AI packages တွေကို Install လုပ်ပါ - npm install ai @ai-sdk/react @openrouter/ai-sdk-provider zod ဒီ Packages တွေရဲ့ အဓိကလုပ်ဆောင်ချက်တွေကတော့ - ai : Vercel AI SDK ရဲ့ ပင်မ Package ဖြစ်ပါတယ်။ @ai-sdk/react : useChat လိုမျိုး React hooks တွေ ပါဝင်ပါတယ်။ @openrouter/ai-sdk-provider : AI SDK နဲ့ OpenRouter ကို ချိတ်ဆက်ပေးပါတယ်။ zod : Tool input တွေကို စစ်ဆေးဖို့ အသုံးပြုပါတယ်။ Project ရဲ့ အပြင်ဘက်ဆုံး Root မှာ .env.local ဖိုင်တစ်ခု ဖန်တီးပြီး အောက်ပါအတိုင်း ရေးထည့်ပါ - OPENROUTER API KEY=your-openrouter-api-key OPENROUTER MODEL=xiaomi/mimo-v2.5 OpenRouter Model ကို မိမိနှစ်သက်ရာ အခြား Model နဲ့လည်း အစားထိုးနိုင်ပါတယ်။ နောက်ပိုင်း Calculator tool ကို အသုံးပြုမှာဖြစ်လို့ ရွေးချယ်လိုက်တဲ့ Model က Tool calling ရဖို့တော့ လိုပါတယ်။ API Key ကို Client-side React ကုဒ်တွေထဲမှာ မထည့်မိဖို့ကို သတိပြုပါ။ Server-side ဘက်မှာပဲ ရှိရပါမယ်။ ကျွန်တော်တို့ တဖြည်းဖြည်းချင်း တည်ဆောက်သွားမယ့် Folder Structure က အောက်ပါအတိုင်း ဖြစ်ပါတယ် - my-agent-web/ ├── app/ │ ├── api/ │ │ ├── chat/ │ │ │ └── route.ts │ │ └── chats/ │ │ └── route.ts │ ├── chat/ │ │ ├── id / │ │ │ └── page.tsx │ │ └── page.tsx │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── components/ │ ├── chat-app.tsx │ ├── chat-input.tsx │ ├── chat-sidebar.tsx │ └── message-list.tsx ├── lib/ │ ├── agent.ts │ ├── chat-store.ts │ ├── message-utils.ts │ └── tools.ts ├── scripts/ │ └── stream-test.ts ├── .data/ │ └── chats/ ├── .env.local ├── package.json └── tsconfig.json .data/chats folder ဟာ ပထမဆုံး Chat History ကို သိမ်းဆည်းတဲ့အခါ အလိုအလျောက် ဖန်တီးသွားမှာပါ။ ပြီးခဲ့တဲ့ သင်ခန်းစာမှာ generateText ကို အသုံးပြုခဲ့ပါတယ် - js const result = await generateText { model, prompt: "Explain AI agents.", } ; console.log result.text ; generateText ဟာ စာတွေ အကုန်လုံး ထုတ်ပေးလို့ ပြီးတဲ့အထိ စောင့်ပါတယ်။ Flow က ဒီလိုပါ - Send prompt ↓ Wait for complete generation ↓ Receive complete answer ↓ Display answer Streaming ရဲ့ အလုပ်လုပ်ပုံကတော့ ကွဲပြားပါတယ် - Send prompt ↓ Receive first piece ↓ Display it ↓ Receive next piece ↓ Display it ↓ Continue until complete Streaming ဟာ Model ကို ပိုမြန်မြန် စာထုတ်ပေးအောင် လုပ်တာမဟုတ်ပါဘူး။ User အနေနဲ့ အဖြေအပြည့်အစုံ မပြီးခင်မှာကတည်းက စာတွေကို တဖြည်းဖြည်းချင်း မြင်တွေ့နိုင်အောင် လုပ်ပေးတာ ဖြစ်ပါတယ်။ Web interface မတည်ဆောက်ခင် Streaming သီးသန့် အလုပ်လုပ်ပုံကို အရင်စမ်းကြည့်ရအောင်။ scripts/stream-test.ts ဆိုပြီး ဖိုင်တစ်ခု ဖန်တီးပါ scripts folder မရှိသေးရင် အသစ်ဆောက်ပါ ။ ပြီးတဲ့အခါ ဒီကုဒ်ကို ထည့်ပါ - js import { createOpenRouter } from "@openrouter/ai-sdk-provider"; import { streamText } from "ai"; async function main { const apiKey = process.env.OPENROUTER API KEY; const modelName = process.env.OPENROUTER MODEL; if apiKey { throw new Error "OPENROUTER API KEY is missing." ; } if modelName { throw new Error "OPENROUTER MODEL is missing." ; } const openrouter = createOpenRouter { apiKey, } ; const result = streamText { model: openrouter modelName , prompt: "Explain streaming responses in simple terms.", } ; for await const textPart of result.textStream { process.stdout.write textPart ; } process.stdout.write "\n" ; } main .catch error = { console.error error ; process.exitCode = 1; } ; ဒီဖိုင်ကို သီးသန့် Run လို့ရအောင် tsx ကို install လုပ်ပါ - npm install -D tsx package.json ထဲက scripts မှာ stream-test ကို သွားထည့်ပေးပါ ရှိပြီးသား Next.js script တွေကို မဖျက်ပါနဲ့ - { "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "stream-test": "tsx --env-file=.env.local scripts/stream-test.ts" } } အခုလို Run ကြည့်ပါ - npm run stream-test စာတွေ တဖြည်းဖြည်းချင်း Stream အနေနဲ့ ထွက်လာတာကို တွေ့ရပါလိမ့်မယ်။ အဓိကကုဒ်ကတော့ streamText ကို အသုံးပြုထားတာပါပဲ - js const result = streamText { model, prompt, } ; ပြီးတော့ ရလာတဲ့ အပိုင်းအစလေးတွေကို အခုလို loop ပတ်ပြီး ထုတ်ယူပါတယ် - js for await const textPart of result.textStream { process.stdout.write textPart ; } Agent နဲ့သက်ဆိုင်တဲ့ Logic တွေကို API route ထဲမှာ အကုန်မရေးဘဲ သီးသန့်ခွဲထုတ်ပါမယ်။ lib/agent.ts ကို ဖန်တီးပြီး အောက်ပါအတိုင်း ရေးပါ - js import { createOpenRouter } from "@openrouter/ai-sdk-provider"; const apiKey = process.env.OPENROUTER API KEY; const modelName = process.env.OPENROUTER MODEL; if apiKey { throw new Error "OPENROUTER API KEY is missing." ; } if modelName { throw new Error "OPENROUTER MODEL is missing." ; } const openrouter = createOpenRouter { apiKey, } ; export const agentModel = openrouter modelName ; export const agentSystemPrompt = You are a helpful AI assistant. Explain ideas clearly and directly. Use the calculator tool whenever accurate arithmetic is required. After using a tool, explain the result to the user. Do not claim that you performed an action unless a tool actually performed it. ; ဒီ module ထဲမှာ - - Provider သတ်မှတ်ခြင်း - Model ရွေးချယ်ခြင်း - System instructions များ ပါဝင်ပါတယ်။ UI တွေ၊ HTTP request တွေ၊ သိမ်းဆည်းတဲ့အပိုင်းတွေကို ဒီထဲမှာ မထည့်ပါဘူး။ သီးခြားခွဲထားမှာပါ။ lib/tools.ts ကို ဖန်တီးပြီး အောက်ပါအတိုင်း ရေးပါ - js import { tool } from "ai"; import { z } from "zod"; export const calculatorTool = tool { description: "Perform accurate arithmetic using two numbers. Use this tool when arithmetic is required.", inputSchema: z.object { operation: z .enum "add", "subtract", "multiply", "divide" .describe "The arithmetic operation to perform" , a: z.number .describe "The first number" , b: z.number .describe "The second number" , } , execute: async { operation, a, b } = { switch operation { case "add": return { success: true, result: a + b, }; case "subtract": return { success: true, result: a - b, }; case "multiply": return { success: true, result: a b, }; case "divide": if b === 0 { return { success: false, error: "Division by zero is not allowed.", }; } return { success: true, result: a / b, }; } }, } ; export const agentTools = { calculator: calculatorTool, }; Tools တွေကို Object တစ်ခုတည်းအနေနဲ့ ပေါင်းပြီး Export လုပ်ထားပါတယ် - js export const agentTools = { calculator: calculatorTool, }; ဒီလိုလုပ်ထားတာက streamText မှာပဲဖြစ်ဖြစ်၊ Message တွေ Validate လုပ်တဲ့အခါမှာပဲဖြစ်ဖြစ် အလွယ်တကူ ထည့်သွင်းအသုံးပြုနိုင်ဖို့ ဖြစ်ပါတယ်။ app/api/chat/route.ts ကို ဖန်တီးပြီး အောက်ပါအတိုင်း ရေးပါ - js import { convertToModelMessages, createIdGenerator, type InferUITools, stepCountIs, streamText, type UIDataTypes, type UIMessage, validateUIMessages, } from "ai"; import { agentModel, agentSystemPrompt, } from "@/lib/agent"; import { agentTools } from "@/lib/tools"; export const runtime = "nodejs"; type AgentUIMessage = UIMessage< never, UIDataTypes, InferUITools