LangChain একটি মানব এবং একটি AI-এর মধ্যে কথোপকথন পরিচালনার জন্য একটি সহজ ইন্টারফেস প্রদান করে। এটি সহজে BufferMemory ব্যবহার করতে কনফিগার করা যায়, যা আপনাকে কথোপকথনের ইতিহাস মেমরিতে সংরক্ষণ করতে দেয়। এটি কিছু ইউজ-কেসের জন্য সমीचীন হতে পারে, কিন্তু আপনার অ্যাপ্লিকেশনগুলোর চ্যাট ইতিহাস দীর্ঘমেয়াদীভাবে সংরক্ষণ করার প্রয়োজনও হতে পারে। خوشকিস্মতভাবে, এটি খুব সহজে একটি Upstash Redis ইনস্ট্যান্সের সাথে বদলা সম্ভব।
LangChain Redis-এর জন্য একাধিক ইন্টিগ্রেশন প্রদান করে, যার মধ্যে আছে ioredis, node-redis এবং Upstash Redis। যেহেতু Upstash Redis ক্লায়েন্ট REST এর মাধ্যমে কাজ করে, আপনি এটিকে ব্যবহার করে এজ-রেডি অ্যাপ্লিকেশন তৈরি করতে পারেন যা Vercel, Cloudflare Workers, বা অন্য যেকোনো সার্ভারলেস এনভায়রনমেন্টে ডিপ্লয় করা যায়। আমরা এটিকে ব্যবহার করে একটি সহজ চ্যাট অ্যাপ তৈরি করব যার মেমরি সেশন জুড়ে থাকবে।
এই ডেমোর পুরো সোর্স কোড আপনি এখানে পাবেন।
পূর্বশর্ত
- একটি Upstash Redis ডাটাবেস
- একটি OpenAI API কী
শুরু করা যাক
প্রজেক্ট তৈরি করা
আমরা Vercel AI SDK ব্যবহার করে একটি বেসিক Next.js অ্যাপ তৈরি করব LangChain-Upstash Redis ব্যবহার প্রদর্শনের জন্য। শুরু করতে, একটি নতুন Next.js অ্যাপ তৈরি করুন:
npx create-next-app@latest
এটি আপনাকে কিছু প্রজেক্ট অপশন সিলেক্ট করতে বলবে। অধিকাংশ অ্যাপের জন্য ডিফল্টগুলোই কাজ করবে। এই ডেমোর জন্য, TypeScript এবং app ডিরেক্টরি সক্ষম করতে ভুলবেন না।
ডিপেন্ডেন্সি ইনস্টল করা
অ্যাপ তৈরি হলে, আপনাকে কিছু ডিপেন্ডেন্সি ইনস্টল করতে হবে:
npm install ai langchain openai @upstash/redis
Vercel AI SDK স্ট্রিক্টলি আবশ্যক নয়, কিন্তু এটি OpenAI-র থেকে স্ট্রিমিং রেসপন্স আমাদের Next.js ফ্রন্টএন্ডে পাঠাতে সহজ করে দেয়। আমাদের শুধু @upstash/redis ব্যবহার করতে হবে একটি Redis ক্লায়েন্ট তৈরি করতে—LangChain বাকি কাজটি হ্যান্ডেল করবে।
এনভায়রনমেন্ট ভেরিয়েবল সেট করা
অবশেষে, আমাদের পূর্বশর্ত থেকে নিচের এনভায়রনমেন্ট ভেরিয়েবলগুলো দরকার। সেগুলো এখানে বর্ণনা করা নামের মতোই নাম দিতে হলে, কারণ অন্যথায় সেগুলো অটোমেটিক্যালি পড়া যাবে না! আপনি আপনার নতুন প্রজেক্টের রুটে একটি .env ফাইলে এগুলো যোগ করতে পারেন:
UPSTASH_REDIS_REST_URL="https://********.upstash.io"
UPSTASH_REDIS_REST_TOKEN="********"
OPENAI_API_KEY="sk-********"
একটি বেসিক চ্যাট ক্লায়েন্ট তৈরি করা
আপনি লক্ষ্য করবেন Next.js আমাদের জন্য অনেক ফাইল তৈরি করেছে। আমরা শুধু app ডিরেক্টরির কিছু ফাইলের সাথে কাজ করব, তাই আপনি public এবং app-এ বর্তমানে যা আছে সেটা ডিলিট করে দিতে পারেন।
শুরুতে, আমরা একটি বেসিক app/layout.tsx তৈরি করব আমাদের অ্যাপ হাউস করার জন্য:
import type { PropsWithChildren } from "react";
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
এরপর, ব্যবহারকারীর থেকে মেসেজ গ্রহণ করার জন্য একটি ইনপুট সহ একটি বেসিক ফর্ম যোগ করব আমাদের 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 একটি দরকারী হুক এক্সপোর্ট করে যেটি useChat, যা আমাদের চ্যাট অ্যাপের জন্য একটি প্রথাগত ইউজার ইন্টারফেস তৈরি করা খুব সহজ করে দেয়। এটি চ্যাট মেসেজ স্ট্রিমিং এবং চ্যাট ইনপুটের স্টেট ম্যানেজমেন্ট হ্যান্ডেল করে। হুকটি ব্যবহার করতে, আমাদের React-কে বলে দিতে হবে যে এটি একটি ক্লায়েন্ট কম্পোনেন্ট "use client" ডিরেক্টিভ ফাইলের শীর্ষে যোগ করে। তারপর, আমরা useChat হук থেকে কিছু প্রপার্টি ডিস্ট্রাকচার করতে পারি:
messagesহলো পাঠানো ও প্রাপ্ত মেসেজের একটি অ্যারে।inputহলো ইনপুট ফিল্ডের বর্তমান মান।handleInputChangeহলো একটি ফাংশন যা ইনপুট মান আপডেট করে।handleSubmitহলো একটি ফাংশন যা মেসেজগুলো আমাদের এন্ডপয়েন্টে পাঠায়।
"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 হুক অটোমেটিক্যালি input-কে messages-এ অ্যাপেন্ড করে যখন handleSubmit কল করা হয়, একটি রি-রেন্ডার ট্রিগার করে যাতে আমাদের নিজেরা UI আপডেট করার জন্য চিন্তা করতে হয় না। এটি ইনপুট ফিল্ডও ক্লিয়ার করে এবং নির্দিষ্ট এন্ডপয়েন্টে একটি API কল ট্রিগার করে। ডিফল্টভাবে, এটি /api/chat।
অবশেষে, ফর্মের উপরে messages রেন্ডার করি:
<main>
<section>
{messages.map((message) => (
<p key={message.id}>{message.content}</p>
))}
</section>
{/* snip */}
</main>
API এন্ডপয়েন্ট তৈরি করা
আমরা একটি app/api/chat/route.ts ফাইল তৈরি করতে পারি আমাদের এন্ডপয়েন্ট হাউস করার জন্য। Next.js API এন্ডপয়েন্টের জন্যও ফাইল-ভিত্তিক রাউটিং ব্যবহার করে—এটি কেন এই নতুন ফাইলের ফোল্ডার স্ট্রাকচার আগের ডিফল্ট এন্ডপয়েন্ট, /api/chat-এর সাথে মেলে।
যেহেতু আমরা Upstash Redis ব্যবহার করছি, আমাদের এন্ডপয়েন্ট এজ-কম্প্যাটিবল। আমরা এটি নির্দিষ্ট করতে পারি const runtime = "edge" এক্সপোর্ট করে আমাদের এন্ডপয়েন্ট থেকে। এন্ডপয়েন্টের ভিতরে, আমরা useChat হুক দ্বারা পপুলেট করা messages ফিল্ডটি রিট্রিভ করতে পারি। এটি আমাদের লেটেস্ট মেসেজটি 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);
}
useChat-এর মতই, LangChainStreamও কিছু প্রপার্টি রিটার্ন করে যা আমরা ডিস্ট্রাকচার করতে পারি।
streamহলো একটিReadableStreamযা শেষে LangChain প্রসেসের ফলাফল ধারণ করবে।handlersহলো একটি অবজেক্ট যেটি LLM কলব্যাক ফাংশন ধারণ করে যা LangChain-এ পাস করা যায়।
চেইনটি ইমপ্লিমেন্ট করার আগে, আমাদের আরও কিছু ক্লাস ইমপোর্ট করতে হবে:
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 ক্লায়েন্ট তৈরি করতে পারি এবং আমাদের চেইনের জন্য মেমরি সেট আপ করতে পারি। এখানে, আমরা একটি ConversationChain তৈরি করছি যা আমরা মডেলের বদলে কল করতে পারি। এটি একটি কাস্টম চেইন যা মানব এবং AI-এর মধ্যে কথোপকথন সুবিধা দেয়। আমরা চেইনকে একটি কাস্টম BaseMemory ইমপ্লিমেন্টেশন পাস করতে পারি, যা মেসেজ সংরক্ষণ ও রিট্রিভ করতে ব্যবহার হবে। এই কেসে, আমরা UpstashRedisChatMessageHistory সহ BufferMemory ব্যবহার করছি মেসেজ 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
আমরা @upstash/redis-এ এক্সপোর্ট করা Redis ক্লাস ব্যবহার করে একটি নতুন Redis ক্লায়েন্ট কনস্ট্রাক্ট করি। এটি বসে একটি মেথড প্রদান করে এনভায়রনমেন্ট ভেরিয়েবল অটোমেটিক্যালি লোড করতে, যা ChatOpenAI-র আচরণের দরদরি প্রতিফলিত করে। যতক্ষণ আপনি আপনার এনভায়রনমেন্ট ভেরিয়েবলগুলো সঠিকভাবে নাম দিয়েছেন, এই দুটি ক্লাসের যেকোনোর জন্য আপনাকে কোনো অতিরিক্ত আর্গুমেন্ট পাস করতে হবে না।
আপনার অ্যাপে, আপনি ব্যবহারকারীর ID বা অন্য যেকোনো ইউনিক আইডেন্টিফায়ার sessionId-র জন্য ব্যবহার করতে পারেন যাতে মেসেজ ব্যবহারকারীদের মধ্যে শেয়ার না হয়, কিন্তু এই ডেমোর জন্য আমরা বর্তমান তারিখ ব্যবহার করছি। UpstashRedisChatMessageHistory আরও কনফিগারেশন অপশন প্রদান করে যেমন sessionTTL ক্যাশের লাইফটাইম সেট করতে।
streaming মডেলে সক্রিয় করা গুরুত্বপূর্ণ, কারণ এটি আমাদের পূর্বে ডিস্ট্রাকচার করা handlers অবজেক্ট ব্যবহার করতে দেয় চেইনের ফলাফল stream-এ পাইপ করতে। অবশেষে, আমরা চেইনটি কল করতে পারি, লেটেস্ট মেসেজ এবং handlers অবজেক্ট পাস করে:
// snip
const chain = new ConversationChain({ llm: model, memory });
chain.call({ input: latestMessage.content, callbacks: [handlers] });
return new StreamingTextResponse(stream);
// snip
আমাদের পূর্বের latestMessage অবজেক্টটি LLM-র জন্য প্রম্পট হিসেবে ব্যবহৃত হয়। আমরা handlers অবজেক্টটিও চেইনকে পাস করি, যা stream-এ ফলাফল পাইপ করতে ব্যবহার হবে।
উপসংহার
বস! এখন আপনি npm run dev দিয়ে আপনার অ্যাপ চালাতে পারেন এবং আপনার AI-র সাথে চ্যাট শুরু করতে পারেন। রেসপন্স অটোমেটিক্যালি ক্লায়েন্টে স্ট্রিম হবে যা আমরা আগে তৈরি করেছি, এবং কথোপকথনের ইতিহাস Upstash Redis-এ সংরক্ষিত থাকবে।