দ্রুত রেসপন্স দেয়া AI-পাওয়ার্ড অ্যাপ্লিকেশন ইউজারকে তাৎক্ষণিক শুনা ও দেখা হয়ে থাকার অনুভূতি দিয়ে ইউজার এক্সপেরিয়েন্স বাড়ায়। স্ট্রিমিং দিয়ে আপনি এমন চ্যাটবট বানাতে পারেন যা তাৎক্ষণিক কোয়েরি সমাধান করে বা রিয়েল-টাইমে পერსোনালাইজড রিকমেন্ডেশন দেয়। এটি শুধু গতির বিষয় নয় — এটি ব্যবহারকারীর চাহিদা তাৎক্ষণিক পূরণ করার বিষয়, যা এর মূল্য বাড়াতে।
স্ট্রিমিং মানে ডেটা ছোট ছোট, συνεχíu চান্কে পাঠানো, এক বড় ব্লকে একসাথে না। AI অ্যাপ্লিকেশনের কনটেক্সটে, যেমন চ্যাটবট বা রিকমেন্ডেশন সিস্টেম, স্ট্রিমিং মানে আংশিক রেসপন্স ইউজারকে পাঠানো যতক্ষণ সেগুলো উপলব্ধ হয়, পুরো রেসপন্স কম্পাইল করে একসাথে ডেলিভার করার জন্য অপেক্ষা করার বদলে। এই পদ্ধতিটি নিশ্চিত করে যে ইউজার তাৎক্ষণিক ফিডব্যাক বা ইনফরমেশন পায়, একটি আরও ডাইনামিক এবং রেসপন্সিভ ইউজার এক্সপেরিয়েন্স সৃষ্টি করে।
এই গাইডে, আপনি শিখবেন কীভাবে Server-Sent Events (SSE) লিভারেজ করে Next.js এন্ডপয়েন্টে ল্যাঙ্গচেইন এবং ওপেনএআই-এর ল্যাঙ্গুয়েজ মডেলের সাথে স্ট্রিমিং ইমপ্লিমেন্ট করতে হয়। আরও, আপনি শিখবেন কীভাবে আপস্ট্যাশ দিয়ে স্ট্রিমিং রেসপন্স ক্যাশ করতে হয়।
প্রে-রেকোয়েজিটস
আপনাকে নিম্নলিখিত موارد দরকার:
- Node.js 18 বা তার পরবর্তী ভার্সন
- একটি OpenAI অ্যাকাউন্ট
- একটি Upstash অ্যাকাউন্ট
- একটি Vercel অ্যাকাউন্ট
টেক স্ট্যাক
OpenAI টোকেন জেনারেট করুন
OpenAI API ব্যবহার করে, আপনি AI দিয়ে চ্যাটবট রেসপন্স তৈরি করতে পারেন। OpenAI API-র যেকোনো রিকোয়েস্টে একটি অথরাইজেশন টোকেন দরকার। টোকেন পেতে, আপনার OpenAI অ্যাকাউন্টের API Keys-এ যান, এবং Create new secret key বাটনে ক্লিক করুন। টোকেন কপি করে নিরাপদে সংরক্ষণ করুন OPENAI_API_KEY এনভায়রনমেন্ট ভেরিয়েবল হিসেবে পরবর্তী ব্যবহার জন্য।
Upstash Redis সেটআপ
আপস্ট্যাশ অ্যাকাউন্ট তৈরি করুন এবং লগইন করলে আপনি রেডিস ট্যাবে যাবেন এবং একটি ডাটাবেস তৈরি করবেন।


নিচে স্ক্রোল করুন যতক্ষণ না REST API সেকশন পাওয়া যায় এবং .env বাটন সিলেক্ট করুন। কন্টেন্ট কপি করে কোথাও নিরাপদে সংরক্ষণ করুন।

নতুন Next.js অ্যাপ্লিকেশন তৈরি করুন
চলুন একটি নতুন Next.js প্রজেক্ট তৈরি করি। আপনার টার্মিনাল খুলুন এবং নিচের কমান্ড চালান:
npx create-next-app@latest my-app প্রম্পট করার সময়, নিচের অপশনগুলো বেছে নিন:
- TypeScript ব্যবহার করার জন্য প্রম্পট করলে
Yes। - ESLint ব্যবহার করার জন্য প্রম্পট করলে
No। - Tailwind CSS ব্যবহার করার জন্য প্রম্পট করলে
Yes। src/ডিরেক্টরি ব্যবহার করার জন্য প্রম্পট করলেNo।- App Router ব্যবহার করার জন্য প্রম্পট করলে
Yes। - ডিফল্ট ইমপোর্ট এলিয়াস (
@/*) কাস্টোমাইজ করার জন্য প্রম্পট করলেNo।
এটি হলে, প্রজেক্ট ডিরেক্টরিতে যান এবং ডেভেলপমেন্ট মোডে অ্যাপ শুরু করুন নিচের কমান্ড চালিয়ে:
cd my-app npm run dev অ্যাপ localhost:3000-এ চলতে থাকবে। ডেভেলপমেন্ট সার্ভার বন্ধ করুন LangChain ডিপেন্ডেন্সি ইনস্টল করার জন্য অ্যাপ্লিকেশনে নিচের কমান্ড চালিয়ে:
npm install @langchain/openai @langchain/community উপরোক্ত কমান্ড নিচের লাইব্রেরি ইনস্টল করেছে:
@langchain/openai: OpenAI সিরিজ মডেলের সাথে ইন্টারফেস করার জন্য একটি LangChain প্যাকেজ।@langchain/community: LangChain কোরের সাথে প্লাগ-এন-প্লে করার জন্য থার্ড পার্টি ইন্টিগ্রেশন কালেকশন।
এখন, আপনার প্রজেক্টের রুটে একটি .env ফাইল তৈরি করুন। আপনি আগে প্রাপ্ত OPENAI_API_KEY এড করবেন।
এটি এমন দেখাবে:
# .env # OpenAI Environment Variable OPENAI_API_KEY="..." # Upstash Redis Environment Variables UPSTASH_REDIS_REST_URL="..." UPSTASH_REDIS_REST_TOKEN="..." Next.js-এ API এন্ডপয়েন্ট তৈরি করতে, আপনি Next.js Route Handlers ব্যবহার করবেন যা Web Request এবং Response APIs-এর মাধ্যমে রেসপন্স সার্ভ করতে দেয়। Next.js-এ একটি API রাউট তৈরি করার জন্য যা রেসপন্স স্ট্রিম করে ইউজারের কাছে, নিচের কমান্ড চালান:
mkdir -p app/api/stream/completion/chat mkdir app/lib -p ফ্ল্যাগ chat ডিরেক্টরির জন্য পেরেন্ট ডিরেক্টরি তৈরি করে যদি সেগুলো মিসিং থাকে।
এটি আমাদের Next.js প্রজেক্ট সেটআপ করে। এখন, আপস্ট্যাশের সাথে একটি ক্যাশ হ্যান্ডলার তৈরি করা যাক।
Upstash Redis ক্যাশ ক্লায়েন্ট ইনস্ট্যানশিয়েট করুন
UpstashRedisCache ক্লাস দিয়ে, আপনি কয়েক লাইন কোডে OpenAI API রেসপন্স ক্যাশ করার জন্য একটি রেডিস ক্যাশ ক্লায়েন্ট ইনিশিয়ালাইজ করতে পারেন। app/lib ডিরেক্টরির ভিতরে upstashCache.tsx নামে একটি ফাইল তৈরি করুন:
ক্যাশ হ্যান্ডলার ব্যবহার করে, OpenAI API দ্বারা জেনারেট হওয়া কনভারসেশন বা কমপ্লিশন রেসপন্স ক্যাশ করা সুপার ইজি হয়ে যায়। চলুন বুঝি কীভাবে Next.js-এ Server-Sent Events ব্যবহার শুরু করতে হয়।
Next.js App Router-এ Server-Sent Events API তৈরি করা
Server-Sent Events (SSE) আপনাকে সার্ভার থেকে ক্লায়েন্টে রিয়েল-টাইম ডেটা আপডেট ডেলিভার করতে দেয় কন্টিনিউঅস পোলিং ছাড়া। SSE একটি একদিকনির্দেশক ডেটা ফ্লো সক্ষম করে একটি একক, লং-লিভড HTTP কানেকশনের ওপর।
app/api/stream ডিরেক্টরিতে route.ts নামে একটি ফাইল নিচের কোড দিয়ে তৈরি করুন SSE ব্যবহার করে রেসপন্স স্ট্রিম করার জন্য প্রয়োজনীয় মিনিমাল সেটআপ বুঝতে:
// File: app/api/stream/route.ts // এই রাউটের রেসপন্স Vercel-এ ক্যাশ হয়ে যাওয়া থেকে বাধা দেয় export const dynamic = "force-dynamic"; export async function POST(request: Request) { const encoder = new TextEncoder() // একটি স্ট্রিমিং রেসপন্স তৈরি করুন const customReadable = new ReadableStream({ start(controller) { const message = "A sample message." controller.enqueue(encoder.encode(`data: ${message}\n\n`)) }, }) // স্ট্রিম রেসপন্স রিটার্ন করুন এবং কানেকশন জীবন্ত রাখুন return new Response(customReadable, { // Server-Sent Events (SSE) জন্য হেডার সেট করুন headers: { Connection: "keep-alive", "Content-Encoding": "none", "Cache-Control": "no-cache, no-transform", "Content-Type": "text/event-stream; charset=utf-8", }, }) } উপরের কোড নিম্নলিখিত কাজ করে:
dynamicকনস্ট্যান্টforce-dynamicসেট করা হয়েছে, Vercel প্ল্যাটফর্মে রেসপন্স ক্যাশ হয়ে যাওয়া থেকে বাধা দিতে। এটি নিশ্চিত করে যে SSE স্ট্রিমের প্রতিটি রিকোয়েস্ট ফ্রেশ ডেটা পায় এবং ক্যাশ থেকে সার্ভ হয় না।- একটি
ReadableStreamতৈরি করা হয়েছে ক্লায়েন্টকে পাঠানো ডেটার একটি স্ট্রিম জেনারেট করার জন্য। স্ট্রিমেরstartমেথডে, একটি মেসেজ এনকোড করে স্ট্রিমের কন্ট্রোলারে এনকিউ করা হয়েছে। এই মেসেজ SSE স্ট্রিমের অংশ হিসেবে ক্লায়েন্টকে পাঠানো হবে। Responseঅবজেক্ট Server-Sent Events-এর জন্য স্পেসিফিক হেডার সহ তৈরি করা হয়েছে। এই হেডারগুলো অন্তর্ভুক্ত করে:Connection: keep-aliveস্ট্রিমিং জন্য কানেকশন ওপেন রাখতে।Cache-Control: no-cache, no-transformব্রাউজারে ক্যাশিং প্রতিবন্ধক করতে।Content-Type: text/event-stream; charset=utf-8কন্টেন্ট টাইপ Server-Sent Events হিসেবে স্পেসিফাই করতে।
- কাস্টম
ReadableStreamধারণকারীResponseঅবজেক্ট এন্ডপয়েন্ট থেকে রিটার্ন করা হয়। এই রেসপন্স SSE স্ট্রিম রিকোয়েস্ট করার ক্লায়েন্টদের পাঠানো হবে।
এটি দিয়ে, আপনি একটি এন্ডপয়েন্ট তৈরি করলেন যা রেসপন্স স্ট্রিম করতে পারে। পরবর্তী সেকশনে, আপনি বুঝবেন কীভাবে OpenAI-এর Completion এবং Chat Completion API রেসপন্স LangChain কলব্যাকস দিয়ে স্ট্রিম করতে হয়।
LangChain কলব্যাকস দিয়ে OpenAI Completion API রেসপন্স স্ট্রিমিং
OpenAI Completion API দেওয়া প্রম্পটের ভিত্তিতে টেক্সট জেনারেট করার একটি পাওয়ারফুল টুল, যা রিয়েল-লাইফ সিনেরিওর জন্য উপযোগী যেন কন্টেন্ট জেনারেশন এবং ল্যাঙ্গুয়েজ ট্রান্সলেশন। LangChain কলব্যাকস ইন্টিগ্রেট করলে রিয়েল-টাইম স্ট্রিমিং রেসপন্স সক্ষম হয়, অ্যাপ্লিকেশনে পারসিভড রেসপন্সিভনেস বাড়ায়।
app/lib ডিরেক্টরিতে completionModel.tsx নামে একটি ফাইল তৈরি করুন, একটি ফাংশন ডিফাইন করে যা একটি OpenAI ইনস্ট্যান্স ইনিশিয়ালাইজ করে স্ট্রিমিং সক্ষম এবং LangChain কলব্যাকস সহ, রিয়েল-টাইমে টেক্সট জেনারেট করে।
// File: app/lib/completionModel.tsx import { OpenAI } from "@langchain/openai"; export const completionModel = ( controller: ReadableStreamDefaultController, encoder: TextEncoder ) => new OpenAI({ streaming: true, callbacks: [ { handleLLMNewToken(token) { controller.enqueue(encoder.encode(`data: ${token}\n\n`)); }, async handleLLMEnd(output) { controller.close(); }, }, ], }); উপরের কোড নিম্নলিখিত কাজ করে:
@langchain/openaiপ্যাকেজ থেকেOpenAIক্লাস ইমপোর্ট করে।completionModelনামে একটি ফাংশন এক্সপোর্ট করে যা দুটি প্যারামিটার নেয়:- controller: একটি
ReadableStreamDefaultControllerঅবজেক্ট যা আপনাকে স্ট্রিমে মেসেজ এনকিউ করতে দেয়। - encoder: একটি
TextEncoderঅবজেক্ট যা মেসেজUint8Arrayঅবজেক্টে এনকোড করে।
- controller: একটি
OpenAIক্লাসের একটি নতুন ইনস্ট্যান্স তৈরি করে নিচের কনফিগারেশন অপশন সহ:streaming: true সেট করা হয়েছে, নির্দেশ করে যে API স্ট্রিমিং রেসপন্স রিটার্ন করবে।callbacks: একটি সিঙ্গেল অবজেক্ট ধারণকারী অ্যারে যার দুটি কলব্যাক ফাংশন, LLM দ্বারা রেসপন্স ক্রিয়েশন প্রতিটি স্টেজে ইন্টারসেপ্ট করতে ব্যবহৃত হয়।
handleLLMNewToken: ল্যাঙ্গুয়েজ মডেল দ্বারা নতুন টোকেন জেনারেট হলে আহ্বানিত একটি কলব্যাক। এটি এনকোডেড টোকেন কন্ট্রোলারে এনকিউ করে।handleLLMEnd: ল্যাঙ্গুয়েজ মডেল জেনারেশন কম্প্লিট হলে আহ্বানিত একটি অ্যাসিনক্রোনাস কলব্যাক। এটি কন্ট্রোলার বন্ধ করে।
আরো, app/api/stream/completion ডিরেক্টরিতে route.ts নামে একটি ফাইল নিচের কোড দিয়ে তৈরি করুন। আপনার তৈরি করা প্রাথমিক স্ট্রিমিং রাউট হ্যান্ডলার থেকে পরিবর্তনগুলো নিচে হাইলাইট করা হয়েছে:
// File: app/api/stream/completion/route.ts // এই রাউটের রেসপন্স Vercel-এ ক্যাশ হয়ে যাওয়া থেকে বাধা দেয় export const dynamic = "force-dynamic"; + import { completionModel } from "@/app/lib/completionModel"; export async function POST(request: Request) { + // রিকোয়েস্ট বডি থেকে ইউজার মেসেজ পান + const { message } = await request.json(); const encoder = new TextEncoder(); // একটি স্ট্রিমিং রেসপন্স তৈরি করুন const customReadable = new ReadableStream({ async start(controller) { + // LangChain দিয়ে OpenAI থেকে স্ট্রিমিং রেসপন্স জেনারেট করুন + await completionModel(controller, encoder).invoke(message); }, }); // স্ট্রিম রেসপন্স রিটার্ন করুন এবং কানেকশন জীবন্ত রাখুন return new Response(customReadable, { // Server-Sent Events (SSE) জন্য হেডার সেট করুন headers: { Connection: "keep-alive", "Content-Encoding": "none", "Cache-Control": "no-cache, no-transform", "Content-Type": "text/event-stream; charset=utf-8", }, }); } আপনি আগে স্ট্রিমিং এন্ডপয়েন্ট তৈরি করার জন্য যা করলেন তার পাশাপাশি, উপরের কোড এডিশনগুলো নিম্নলিখিত কাজ করে:
completionModelফাংশন ইমপোর্ট করে।request.json()ব্যবহার করে রিকোয়েস্ট বডি থেকে ইউজার মেসেজ এক্সট্রাক্ট করে।ReadableStream-এরstartমেথডের ভিতরে,completionModelফাংশন রিকোয়েস্ট থেকে প্রাপ্ত মেসেজ সহ অ্যাসিনক্রোনাসলি আহ্বান করা হয়। এই ফাংশন LangChain দিয়ে OpenAI থেকে একটি স্ট্রিমিং রেসপন্স জেনারেট করে।
Upstash দিয়ে ইউজার কোয়েরি এবং তাদের রেসপন্স ক্যাশ করতে, Upstash Redis ক্যাশ ক্লায়েন্ট completionModel ফাংশনে ইমপোর্ট করুন নিচের মত:
import { OpenAI } from "@langchain/openai"; + import cache from '@/app/lib/upstashCache'; export const completionModel = ( controller: ReadableStreamDefaultController, encoder: TextEncoder ) => new OpenAI({ + cache, streaming: true, temperature: 0.9, callbacks: [ { handleLLMNewToken(token) { controller.enqueue(encoder.encode(token)); }, async handleLLMEnd(output) { console.log(output.generations[0][0].text); controller.close(); }, }, ], }); মিনিমাল পরিবর্তন দিয়ে, আপনি Upstash দিয়ে OpenAI Completion API রেসপন্স ক্যাশিং সক্ষম করেছেন।
এখন, চলুন শিখি কীভাবে OpenAI Chat Completion API রেসপন্স Next.js এন্ডপয়েন্টে স্ট্রিম করা যায়।
LangChain কলব্যাকস দিয়ে OpenAI Chat Completion API রেসপন্স স্ট্রিমিং
OpenAI Chat Completion API প্রদত্ত মেসেজের ভিত্তিতে রিয়েল-টাইম কনভারসেশনাল রেসপন্স জেনারেট করার একটি পাওয়ারফুল টুল। অ্যাপ্লিকেশন পারură ন্যাচারেল ডায়লগে সক্ষম চ্যাটবট বানান থেকে AI-চালিত ইন্টারঅ্যাকশন ক্যাপাবিলিটি দিয়ে কাস্টমার সাপোর্ট সিস্টেম বাড়াতে। এটি ডেভেলপারদের ডাইনামিক এবং রেসপন্সিভ কনভারসেশনাল ইন্টারফেস তৈরি করতে সক্ষম করে।
app/lib ডিরেক্টরিতে chatCompletionModel.tsx নামে একটি ফাইল তৈরি করুন, একটি chatCompletionModel ফাংশন ডিফাইন করে যা OpenAI-এর Chat Completion API-এর জন্য একটি স্ট্রিমিং ইন্টারফেস তৈরি করে LangChain কলব্যাকস সহ, প্রদত্ত মেসেজের ভিত্তিতে রিয়েল-টাইম কনভারসেশন জেনারেশন সক্ষম করে।
// File: app/lib/chatCompletionModel.tsx import { ChatOpenAI } from "@langchain/openai"; export type ConversationMessage = { role: string; content: string; }; export type ConversationMessages = ConversationMessage[]; export const chatCompletionModel = ( controller: ReadableStreamDefaultController, encoder: TextEncoder ) => new ChatOpenAI({ streaming: true, callbacks: [ { handleLLMNewToken(token) { controller.enqueue(encoder.encode(`data: ${token}\n\n`)); }, async handleLLMEnd(output) { controller.close(); }, }, ], }); উপরের কোড নিম্নলিখিত কাজ করে:
@langchain/openaiপ্যাকেজ থেকেChatOpenAIক্লাস ইমপোর্ট করে।- নিচের টাইপ ডেফিনিশন তৈরি করে:
ConversationMessage: একটি কনভারসেশনে একটি সিঙ্গেল মেসেজের টাইপ ডিফাইন করে। এতে দুটি প্রপার্টি থাকে: role (সেন্ডারের ভূমিকা নির্দেশ করে) এবং content (মেসেজ কন্টেন্ট)।ConversationMessages: কনভারসেশন মেসেজের একটি অ্যারের টাইপ ডিফাইন করে।
chatCompletionModelনামে একটি ফাংশন এক্সপোর্ট করে যা দুটি প্যারামিটার নেয়:- controller: একটি
ReadableStreamDefaultControllerঅবজেক্ট যা আপনাকে স্ট্রিমে মেসেজ এনকিউ করতে দেয়। - encoder: একটি
TextEncoderঅবজেক্ট যা মেসেজUint8Arrayঅবজেক্টে এনকোড করে।
- controller: একটি
ChatOpenAIক্লাসের একটি নতুন ইনস্ট্যান্স তৈরি করে নিচের কনফিগারেশন অপশন সহ:streaming: true সেট করা হয়েছে, নির্দেশ করে যে API স্ট্রিমিং রেসপন্স রিটার্ন করবে।callbacks: একটি সিঙ্গেল অবজেক্ট ধারণকারী অ্যারে যার দুটি কলব্যাক ফাংশন, LLM দ্বারা রেসপন্স ক্রিয়েশন প্রতিটি স্টেজে ইন্টারসেপ্ট করতে ব্যবহৃত হয়।
handleLLMNewToken: ল্যাঙ্গুয়েজ মডেল দ্বারা নতুন টোকেন জেনারেট হলে আহ্বানিত একটি কলব্যাক। এটি এনকোডেড টোকেন কন্ট্রোলারে এনকিউ করে।handleLLMEnd: ল্যাঙ্গুয়েজ মডেল জেনারেশন কম্প্লিট হলে আহ্বানিত একটি অ্যাসিনক্রোনাস কলব্যাক। এটি কন্ট্রোলার বন্ধ করে।
আরো, app/api/stream/completion/chat ডিরেক্টরিতে route.ts নামে একটি ফাইল নিচের কোড দিয়ে তৈরি করুন। আপনার তৈরি করা প্রাথমিক স্ট্রিমিং রাউট হ্যান্ডলার থেকে পরিবর্তনগুলো নিচে হাইলাইট করা হয়েছে:
// File: app/api/stream/completion/chat/route.ts // এই রাউটের রেসপন্স Vercel-এ ক্যাশ হয়ে যাওয়া থেকে বাধা দেয় export const dynamic = "force-dynamic"; + import { + type ConversationMessage, + chatCompletionModel, + } from "@/app/lib/chatCompletionModel"; export async function POST(request: Request) { + // রিকোয়েস্ট বডি থেকে কনভারসেশন মেসেজ পান + const { messages = [] } = await request.json(); const encoder = new TextEncoder(); // একটি স্ট্রিমিং রেসপন্স তৈরি করুন const customReadable = new ReadableStream({ async start(controller) { + // LangChain দিয়ে OpenAI থেকে স্ট্রিমিং রেসপন্স জেনারেট করুন + await chatCompletionModel(controller, encoder).invoke( + messages.map((i: ConversationMessage) => [i["role"], i["content"]]) + ); }, }); // স্ট্রিম রেসপন্স রিটার্ন করুন এবং কানেকশন জীবন্ত রাখুন return new Response(customReadable, { // Server-Sent Events (SSE) জন্য হেডার সেট করুন headers: { Connection: "keep-alive", "Content-Encoding": "none", "Cache-Control": "no-cache, no-transform", "Content-Type": "text/event-stream; charset=utf-8", }, }); } আপনি আগে স্ট্রিমিং এন্ডপয়েন্ট তৈরি করার জন্য যা করলেন তার পাশাপাশি, উপরের কোড এডিশনগুলো নিম্নলিখিত কাজ করে:
chatCompletionModelফাংশন এবংConversationMessageটাইপ ডেফিনিশন ইমপোর্ট করে।request.json()ব্যবহার করে রিকোয়েস্ট বডি থেকে কনভারসেশনের মেসেজ এক্সট্রাক্ট করে।ReadableStream-এরstartমেথডের ভিতরে,chatCompletionModelফাংশন ট্রান্সফর্মড মেসেজ অ্যারে সহ অ্যাসিনক্রোনাসলি আহ্বান করা হয়। প্রতিটি মেসেজ একটি অ্যারে হিসেবে ট্রান্সফর্ম করা হয়েছে যেটিতে মেসেজের role এবং content থাকে। এই ফাংশন LangChain দিয়ে OpenAI থেকে একটি স্ট্রিমিং রেসপন্স জেনারেট করে।
Upstash দিয়ে চ্যাট হিস্টরি ক্যাশ করতে, Upstash Redis ক্যাশ ক্লায়েন্ট chatCompletionModel ফাংশনে ইমপোর্ট করুন নিচের মত:
+ import cache from '@/app/lib/upstashCache'; import { ChatOpenAI } from "@langchain/openai"; export type ConversationMessage = { role: string; content: string; }; export type ConversationMessages = ConversationMessage[]; export const chatCompletionModel = ( controller: ReadableStreamDefaultController, encoder: TextEncoder ) => new ChatOpenAI({ + cache, streaming: true, temperature: 0.9, callbacks: [ { handleLLMNewToken(token) { controller.enqueue(encoder.encode(token)); }, async handleLLMEnd(output) { console.log(output.generations[0][0].text); controller.close(); }, }, ], }); মিনিমাল পরিবর্তন দিয়ে, আপনি Upstash দিয়ে পুরো চ্যাট হিস্টরি ক্যাশিং সক্ষম করেছেন।
এখন, চলুন স্ট্রিমিং এন্ডপয়েন্ট কনসিউম করার জন্য ক্লায়েন্ট সাইড React কম্পোনেন্ট তৈরি করি।
Server-Sent Events শোনার জন্য Next.js ফ্রন্টএন্ড সেটআপ
এই সেকশনে, আপনি শিখবেন কীভাবে Server-Sent Events API মেসেজ শোনার জন্য একটি মিনিমাল লিসেনার সেটআপ করতে হয়, এবং ইউজার এবং AI-এর মধ্যে এক্সচেঞ্জ হওয়া মেসেজের স্টেট ম্যানেজ করার একটি পদ্ধতি।
React-এ Server-Sent Events API শোনা
React-এ আমাদের ক্লায়েন্ট সাইড কম্পোনেন্টে SSE API শোনার জন্য, আপনি নির্দিষ্ট API রাউটে একটি POST রিকোয়েস্ট ইনিশিয়েট করবেন। রেসপন্স পাওয়ার পর, আপনি ইনকামিং ডেটা TextDecoderStream মেথড ব্যবহার করে স্ট্রিং হিসেবে ডিকোড করবেন, এবং স্ট্রিম থেকে ডেটা কন্টিনিউয়াসলি পড়বেন।
"use client"; export default function () { const obtainAPIResponse = async (apiRoute: string, apiData: any) => { // SSE API-র সাথে কানেক্ট করার জন্য প্রথম কল ইনিশিয়েট করুন const apiResponse = await fetch(apiRoute, { method: "POST", headers: { "Content-Type": "text/event-stream", }, body: JSON.stringify(apiData), }); if (!apiResponse.body) return; // ইনকামিং ডেটা স্ট্রিং হিসেবে ডিকোড করতে const reader = apiResponse.body .pipeThrough(new TextDecoderStream()) .getReader(); while (true) { const { value, done } = await reader.read(); if (done) { break; } if (value) { // কিছু করুন } } }; return <></> } React-এ কনভারসেশনের স্টেট ম্যানেজ করা
ইউজার এবং চ্যাটবটের মধ্যে কনভারসেশনের স্টেট ম্যানেজ করতে, আপনি স্টেট ভেরিয়েবল ব্যবহার করতে পারেন। আপনি messages এবং latestMessage স্টেট ভেরিয়েবল আপডেট করবেন কনভারসেশন হিস্টরি এবং লেটেস্ট মেসেজ সংরক্ষণ করার জন্য। SSE API থেকে ইনকামিং ডেটা প্রসেস করার লুপের ভিতরে এই স্টেট ভেরিয়েবল আপডেট করলে, আপনি কনভারসেশন ডিসপ্লের রিয়েল-টাইম আপডেট নিশ্চিত করতে পারেন। এটার জন্য কোড এডিশনগুলো নিচে:
"use client"; + import { useEffect, useState } from "react"; + import { ConversationMessages } from "@/app/lib/chatCompletionModel"; export default function () { + const [latestMessage, setLatestMessage] = useState<string>(""); + const [messages, setMessages] = useState<ConversationMessages>([]); const obtainAPIResponse = async (apiRoute: string, apiData: any) => { // SSE API-র সাথে কানেক্ট করার জন্য প্রথম কল ইনিশিয়েট করুন const apiResponse = await fetch(apiRoute, { method: "POST", headers: { "Content-Type": "text/event-stream", }, body: JSON.stringify(apiData), }); if (!apiResponse.body) return; // ইনকামিং ডেটা স্ট্রিং হিসেবে ডিকোড করতে const reader = apiResponse.body .pipeThrough(new TextDecoderStream()) .getReader(); + let incomingMessage = ""; while (true) { const { value, done } = await reader.read(); if (done) { + // পাওয়া রেসপন্স messages state-এ ইনসার্ট করুন + setMessages((messages) => [ + ...messages, + { role: "assistant", content: incomingMessage }, + ]); + // রিসিভড লেটেস্ট মেসেজের স্টেট রিসেট করুন + setLatestMessage(""); break; } if (value) { + // ইনকামিং ডেটা লেটেস্ট মেসেজের ভ্যালুতে অ্যাপেন্ড করুন + incomingMessage += value; + setLatestMessage(incomingMessage); } } }; return <></> } উপরের কোড এডিশনগুলো নিম্নলিখিত কাজ করে:
- SSE API থেকে রিসিভড ইনকামিং ডেটা স্ট্রিম সংরক্ষণ করার জন্য একটি স্টেট ভেরিয়েবল ডিক্লেয়ার করা হয়েছে।
- একটি কমপ্লিট মেসেজ পাওয়ার পর (
donetrue হলে নির্দেশিত), লেটেস্ট রিসিভড মেসেজmessagesস্টেট অ্যারেয়ে যোগ করা হয়। এই মেসেজ assistant রোল দিয়ে ফরম্যাট করা হয় ইউজার মেসেজ থেকে আলাদা করার জন্য। অথবা, লেটেস্ট মেসেজ স্টেট খালি স্ট্রিং-এ রিসেট করা হয় পরবর্তী ইনকামিং মেসেজের জন্য প্রস্তুত হওয়ার জন্য। - যে সময় ডেটা ইনক্রিমেন্টালি রিসিভ হয় (এখনও কমপ্লিট মেসেজ ফর্ম করা নয়), সেটি
incomingMessageভেরিয়েবলে অ্যাপেন্ড করা হয়। - লেটেস্ট মেসেজ স্টেট কনক্যাটেনেটেড ইনকামিং ডেটা দিয়ে আপডেট করা হয়, নতুন ডেটা আসার সাথে সাথে রিয়েল-টাইম আপডেট নিশ্চিত করে।
বাজি! রিয়েক্টিভ latestMessage এবং messages ভেরিয়েবল দিয়ে, আপনি এখন কনভারসেশনে এক্সচেঞ্জ হওয়া মেসেজ এবং লেটেস্ট AI জেনারেটেড রেসপন্স রিপ্রেজেন্ট করার ডাইনামিক ইউজার ইন্টারফেস তৈরি করতে পারেন।
খুব সকল শেখা হয়েছে! আপনি এখন ডান ✨
Vercel-এ ডিপ্লয় করুন
রিপোজিটরি এখন Vercel-এ ডিপ্লয় করার জন্য প্রস্তুত। ডিপ্লয় করার জন্য নিচের ধাপগুলো ফলো করুন:
- আপনার অ্যাপের কোড ধারণকারী একটি GitHub রিপোজিটরি তৈরি করুন।
- তারপর, Vercel Dashboard-এ যান এবং একটি New Project তৈরি করুন।
- নতুন প্রজেক্টকে আপনার তৈরি করা GitHub রিপোজিটরির সাথে লিংক করুন।
- Settings-এ, Environment Variables আপডেট করুন যাতে আপনার লোকাল
.envফাইলের সাথে মেলে। - Deploy! 🚀
আরও তথ্য
আরো বিস্তারিত ইনসাইটের জন্য, এই পোস্টে সাইটেড রেফারেন্স এক্সপ্লোর করুন।
- GitHub Repository
- Server Sent Events
- Next.js Streaming
- LLMs-এর জন্য ক্যাশিং লেয়ার