LangChain มี Interface เรียบง่ายสำหรับการสนทนาระหว่างมนุษย์และ AI สามารถตั้งค่าใช้ BufferMemory เก็บประวัติใน Memory ได้ ซึ่งเพียงพอสำหรับบาง Use Cases แต่อาจต้องการ Persistence ระยะยาว สลับไปใช้ Upstash Redis ได้ง่ายเช่นกัน
LangChain มี Redis Integrations หลายตัว ได้แก่ ioredis, node-redis และ Upstash Redis เนื่องจาก Upstash Redis Client ทำงานผ่าน REST จึงสร้าง Edge-ready Apps Deploy ได้บน Vercel, Cloudflare Workers หรือ Serverless อื่นๆ เราจะสร้าง Chat App เรียบง่ายกับ Memory ที่ Persist ข้าม Session
ซอร์สโค้ดเต็มได้ที่นี่
Prerequisites - เงื่อนไขก่อนเริ่ม
- Upstash Redis Database
- OpenAI API Key
Getting Started - เริ่มต้น
Creating the Project - สร้างโปรเจกต์
สร้าง Next.js App พื้นฐานพร้อม Vercel AI SDK สาธิต LangChain กับ Upstash Redis:
npx create-next-app@latest
เลือก Options ตามปกติ สำหรับ Demo ให้ Enable TypeScript และ app Directory
Installing Dependencies - ติดตั้ง Dependencies
npm install ai langchain openai @upstash/redis
Vercel AI SDK ช่วย Streaming Responses จาก OpenAI ไป Frontend Next.js เราต้องใช้ @upstash/redis สร้าง Redis Client เท่านั้น LangChain จัดการส่วนอื่น
Setting Environment Variables - ตั้งค่า Environment Variables
Env Variables ต่อไปจาก Prerequisites ใส่ใน .env Root Project (ชื่อต้องตรงตามนี้ ไม่งั้นอ่าน Auto ไม่ได้):
UPSTASH_REDIS_REST_URL="https://********.upstash.io"
UPSTASH_REDIS_REST_TOKEN="********"
OPENAI_API_KEY="sk-********"
Creating a Basic Chat Client - สร้าง Chat Client พื้นฐาน
Next.js สร้างไฟล์เยอะ เราทำงานแค่ไฟล์ใน app Directory ลบของใน public และ app ทิ้งได้
สร้าง app/layout.tsx 基礎:
import type { PropsWithChildren } from "react";
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
สร้าง Form พร้อม Input รับข้อความใน app/page.tsx:
export default function Home() {
return (
<main>
<form>
<input placeholder="Enter a message..." />
<button type="submit">Send</button>
</form>
</main>
);
}

Vercel AI SDK มี Hook useChat สร้าง Chat UI ง่าย จัดการ Streaming และ State Input ใช้ Hook ต้องเพิ่ม "use client" ด้านบน Destructure Properties:
messages- Array ข้อความที่ส่งและรับinput- ค่า Input Field ปัจจุบันhandleInputChange- Function Update InputhandleSubmit- Function ส่งข้อความไป Endpoint
"use client";
import { useChat } from "ai/react";
export default function Home() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<main>
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} placeholder="Enter a message..." />
<button type="submit">Send</button>
</form>
</main>
);
}
useChat Append input ไป messages เมื่อ handleSubmit เรียก Trigger Re-render ไม่ต้องจัดการ UI เอง Clear Input และ Trigger API Call ไป Endpoint Default /api/chat
Render messages เหนือ Form:
<main>
<section>
{messages.map((message) => (
<p key={message.id}>{message.content}</p>
))}
</section>
{/* snip */}
</main>
Creating the API Endpoint - สร้าง API Endpoint
สร้าง app/api/chat/route.ts Next.js ใช้ File-based Routing สำหรับ API และ Pages โฟลเดอร์ตรงกับ Default Endpoint /api/chat
ใช้ Upstash Redis Endpoint Edge-Compatible ระบุ export const runtime = "edge" ดึง messages จาก useChat ส่ง Latest Message ให้ LangChain:
import { type NextRequest } from "next/server";
import { LangChainStream, StreamingTextResponse } from "ai";
export const runtime = "edge";
export async function POST(req: NextRequest) {
const { messages } = await req.json();
const { stream, handlers } = LangChainStream();
const latestMessage = messages[messages.length - 1];
return new StreamingTextResponse(stream);
}
LangChainStream Return Properties:
stream- ReadableStream ผลลัพธ์ LangChain Processhandlers- Object Callback Functions ส่งให้ LangChain
Import Classes เพิ่มเติม:
import { Redis } from "@upstash/redis";
import { ConversationChain } from "langchain/chains";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { BufferMemory } from "langchain/memory";
import { UpstashRedisChatMessageHistory } from "langchain/stores/message/upstash_redis";
สร้าง Redis Client ตั้งค่า Memory สำหรับ Chain ใช้ ConversationChain สนทนาระหว่าง Human และ AI ส่ง BaseMemory Custom Implementation เก็บ/ดึงข้อความ ใช้ BufferMemory กับ UpstashRedisChatMessageHistory เก็บใน Upstash Redis:
// snip
const latestMessage = messages[messages.length - 1];
const memory = new BufferMemory({
chatHistory: new UpstashRedisChatMessageHistory({
sessionId: new Date().toLocaleDateString(),
client: Redis.fromEnv(),
}),
});
const model = new ChatOpenAI({
modelName: "gpt-3.5-turbo",
streaming: true,
});
const chain = new ConversationChain({ llm: model, memory });
// snip
สร้าง Redis Client ด้วย Class Redis จาก @upstash/redis มี Method โหลด Env Auto เหมือน ChatOpenAI ตั้งชื่อ Env ถูกต้องไม่ต้องส่ง Arguments เพิ่ม
sessionId ใช้ Date ปัจจุบันสำหรับ Demo แอปจริงควรใช้ User ID หรือ Unique Identifier ป้องกัน Share Messages ระหว่าง User UpstashRedisChatMessageHistory มี Options อื่นๆ เช่น sessionTTL ตั้งอายุ Cache
สำคัญ: Enable streaming บน Model เพื่อใช้ handlers Pipe ผลลัพธ์ไป stream เรียก Chain ส่ง Latest Message และ handlers:
// snip
const chain = new ConversationChain({ llm: model, memory });
chain.call({
input: latestMessage.content,
callbacks: [handlers],
});
return new StreamingTextResponse(stream);
// snip
latestMessage เป็น Prompt ให้ LLM ส่ง handlers Pipe ผลลัพธ์ไป stream
Conclusion - สรุป
เสร็จแล้ว! รัน npm run dev เริ่มสนทนากับ AI Response จะ Stream กลับ Client อัตโนมัติ ประวัติสนทนาจะเก็บใน Upstash Redis

