AI রিসার্চ এজেন্টের পরিচিতি
একাডেমিক রিসার্চ খুব দ্রুত চলে - নতুন পেপাররা প্রতিদিন arXiv এবং অন্যান্য প্রি-প্রিন্ট সার্ভারে প্রকাশিত হয়। ম্যানুয়ালি টেক কারিখ রাখা 오ভারওয়েলমিং হতে পারে। এই গাইডে, আমরা একটি AI রিসার্চ অ্যাসিস্ট্যান্ট বানাব যা:
- একজন রিসার্চারের ন্যাচারাল-ল্যাঙ্গুয়েজ প্রশ্ন বুঝবে
- arXiv অ্যাবস্ট্রাক্টের একটি ভেক্টর ডাটাবেসে সবচেয়ে রিলেভান্ট পেপারগুলো খুঁজে বের করবে
- মূল ইনসাইট সারমর্ম করবে এবং ব্যাখ্যা করবে কীভাবে সেগুলো প্রশ্নের উত্তর দেয়
- গভীর পড়ার জন্য ডাইরেক্ট PDF লিংক প্রদান করবে
আমরা এটা সম্পন্ন করব Mastra-এর সাথে, একটি ওপেন-সোর্স TypeScript ফ্রেমওয়ার্ক AI এজেন্ট বানাতে, এবং Upstash-এর সাথে সার্ভারলেস Redis এবং Vector স্টোরেজের জন্য। এখানে আমাদের আর্টিকেল এজেন্টের একটি লাইভ ডেমো যা AI রিসার্চের ওপর ফোকাসড। এটি Vercel-এ ডিপ্লয়েড আপনাদের ট্রাই করার জন্য।

Mastra কী?
Mastra একটি ব্যাটারি-ইনক্লুডেড ফ্রেমওয়ার্ক যা প্রোডাকশন-গ্রেড AI এজেন্ট বানানো সহজ করে দেয়।
- এজেন্ট ও ওয়ার্কফ্লো — এজেন্ট, টুল, এবং মাল্টি-স্টেপ ওয়ার্কফ্লো কম্পোজ করুন
- Retrieval-Augmented Generation (RAG) - বিল্ট-ইন মেমরি এবং ভেক্টর স্টোর
- Multi-LLM - OpenAI, Claude এবং আরও অনেক কিছুর সাথে কাজ করে।
আমরা একটি এজেন্ট তৈরি করব যা Upstash Redis ব্যবহার করে মেমরির জন্য। এটিতে একটি টুলও থাকবে রিলেভান্ট রিসার্চ আর্টিকেল খুঁজে বের করার জন্য, যেগুলো আমরা পূর্বে Upstash Vector ডাটাবেসে এম্বেড করে রাখব।
গভীরে জানতে, Mastra ডকুমেন্টেশন চেক আউট করুন।
প্রজেক্টের টেক স্ট্যাক
- Mastra Framework AI এজেন্ট এবং টুল তৈরি করার জন্য
- Upstash Redis এজেন্টকে কনভারসেশন মেমরি দিতে
- Upstash Vector রিসার্চ আর্টিকেল অ্যাবস্ট্রাক্টের এম্বেডিং স্টোর করার জন্য
- Next.js এবং Vercel ওয়েব অ্যাপ্লিকেশন বানাতে এবং ডিপ্লয় করার জন্য
আমরা Upstash Ratelimitও ব্যবহার করব আমাদের ডেমো অ্যাপ্লিকেশনের জন্য রিকোয়েস্ট লিমিট করার জন্য।
ইমপ্লিমেন্টেশন ওয়াকথ্রু
এই অ্যাপ্লিকেশন বানাতে দুটি মূল কম্পোনেন্ট তৈরি করা লাগে: Mastra সার্ভার এবং ওয়েব অ্যাপ্লিকেশন। সেগুলো একই প্রজেক্টে থাকতে পারে, তবে আলাদা রাখা ক্লিনার। Mastra সার্ভার দিয়ে শুরু করি।
Mastra প্রজেক্ট তৈরি করা
একটি নতুন Mastra প্রজেক্ট তৈরি করতে, আপনার টার্মিনালে নিচের কমান্ডটি রান করুন।
npm create mastra@latest
এটা কয়েকটি প্রশ্ন করবে; এই প্রজেক্টের জন্য ডিফল্ট সেটিংস ঠিক আছে।
এজেন্ট এবং টুল তৈরি করা
একজন এজেন্ট কনফিগার করার প্রথম ধাপ হলো এর নাম, উদ্দেশ্য, এবং টুল ডিফাইন করা। এছাড়া প্রদত্ত টাস্কের জন্য ভালো পারফর্ম করার একটি ল্যাঙ্গুয়েজ মডেল বেছে নেওয়া গুরুত্বপূর্ণ। এই প্রজেক্টে, আমাদের এক জন এজেন্ট এবং একটা টুল থাকবে।
export const articleAgent = new Agent({
name: "articleAgent",
instructions: instruction,
model: openai('gpt-4o'),
tools: { articleQueryTool },
memory: memory
});
এজেন্ট কনফিগার করা উপরের কোডের মত সহজ। আমরা আমাদের articleAgent-কে একটি instruction (যেটি সিস্টেম প্রম্পট হিসেবে কাজ করে), এর ডেডিকেটেড tools, model, এবং আরেকটি গুরুত্বপূর্ণ কম্পোনেন্ট: memory দিয়ে ডিফাইন করি।
এজেন্টের মেমরি
Mastra এজেন্টদের চ্যাট হিস্টরি এবং সেমান্টিক রিকল ক্যাপাবিলিটি দুটোই দেয়। স্টোরেজে মেমরি মেইনটেইন করে, এজেন্ট আরও পার্সোনালাইজড এবং সঠিক উত্তর দিতে পারে। চলুন আমাদের এজেন্টের মেমরি কনফিগারেশন দেখি।
export const memory = new Memory({
storage: myUpstashStore,
options: {
lastMessages: 10,
semanticRecall: false,
threads: { generateTitle: true }
}
});
চ্যাট হিস্টরি ইনেবল করার জন্য, আমরা Upstash Redis ব্যবহার করি আমাদের স্টোরেজ অপশন হিসেবে। আমরা এটি একটি UpstashStore অবজেক্ট হিসেবে ইনিশিয়ালাইজ করি, যা MastraStorage-কে এক্সটেন্ড করে, নিশ্চিত করে যে এটি আমাদের Mastra এজেন্টের সাথে স্মুথলি কাজ করে।
export const myUpstashStore = new UpstashStore({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
আমরা পূর্বে এজেন্টে সেমান্টিক রিকল ফিচার যোগ করার কথা বলেছিলাম, যা এজেন্টকে বর্তমান কন্টেক্সটের সাথে সম্পর্কিত পূর্বের মেসেজগুলো বিবেচনা করতে দেয়। সেটার জন্য, এজেন্টকে একটি ভেক্টর ডাটাবেস এবং মেসেজ প্রসেস করার একটি এম্বেডার দরকার। যেহেতু আমাদের পাবলিক ডেমো পারসোনাল ইউজের জন্য নয় এবং বিভিন্ন থ্রেড জুড়ে মেসেজ মনে রাখতে হবে না, আমরা এই ফিচার ব্যবহার করব না, তবে এটি নিচের মত ইমপ্লিমেন্ট করা যায়।
export const myUpstashVector = new UpstashVector({
url: process.env.UPSTASH_VECTOR_REST_URL!,
token: process.env.UPSTASH_VECTOR_REST_TOKEN!,
});
export const memory = new Memory({
storage: myUpstashStore,
vector: myUpstashVector,
embedder: openai.embedding("text-embedding-3-small"),
options: {
lastMessages: 10,
semanticRecall: {
topK: 3,
messageRange: 2,
scope: 'resource'
},
threads: { generateTitle: true }
}
});
সেমান্টিক রিকল কনফিগারেশনে, topK స্পেসিফাই করে কতটা সিমিলার মেসেজ রিট্রিভ করা হবে, messageRange ডিফাইন করে প্রতিটি ম্যাচের সাথে কতটুকু সারাউন্ডিং কন্টেক্সট ইনক্লুড করা হবে, এবং scope 'resource'-এ সেট করলে এজেন্ট 'resource' নামে ইউজারের সাথে জড়িত সকল থ্রেড জুড়ে সার্চ করে। এই ক্রস-থ্রেড মেমরি Upstash-এ উপলব্ধ একটি পাওয়ারফুল ফিচার।
টুলস
একটি টুল তৈরি করা আজ事实证明 এজেন্ট বানানোর চেয়ে সহজ। আমরা একটি নাম, বর্ণনা, ইনপুট এবং আউটপুট স্কিমা, এবং একটি ফাংশন প্রদান করি যা এক্সিকিউট হবে যখন এজেন্ট টুলটির ক্যাপাবিলিটি দরকার করবে।
export const articleQueryTool = createTool({
id: 'get-relevant-article',
description: 'Get relevant article information',
inputSchema: z.object({
question: z.string().describe('the question about the field'),
}),
outputSchema: z.object({
bestOption: z.object({
abstract: z.string().describe('the abstract of the article'),
title: z.string().describe('the title of the article'),
pdfUrl: z.string().describe('the PDF URL of the article')
})
}),
execute: async ({ context }) => {
return await querySimilar(context.question);
},
});
আমরা Zod ব্যবহার করি ইনপুট এবং আউটপুট স্কিমা ভ্যালিডেট করার জন্য। এটি কনসিস্টেন্ট রেসপন্স মেইনটেইন করতে সাহায্য করে এবং LLM থেকে পটেনশিয়াল এরর মিনিমাইজ করে। আমরা টুলের জন্য একটি ফাংশনও ডিফাইন করি। আমাদের টুল একটি বড় কালেকশন রিসার্চ আর্টিকেল কোয়েরি করবে, যা=arXiv API-এর মাধ্যমে পিরিয়ডিক্যালি আপডেট হয় এবং আমাদের Upstash Vector ডাটাবেসে এম্বেডেড থাকে।
const querySimilar = async (query: string) => {
const { embedding } = await embed({
value: query,
model: openai.embedding("text-embedding-3-small"),
});
const results = await myMastraUpstashVector.query({
indexName: "arxiv",
queryVector: embedding,
topK: 3,
});
if (results && results.length > 0) {
const bestMatch = results[0];
const metadata = bestMatch.metadata as ArxivPaper;
return {
bestOption: {
abstract: metadata.abstract,
title: metadata.title,
pdfUrl: metadata.pdfUrl
}
};
}
throw new Error("No relevant information found");
};
আমরা আমাদের ভেক্টর ডাটাবেসে সিম্পল অপারেশন পারফর্ম করতে পারি একটি UpstashVector ইনস্ট্যান্স দিয়ে, যা MastraVector-কে এক্সটেন্ড করে। উপরে, আমরা সিমিলার আর্টিকেল অ্যাবস্ট্রাক্ট কোয়েরি করি যেগুলো আমরা পূর্বে এম্বেড করেছি এবং টুলকে বেস্ট রেজাল্ট রিটার্ন করি। লক্ষ্য করুন যে আমরা কোয়েরির জন্য সেম এম্বেডিং মডেল ব্যবহার করছি যা আমরা আর্টিকেলগুলোর জন্য করেছিলাম। আর্টিকেল এম্বেডিং নিয়ে পরে বিস্তারিত বলব।
Mastra ইনস্ট্যান্স
export const mastra = new Mastra({
storage: myMastraUpstashStore,
agents: { articleAgent },
deployer: new VercelDeployer()
});
আমরা শুধু স্পেসিফাই করি কোন এজেন্টগুলো ব্যবহার করতে হবে, এবং আমাদের Mastra অবজেক্ট রেডি। আমরা স্টোরেজও প্রদান করি ডেটা পা arsen করতে ইন-মেমরি স্টোরেজের বাইরে। আপনি উপলব্ধ ডিপ্লয়মেন্ট কনফিগারেশন থেকে বেছে নেওয়া পারেন; আমরা Vercel ব্যবহার করব ডিপ্লয় করার জন্য।
create-mastra-app-এর ডিফল্ট অপশনগুলোতে, আমাদের ইতিমধ্যে প্রয়োজনীয় ফাইল স্ট্রাকচার আছে:
.
└── mastra
├── agents
│ └── index.ts
├── tools
│ └── index.ts
└── index.ts
ডিপ্লয় করার আগে শুধু এক ধাপ বাকি: আমাদের এনভায়রনমেন্ট ভেরিয়েবলস।
OPENAI_API_KEY=
UPSTASH_VECTOR_REST_URL=
UPSTASH_VECTOR_REST_TOKEN=
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
এগুলোর আপনার .env.local ফাইলে রাখুন লোকাল ডেভেলপমেন্টের জন্য এবং আপনার ডিপ্লয়মেন্ট এনভায়রনমেন্টে যোগ করুন।
এখন আমরা আমাদের Mastra সার্ভার বিল্ড এবং ডিপ্লয় করার জন্য রেডি।
npm run build && vercel --prod
Vercel ডকুমেন্টেশন চেক আউট করুন কীভাবে ডিপ্লয় করতে হয়।
ডেভেলপমেন্টের সময়, আমরা Mastra Playground ব্যবহার করতে পারি আমাদের সার্ভারের আউটপুট দেখতে। নিচের কমান্ডটি রান করুন:
npm run dev
এটা একটি লিংক দেবে একটি ওয়েব ইন্টারফেসের যেখানে আপনি আমাদের এজেন্টের সাথে চ্যাট করতে পারেন, টুলস এক্সপ্লিসিটলি রান করতে পারেন, এবং আমাদের সার্ভারের ক্যাপাবিলিটি এক্সপ্লোর করতে পারেন।
এখন আপনাকে ওয়েব অ্যাপ্লিকেশন সম্পর্কে কথা বলার পালা।
Next.js সার্ভার
Mastra সার্ভার সেট আপ হয়ে গেলে, আমাদের তিনটি জিনিস হ্যান্ডেল করতে হবে: UI, Mastra সার্ভারের সাথে কমিউনিকেশন, এবং একটি আর্টিকেল সার্ভিস যা arXiv API-র সাথে কথা বলে এবং অ্যাবস্ট্রাক্টগুলো Upstash Vector-এ এম্বেড করে। Mastra-এ একটি ক্লায়েন্ট SDK আছে সার্ভার সের ফাংশনালিটি এক্সপোজ করার জন্য। এর মাধ্যমে, আপনি এজেন্ট, টুল, মেমরি, এবং আরও অনেক কিছু অ্যাক্সেস করতে পারেন। এর ব্যবহার সোজা, কিন্তু আমরা কিছু উদাহরণ শেয়ার করব। আরও ডিটেলসের জন্য, ডকুমেন্টেশন চেক করুন। Next.js প্রজেক্টে, আপনি সিম্পলি ক্লায়েন্ট SDK ইনস্টল এবং ব্যবহার করতে পারেন।
npm install @mastra/client-js@latest
আপনার কোডে, MastraClient-এর একটি ইনস্ট্যান্স তৈরি করুন আপনার প্রজেক্টে ব্যবহার করার জন্য।
import { MastraClient } from "@mastra/client-js";
export const mastra_sdk = new MastraClient({
baseUrl: process.env.NEXT_PUBLIC_MASTRA_API!,
retries: 3,
});
আপনাকে NEXT_PUBLIC_MASTRA_API সেট করতে হবে আপনার Mastra সার্ভারের অ্যাড্রেসে। আপনি লোকালি ডেভেলপ করছেন তবে, এটি একটি localhost অ্যাড্রেস হবে। যেহেতু 3000 পোর্টে কনফ্লিক্ট হবে সম্ভবত, আপনি Mastra সার্ভারের কনফিগারেশন লোকালি রান করার সময় চেঞ্জ করতে পারেন, নিচের মত:
export const mastra = new Mastra({
storage: myMastraUpstashStore,
agents: { articleAgent },
server: {
port: 4111,
timeout: 10000,
}
});
এখন, আমরা লোকালি Mastra সার্ভার npm run dev দিয়ে রান করলে, সেটি পোর্ট 4111-এ সার্ভ হবে। আমরা NEXT_PUBLIC_MASTRA_API-কে https://localhost:4111 সেট করতে পারি যখন আমরা Next.js প্রজেক্ট লোকালি রান করব।
চলুন দেখি Mastra-এর ক্লায়েন্ট SDK কীভাবে ব্যবহার করতে হয়।
export const MASTRA_CONFIG = {
resourceId: process.env.NEXT_PUBLIC_RESOURCE_ID || "articleAgent",
agentId: "articleAgent",
baseUrl: process.env.NEXT_PUBLIC_MASTRA_API || "https://localhost:4111",
retries: 3,
};
// এটি অন্য ফাইলে এক্সপোর্ট করা হয়েছে যাতে কোডবেসের যেকোনো জায়গা থেকে ব্যবহার করা যায়।
// আপনার এজেন্ট পান এবং সিম্পলি আপনার রেসপন্স স্ট্রিম করুন আপনার এজেন্ট অবজেক্ট দিয়ে।
const agent = mastra_sdk.getAgent(MASTRA_CONFIG.agentId);
const response = await agent.stream({
messages: [message],
resourceId: MASTRA_CONFIG.resourceId,
threadId: threadId
});
আপনি আপনার টুল এবং এজেন্ট পেতে পারেন, এবং একবার পেলে, আপনি Почティ সবকিছু করতে পারেন যা আপনি একচুয়াল অবজেক্ট দিয়ে করতে পারতেন ক্লায়েন্ট SDK দিয়ে।
যেহেতু আমরা এই ডেমো প্রজেক্ট পাবলিকলি পাবলিশ করব, এজেন্টে হেভি লোড এড়াতে গুরুত্বপূর্ণ। এখানেই Upstash Ratelimit কাজে লাগে। প্রতিটি স্ট্রিম রিকোয়েস্টের আগে, আমরা চেক করব ইউজার রেট-লিমিটেড কিনা। আমাদের রেট লিমিটার কনফিগার করার জন্য, আমাদের Upstash Redis দরকার। আমরা আমাদের Mastra এজেন্টের জন্য একই রেডিস ডাটাবেস ব্যবহার করতে পারি।
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
// একই রেডিস ডিবি প্রজেক্ট জুড়ে ব্যবহার করুন
export const rateLimit = new Ratelimit({
redis: new Redis({
url: process.env.UPSTASH_REDIS_MEMORY_URL!,
token: process.env.UPSTASH_REDIS_MEMORY_TOKEN!
}),
limiter: Ratelimit.slidingWindow(10, '10s'),
prefix: 'upstash-ratelimit',
});
// প্রতি স্ট্রিমের আগে নিচের ফাংশন কল করুন।
export async function isRateLimited(id: string): Promise<boolean> {
const { success } = await rateLimit.limit(id);
return !success;
}
এভাবে, আমরা নিশ্চিত করি আমাদের এন্ডপয়েন্টগুলো হেভি লোডের অধীন থাকবে না।
Mastra দিয়ে চ্যাট এজেন্ট বানাতে সময়, Mastra-এর থ্রেড জেনারেশনের কিছু ফিচার জানা হেল্পফুল হতে পারে। মনে রাখবেন যখন আমরা এজেন্টের জন্য মেমরি কনফিগার করলাম, আমরা generateTitle-কে true সেট করেছিলাম threads অবজেক্টে। এটি Mastra-কে নতুন তৈরি থ্রেডের জন্য অটোমেটিক্যালি টাইটেল জেনারেট করতে বাধ্য করে। কিন্তু এখানে ক্যাচটি: একটি থ্রেড এক্সপ্লিসিটলি তৈরি করা সম্ভব, কিন্তু অটোমেটিক টাইটেল জেনারেশন সেটা ট্রিগার করে না। নরমালি, একটি নতুন থ্রেড তৈরি করার উপায় হলো:
const thread = await mastraClient.createMemoryThread({
title: "New Conversation",
metadata: { category: "support" },
resourceId: "resource-1",
agentId: "agent-1",
});
তবে, এটি এজেন্টের অটোমেটিক টাইটেল জেনারেট করার ক্ষমতা নেয় যাওয়া, যেহেতু আপনি সেটা ম্যানুয়ালি সেট করছেন। title ফিল্ড খালি রেখেও কাজ করে না। এই কেসে, আমরা দেখতে পারি Playground কী করে। মনে রাখবেন Playground, Mastra-এর দেওয়া ডেভেলপমেন্টের সময় আপনার সার্ভারের ক্যাপাবিলিটি এক্সপেরিয়েন্স করার জন্য? যদি আমরা ব্রাউজারের ডেভেলপার টুলসের নেটওয়ার্ক ট্যাব ইন্সপেক্ট করি, আমরা দেখব যখন একটি নতুন থ্রেড তৈরি হয়, এটি আসলে কোনো API রিকোয়েস্ট পাঠায় না সেটা তৈরি করার জন্য। বরং, এটি অপেক্ষা করে আপনার প্রথম মেসেজ সাবমিট করার। এরপর, এটি একটি স্ট্রিম রিকোয়েস্ট পাঠায় একটি নতুন জেনারেটেড থ্রেড আইডির সাথে। এটি Mastra-কে বলে যে এই আইডির সাথে কোনো থ্রেড এক্সিস্ট করে না, তাই এটা একটা তৈরি করুক এবং, যদি generateTitle true হয়, প্রথম মেসেজের ওপর ভিত্তি করে একটি টাইটেল জেনারেট করুক।
চলুন আমাদের প্রজেক্টের শেষ কম্পোনেন্টের দিকে যাই: arXiv আর্টিকেল।
arXiv আর্টিকেল
arXiv লাগভাগ ২.৪ মিলিয়ন রিসার্চ আর্টিকেলের একটি ওপেন-অ্যাক্সেস আর্কাইভ বিভিন্ন ফিল্ডে। articleQueryTool Upstash Vector ডাটাবেস কোয়েরি করে, যেটি arXiv API-এর মাধ্যমে ফেচ করা আর্টিকেল দিয়ে ফিড করা হয়। API ব্যবহার করা সহজ; আরও ডিটেলসের জন্য এখানে দেখুন।
আমাদের প্রজেক্টে, আমরা আর্টিকেল ফেচ এবং স্টোর করি ডেইলি। সার্ভার প্রথমবার রান হলে, এটি নির্দিষ্ট ক্যাটেগরি থেকে প্রায় ৩০,০০০ আর্টিকেল ফেচ করে। তারপর, এটি প্রতিদিন গত দিন প্রকাশিত নতুন আর্টিকেল ফেচ করে। আর্টিকেল ক্যাটেগরি এবং ইনিশিয়াল বড় ব্যাচ ফেচ করা হবে কিনা স্পেসিফাই করার জন্য, আমরা সংশ্লিষ্ট এনভায়রনমেন্ট ভেরিয়েবল সেট করি। আমরা arXiv-এর ট্যাক্সোনোমি ব্যবহার করে কাঙ্ক্ষিত আর্টিকেল ক্যাটেগরি কমা দিয়ে সেপারেট করে দিতে পারি। ক্যাটেগরিগুলো এখানে লুক আপ করতে পারেন।
CATEGORIES=cs.AI
RUN_BEGINNING_STACK=false
আপনি যদি একটি আরও কম্প্রিহেনসিভ ডাটাবেস চান, তবে আপনি arXiv-এর বাল্ক ডেটা অ্যাক্সেস ব্যবহার করতে পারেন। সেটা ছাড়া, আমরা প্রতি API কোয়েরিতে ৩০,০০০ আর্টিকেল পর্যন্ত সীমাবদ্ধ, যা আমাদের উদ্দেশ্যে পর্যাপ্ত।
arXiv-এ একটি সিম্পল কোয়েরি এরকম দেখে:
const categories = process.env.CATEGORIES?.split(',') || [];
// কাঙ্ক্ষিত ক্যাটেগরি পান এবং কোয়েরির জন্য সপ্লিট করুন।
const searchQuery = categories.length === 1 ? `cat:${categories[0]}` : `(${categories.map(c => `cat:${c}`).join(" OR ")})`;
const query = `search_query=${searchQuery}&sortBy=submittedDate&sortOrder=descending`;
const url = `https://export.arxiv.org/api/query?${query}`;
const response = await axios.get(url); // কনস্ট্রাক্টেড URL দিয়ে API কল করুন।
আমরা প্রতিদিন লেটেস্ট আর্টিকেল পেতে এবং ইনিশিয়াল স্ট্যাক ফেচ করতে সিমিলার কল করি।
আর্টিকেল ফেচ করার পর, আমরা সেগুলো নরমালাইজ করি এবং Upstash Vector-এ স্টোরেজের জন্য এম্বেড করি। এটাকে অবশ্যই সেম ভেক্টর ডাটাবেস হতে হবে যা আমাদের Mastra টুল ব্যবহার করে। "নরমালাইজ" বলতে আমরা মানে ফেচ করা আর্টিকেলগুলোকে একটি স্ট্যান্ডার্ড ArxivPaper টাইপে পার্স করা যেটি আমরা আমাদের কোডবেস জুড়ে ব্যবহার করব।
export interface ArxivPaper {
id: string;
title: string;
abstract: string;
authors: string[];
published: string;
pdfUrl: string;
category: string;
}// আমাদের আর্টিকেলের টাইপ, আমাদের কোডবেস জুড়ে।
async function storeAbstracts(papers: ArxivPaper[]) {
const embeddingModel = openai.embedding("text-embedding-3-small");
// সেম মডেল যা Mastra সাইডে কোয়েরির জন্য ব্যবহৃত হয়।
const embeddings = await embedArticles(papers, embeddingModel)
// এম্বেডিংগুলকে রিকোয়ায়ারড ফর্মে তাদের মেটাডেটার সাথে রাখুন।
const vectorsToUpsert = getVectorsToUpsert(embeddings, papers)
for (let j = 0; j < vectorsToUpsert.length; j++) {
await vectorStore.upsert(vectorsToUpsert[j], { namespace: "arxiv" });
// এম্বেডিংগুলকে তাদের মেটাডেটার সাথে Upstash Vector-এ আপসার্ট করুন।
}
}
আমাদের ডাটাবেস লেটেস্ট রিসার্চের সাথে কারেন্ট রাখতে, আমরা Upstash QStash ইমপ্লিমেন্ট করি শিডিউলড টাস্ক এক্সিকিউশনের জন্য। যেহেতু আমরা Vercel-এ ডিপ্লয়েড, আমাদের এক্সটেনডেড প্রসেসিং ইন্টারভালের কারণে ফাংশন টাইমআউট প্রিভেন্ট করতে হবে। আমরা আমাদের সার্ভারে একটি পাবলিক API এন্ডপয়েন্ট এক্সপোজ করি এই সমস্যাটি সমাধান করার জন্য, যা আমাদের QStash ইনস্ট্যান্সকে ডেইলি ডাটাবেস আপডেট ফাংশন ট্রিগার করতে সক্ষম করে।
// src/app/api/arxiv_reneval/route.ts
import { verifySignatureAppRouter } from "@upstash/qstash/nextjs"
import { fetchAndUpsertYesterday} from "@/services/arxiv"
async function handler(request: Request) {
console.log("Fetching and upserting yesterday's papers...")
await fetchAndUpsertYesterday()
console.log("Fetching and upserting yesterday's papers completed")
return Response.json({ success: true })
}
export const POST = verifySignatureAppRouter(handler)
একটি শিডিউলার Upstash Console-এ কনফিগার করা যাবে যেটি এই এন্ডপয়েন্টে প্রতিদিন UTC ৬:০০ AM-এ অটোমেটিক্যালি রিকোয়েস্ট ট্রিগার করবে।

এই শিডিউলার কনফিগারেশন inplace থাকলে, আমাদের সার্ভার প্রতিটি সকাল অটোমেটেড ডাটাবেস আপডেট পারফর্ম করবে, কন্টিনিউয়াস ডেটা ফ্রেশনেস নিশ্চিত করে।
আমাদের QStash ইনস্ট্যান্সের ক্রেডেনশিয়ালও প্রদান করা উচিত, সকল প্রয়োজনীয় env ভেরিয়েবল উদাহরণ env ফাইলে দেওয়া আছে।
এটাই প্রায় সব। আপনি চাইলে কোডের সাথে এক্সপেরিমেন্ট করতে পারেন। শুধু রিপোজিটরি ফর্ক করুন এবং ডেভেলপমেন্ট শুরু করুন। আপনি Mastra পার্টের রিপোতে যেতে পারেন এখানে এবং অন্য রিপোতে এখানে। ফর্ক করার পর:
- লোকাল মেশিনে ক্লোন করুন।
- আপনার এনভায়রনমেন্ট ভেরিয়েবল ফিল আপ করুন (উদাহরণ
.envফাইল প্রদান করা আছে)। - দুই প্রজেক্টের রুট ডিরেক্টরি আলাদা টার্মিনেলে যান।
- নিচের কমান্ডগুলো রান করুন:
npm install
npm run dev
এখন আপনি আপনার অ্যাপ্লিকেশন https://localhost:3000-এ দেখতে পারেন।
Mastra-এ, আপনি আরও কমপ্লেক্স জিনিস বানাতে পারেন এর অন্যান্য টেমপ্লেট ব্যবহার করে যেন RAG, ওয়ার্কফ্লো, এবং নেটওয়ার্ক। মনে হয় মেমরি এবং স্টোরেজ এই সব উদ্দেশ্যে একটি গুরুত্বপূর্ণ ভূমিকা পালন করে। এখানেই Upstash চমকে।