paint-brush
Next.js, OpenAI, LangChain, এবং Supabase দিয়ে কিভাবে একটি ওয়েব পেজ সামারাইজেশন অ্যাপ তৈরি করবেনদ্বারা@nassermaronie
6,013 পড়া
6,013 পড়া

Next.js, OpenAI, LangChain, এবং Supabase দিয়ে কিভাবে একটি ওয়েব পেজ সামারাইজেশন অ্যাপ তৈরি করবেন

দ্বারা Nasser Maronie13m2024/06/27
Read on Terminal Reader

অতিদীর্ঘ; পড়তে

এই নিবন্ধে, আমরা আপনাকে দেখাব কিভাবে একটি সহজ ওয়েব অ্যাপ তৈরি করতে হয় যা যেকোনো ওয়েব পৃষ্ঠার বিষয়বস্তুকে সংক্ষিপ্ত করতে পারে। একটি মসৃণ এবং দ্রুত ওয়েব অভিজ্ঞতার জন্য [Next.js] ব্যবহার করে, ভাষা প্রক্রিয়াকরণের জন্য [LangChain], সারাংশ তৈরির জন্য [OpenAI](https://openai.com/) এবং ভেক্টর ডেটা পরিচালনা ও সংরক্ষণের জন্য [Supabase] ব্যবহার করে, আমরা একসাথে একটি শক্তিশালী হাতিয়ার তৈরি করবে।
featured image - Next.js, OpenAI, LangChain, এবং Supabase দিয়ে কিভাবে একটি ওয়েব পেজ সামারাইজেশন অ্যাপ তৈরি করবেন
Nasser Maronie HackerNoon profile picture

একটি অ্যাপ যা যেকোনো ওয়েব পেজের প্রসঙ্গ বুঝতে পারে।

এই নিবন্ধে, আমরা আপনাকে দেখাব কিভাবে একটি সহজ ওয়েব অ্যাপ তৈরি করতে হয় যা যেকোনো ওয়েব পৃষ্ঠার বিষয়বস্তুকে সংক্ষিপ্ত করতে পারে। একটি মসৃণ এবং দ্রুত ওয়েব অভিজ্ঞতার জন্য Next.js ব্যবহার করে, ভাষা প্রক্রিয়াকরণের জন্য LangChain , সারাংশ তৈরির জন্য OpenAI এবং ভেক্টর ডেটা পরিচালনা ও সংরক্ষণের জন্য Supabase ব্যবহার করে, আমরা একসঙ্গে একটি শক্তিশালী টুল তৈরি করব।



কেন আমরা এটা নির্মাণ করছি

অনলাইনে অনেক কন্টেন্ট সহ আমরা সকলেই তথ্য ওভারলোডের সম্মুখীন হই। একটি অ্যাপ তৈরি করে যা দ্রুত সারাংশ দেয়, আমরা লোকেদের সময় বাঁচাতে এবং অবগত থাকতে সাহায্য করি। আপনি একজন ব্যস্ত কর্মী, একজন ছাত্র বা শুধুমাত্র এমন কেউ যিনি খবর এবং নিবন্ধের সাথে তাল মিলিয়ে চলতে চান না কেন, এই অ্যাপটি আপনার জন্য একটি সহায়ক হাতিয়ার হবে।

এটা কিভাবে হতে যাচ্ছে

আমাদের অ্যাপ ব্যবহারকারীদের যেকোনো ওয়েবসাইটের URL লিখতে এবং দ্রুত পৃষ্ঠার সংক্ষিপ্ত সারসংক্ষেপ পেতে দেবে। এর মানে আপনি দীর্ঘ নিবন্ধ, ব্লগ পোস্ট বা গবেষণাপত্রের মূল বিষয়গুলো সম্পূর্ণ না পড়েই বুঝতে পারবেন।

সম্ভাব্য এবং প্রভাব

এই সংক্ষিপ্তকরণ অ্যাপটি বিভিন্ন উপায়ে কার্যকর হতে পারে। এটি গবেষকদের একাডেমিক কাগজপত্রের মাধ্যমে স্কিম করতে, সংবাদ প্রেমীদের আপডেট রাখতে এবং আরও অনেক কিছু করতে সহায়তা করতে পারে। এছাড়াও, বিকাশকারীরা আরও বেশি দরকারী বৈশিষ্ট্য তৈরি করতে এই অ্যাপটি তৈরি করতে পারে।


টেক স্ট্যাক

পরবর্তী.js

Next.js একটি শক্তিশালী এবং নমনীয় প্রতিক্রিয়া ফ্রেমওয়ার্ক যা Vercel দ্বারা তৈরি করা হয়েছে যা ডেভেলপারদের সহজে সার্ভার-সাইড রেন্ডারিং (SSR) এবং স্ট্যাটিক ওয়েব অ্যাপ্লিকেশন তৈরি করতে সক্ষম করে। এটি অপ্টিমাইজ করা এবং মাপযোগ্য ওয়েব অ্যাপ্লিকেশন তৈরি করতে অতিরিক্ত ক্ষমতার সাথে প্রতিক্রিয়ার সেরা বৈশিষ্ট্যগুলিকে একত্রিত করে।

OpenAI

Node.js-এ OpenAI মডিউল OpenAI-এর API-এর সাথে ইন্টারঅ্যাক্ট করার একটি উপায় প্রদান করে, যা ডেভেলপারদের GPT-3 এবং GPT-4-এর মতো শক্তিশালী ভাষা মডেলের সুবিধা নিতে দেয়। এই মডিউলটি আপনাকে আপনার Node.js অ্যাপ্লিকেশনগুলিতে উন্নত AI কার্যকারিতাগুলিকে একীভূত করতে সক্ষম করে৷

LangChain.js

ল্যাংচেইন হল একটি শক্তিশালী ফ্রেমওয়ার্ক যা ভাষা মডেলের সাথে অ্যাপ্লিকেশন বিকাশের জন্য ডিজাইন করা হয়েছে। মূলত পাইথনের জন্য তৈরি করা হয়েছে, এটি তখন থেকে Node.js সহ অন্যান্য ভাষার জন্য অভিযোজিত হয়েছে। এখানে Node.js এর প্রসঙ্গে LangChain এর একটি ওভারভিউ রয়েছে:

ল্যাংচেইন কি?

LangChain হল একটি লাইব্রেরি যা বড় ভাষা মডেল (LLMs) ব্যবহার করে অ্যাপ্লিকেশন তৈরিকে সহজ করে। এটি আপনার অ্যাপ্লিকেশানগুলিতে এলএলএমগুলি পরিচালনা এবং সংহত করার জন্য সরঞ্জামগুলি সরবরাহ করে, এই মডেলগুলিতে কলগুলির চেইনিং পরিচালনা করে এবং সহজে জটিল কর্মপ্রবাহ সক্ষম করে৷

বড় ভাষা মডেল (LLM) কিভাবে কাজ করে?

ওপেনএআই-এর GPT-3.5- এর মতো বৃহৎ ভাষার মডেলগুলিকে মানুষের মতো পাঠ্য বোঝা এবং তৈরি করার জন্য প্রচুর পরিমাণে পাঠ্য ডেটার উপর প্রশিক্ষণ দেওয়া হয়। তারা প্রতিক্রিয়া তৈরি করতে পারে, ভাষা অনুবাদ করতে পারে এবং অন্যান্য অনেক প্রাকৃতিক ভাষা প্রক্রিয়াকরণ কাজ সম্পাদন করতে পারে।

সুপাবেস

সুপাবেস হল একটি ওপেন-সোর্স ব্যাকএন্ড-এ-সার্ভিস (BaaS) প্ল্যাটফর্ম যা ডেভেলপারদের দ্রুত স্কেলযোগ্য অ্যাপ্লিকেশন তৈরি এবং স্থাপনে সহায়তা করার জন্য ডিজাইন করা হয়েছে। এটি এমন একটি সরঞ্জাম এবং পরিষেবা সরবরাহ করে যা ডেটাবেস পরিচালনা, প্রমাণীকরণ, সঞ্চয়স্থান এবং রিয়েল-টাইম ক্ষমতাগুলিকে সহজ করে, যা পোস্টগ্রেএসকিউএল- এর উপরে নির্মিত


পূর্বশর্ত

আমরা শুরু করার আগে, নিশ্চিত করুন যে আপনার নিম্নলিখিত আছে:

  • Node.js এবং npm ইনস্টল করা হয়েছে
  • একটি সুপাবেস অ্যাকাউন্ট
  • একটি OpenAI অ্যাকাউন্ট

ধাপ 1: সুপাবেস সেট আপ করা

প্রথমত, আমাদের একটি সুপাবেস প্রকল্প সেট আপ করতে হবে এবং আমাদের ডেটা সংরক্ষণ করার জন্য প্রয়োজনীয় টেবিল তৈরি করতে হবে।

একটি সুপাবেস প্রকল্প তৈরি করুন

  1. সুপাবেসে যান, এবং একটি অ্যাকাউন্টের জন্য সাইন আপ করুন।


  2. একটি নতুন প্রকল্প তৈরি করুন এবং আপনার Supabase URL এবং API কী নোট করুন৷ আপনার এগুলো পরে লাগবে।

সুপাবেসের জন্য এসকিউএল স্ক্রিপ্ট

আপনার সুপাবেস ড্যাশবোর্ডে একটি নতুন এসকিউএল কোয়েরি তৈরি করুন এবং প্রয়োজনীয় টেবিল এবং ফাংশন তৈরি করতে নিম্নলিখিত স্ক্রিপ্টগুলি চালান:

প্রথমত, একটি এক্সটেনশন তৈরি করুন যদি এটি আমাদের ভেক্টর স্টোরের জন্য ইতিমধ্যে বিদ্যমান না থাকে:

 create extension if not exists vector;


এরপরে, "ডকুমেন্টস" নামে একটি টেবিল তৈরি করুন। এই টেবিলটি ভেক্টর ফর্ম্যাটে ওয়েব পৃষ্ঠার বিষয়বস্তু সংরক্ষণ এবং এম্বেড করতে ব্যবহার করা হবে:

 create table if not exists documents ( id bigint primary key generated always as identity, content text, metadata jsonb, embedding vector(1536) );


এখন, আমাদের এমবেডেড ডেটা জিজ্ঞাসা করার জন্য আমাদের একটি ফাংশন দরকার:

 create or replace function match_documents ( query_embedding vector(1536), match_count int default null, filter jsonb default '{}' ) returns table ( id bigint, content text, metadata jsonb, similarity float ) language plpgsql as $$ begin return query select id, content, metadata, 1 - (documents.embedding <=> query_embedding) as similarity from documents where metadata @> filter order by documents.embedding <=> query_embedding limit match_count; end; $$;


এর পরে, ওয়েব পৃষ্ঠার বিশদ সংরক্ষণের জন্য আমাদের টেবিল সেট আপ করতে হবে:

 create table if not exists files ( id bigint primary key generated always as identity, url text not null, created_at timestamp with time zone default timezone('utc'::text, now()) not null );

ধাপ 2: OpenAI সেট আপ করা

OpenAI প্রকল্প তৈরি করুন


  • API এ নেভিগেট করুন: লগ ইন করার পরে, API বিভাগে নেভিগেট করুন এবং একটি নতুন API কী তৈরি করুন। এটি সাধারণত ড্যাশবোর্ড থেকে অ্যাক্সেসযোগ্য।

ধাপ 3: Next.js সেট আপ করা

Next.js অ্যাপ তৈরি করুন

 $ npx create-next-app summarize-page $ cd ./summarize-page


প্রয়োজনীয় নির্ভরতা ইনস্টল করুন:

 npm install @langchain/community @langchain/core @langchain/openai @supabase/supabase-js langchain openai axios


তারপর, আমরা আমাদের ইন্টারফেস তৈরির জন্য উপাদান UI ইনস্টল করব; অন্য লাইব্রেরি ব্যবহার করতে নির্দ্বিধায়:

 npm install @mui/material @emotion/react @emotion/styled

ধাপ 4: OpenAI এবং Supabase ক্লায়েন্ট

এর পরে, আমাদের ওপেনএআই এবং সুপাবেস ক্লায়েন্ট সেট আপ করতে হবে। আপনার প্রকল্পে একটি libs ডিরেক্টরি তৈরি করুন, এবং নিম্নলিখিত ফাইল যোগ করুন।

src/libs/openAI.ts

এই ফাইলটি OpenAI ক্লায়েন্ট কনফিগার করবে।

 import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai"; const openAIApiKey = process.env.OPENAI_API_KEY; if (!openAIApiKey) throw new Error('OpenAI API Key not found.') export const llm = new ChatOpenAI({ openAIApiKey, modelName: "gpt-3.5-turbo", temperature: 0.9, }); export const embeddings = new OpenAIEmbeddings( { openAIApiKey, }, { maxRetries: 0 } );
  • llm : ভাষা মডেল উদাহরণ, যা আমাদের সারাংশ তৈরি করবে।


  • embeddings : এটি আমাদের নথিগুলির জন্য এমবেডিং তৈরি করবে, যা অনুরূপ বিষয়বস্তু খুঁজে পেতে সাহায্য করবে।

src/libs/supabaseClient.ts

এই ফাইলটি সুপাবেস ক্লায়েন্ট কনফিগার করবে।

 import { createClient } from "@supabase/supabase-js"; const supabaseUrl = process.env.SUPABASE_URL || ""; const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || ""; if (!supabaseUrl) throw new Error("Supabase URL not found."); if (!supabaseAnonKey) throw new Error("Supabase Anon key not found."); export const supabaseClient = createClient(supabaseUrl, supabaseAnonKey);
  • supabaseClient : সুপাবেস ক্লায়েন্ট আমাদের সুপাবেস ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করার জন্য।

ধাপ 5: বিষয়বস্তু এবং ফাইলের জন্য পরিষেবা তৈরি করা

একটি services ডিরেক্টরি তৈরি করুন, এবং সামগ্রী আনয়ন এবং ফাইলগুলি পরিচালনা করার জন্য নিম্নলিখিত ফাইলগুলি যুক্ত করুন৷

src/services/content.ts

এই পরিষেবাটি ওয়েব পৃষ্ঠার বিষয়বস্তু আনবে এবং HTML ট্যাগ, স্ক্রিপ্ট এবং শৈলীগুলি সরিয়ে এটি পরিষ্কার করবে৷

 import axios from "axios"; export async function getContent(url: string): Promise<string> { let htmlContent: string = ""; const response = await axios.get(url as string); htmlContent = response.data; if (!htmlContent) return ""; // Remove unwanted elements and tags return htmlContent .replace(/style="[^"]*"/gi, "") .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "") .replace(/\s*on\w+="[^"]*"/gi, "") .replace( /<script(?![^>]*application\/ld\+json)[^>]*>[\s\S]*?<\/script>/gi, "" ) .replace(/<[^>]*>/g, "") .replace(/\s+/g, " "); }

এই ফাংশনটি একটি প্রদত্ত URL এর HTML বিষয়বস্তু নিয়ে আসে এবং শৈলী, স্ক্রিপ্ট এবং HTML ট্যাগগুলি সরিয়ে এটি পরিষ্কার করে।

src/services/file.ts

এই পরিষেবাটি ওয়েব পৃষ্ঠার বিষয়বস্তু সুপাবেসে সংরক্ষণ করবে এবং সারাংশ পুনরুদ্ধার করবে।

 import { embeddings, llm } from "@/libs/openAI"; import { supabaseClient } from "@/libs/supabaseClient"; import { SupabaseVectorStore } from "@langchain/community/vectorstores/supabase"; import { StringOutputParser } from "@langchain/core/output_parsers"; import { ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate, } from "@langchain/core/prompts"; import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables"; import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; import { formatDocumentsAsString } from "langchain/util/document"; export interface IFile { id?: number | undefined; url: string; created_at?: Date | undefined; } export async function saveFile(url: string, content: string): Promise<IFile> { const doc = await supabaseClient .from("files") .select() .eq("url", url) .single<IFile>(); if (!doc.error && doc.data?.id) return doc.data; const { data, error } = await supabaseClient .from("files") .insert({ url }) .select() .single<IFile>(); if (error) throw error; const splitter = new RecursiveCharacterTextSplitter({ separators: ["\n\n", "\n", " ", ""], }); const output = await splitter.createDocuments([content]); const docs = output.map((d) => ({ ...d, metadata: { ...d.metadata, file_id: data.id }, })); await SupabaseVectorStore.fromDocuments(docs, embeddings, { client: supabaseClient, tableName: "documents", queryName: "match_documents", }); return data; } export async function getSummarization(fileId: number): Promise<string> { const vectorStore = await SupabaseVectorStore.fromExistingIndex(embeddings, { client: supabaseClient, tableName: "documents", queryName: "match_documents", }); const retriever = vectorStore.asRetriever({ filter: (rpc) => rpc.filter("metadata->>file_id", "eq", fileId), k: 2, }); const SYSTEM_TEMPLATE = `Use the following pieces of context, explain what is it about and summarize it. If you can't explain it, just say that you don't know, don't try to make up some explanation. ---------------- {context}`; const messages = [ SystemMessagePromptTemplate.fromTemplate(SYSTEM_TEMPLATE), HumanMessagePromptTemplate.fromTemplate("{format_answer}"), ]; const prompt = ChatPromptTemplate.fromMessages(messages); const chain = RunnableSequence.from([ { context: retriever.pipe(formatDocumentsAsString), format_answer: new RunnablePassthrough(), }, prompt, llm, new StringOutputParser(), ]); const format_summarization = ` Give it title, subject, description, and the conclusion of the context in this format, replace the brackets with the actual content: [Write the title here] By: [Name of the author or owner or user or publisher or writer or reporter if possible, otherwise leave it "Not Specified"] [Write the subject, it could be a long text, at least minimum of 300 characters] ---------------- [Write the description in here, it could be a long text, at least minimum of 1000 characters] Conclusion: [Write the conclusion in here, it could be a long text, at least minimum of 500 characters] `; const summarization = await chain.invoke(format_summarization); return summarization; }
  • saveFile : ফাইল এবং এর বিষয়বস্তু সুপাবেসে সংরক্ষণ করে, বিষয়বস্তুকে পরিচালনাযোগ্য খণ্ডে বিভক্ত করে এবং ভেক্টর স্টোরে সংরক্ষণ করে।


  • getSummarization : ভেক্টর স্টোর থেকে প্রাসঙ্গিক নথি উদ্ধার করে এবং OpenAI ব্যবহার করে একটি সারাংশ তৈরি করে।

ধাপ 6: একটি API হ্যান্ডলার তৈরি করা

এখন, বিষয়বস্তু প্রক্রিয়া করতে এবং একটি সারাংশ তৈরি করতে একটি API হ্যান্ডলার তৈরি করা যাক।

pages/api/content.ts

 import { getContent } from "@/services/content"; import { getSummarization, saveFile } from "@/services/file"; import { NextApiRequest, NextApiResponse } from "next"; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== "POST") return res.status(404).json({ message: "Not found" }); const { body } = req; try { const content = await getContent(body.url); const file = await saveFile(body.url, content); const result = await getSummarization(file.id as number); res.status(200).json({ result }); } catch (err) { res.status( 500).json({ error: err }); } }

এই API হ্যান্ডলার একটি URL গ্রহণ করে, বিষয়বস্তু নিয়ে আসে, এটি সুপাবেসে সংরক্ষণ করে এবং একটি সারাংশ তৈরি করে। এটি আমাদের পরিষেবাগুলি থেকে saveFile এবং getSummarization ফাংশন উভয়ই পরিচালনা করে।


ধাপ 7: ফ্রন্টেন্ড তৈরি করা

অবশেষে, ইউজারদের ইউআরএল ইনপুট করতে এবং সারসংক্ষেপ প্রদর্শন করার জন্য src/pages/index.tsx এ ফ্রন্টএন্ড তৈরি করা যাক।

src/pages/index.tsx

 import axios from "axios"; import { useState } from "react"; import { Alert, Box, Button, Container, LinearProgress, Stack, TextField, Typography, } from "@mui/material"; export default function Home() { const [loading, setLoading] = useState(false); const [url, setUrl] = useState(""); const [result, setResult] = useState(""); const [error, setError] = useState<any>(null); const onSubmit = async () => { try { setError(null); setLoading(true); const res = await axios.post("/api/content", { url }); setResult(res.data.result); } catch (err) { console.error("Failed to fetch content", err); setError(err as any); } finally { setLoading(false); } }; return ( <Box sx={{ height: "100vh", overflowY: "auto" }}> <Container sx={{ backgroundColor: (theme) => theme.palette.background.default, position: "sticky", top: 0, zIndex: 2, py: 2, }} > <Typography sx={{ mb: 2, fontSize: "24px" }}> Summarize the content of any page </Typography> <TextField fullWidth label="Input page's URL" value={url} onChange={(e) => { if (result) setResult(""); setUrl(e.target.value); }} sx={{ mb: 2 }} /> <Button disabled={loading} variant="contained" onClick={onSubmit} > Summarize </Button> </Container> <Container maxWidth="lg" sx={{ py: 2 }}> {loading ? ( <LinearProgress /> ) : ( <Stack sx={{ gap: 2 }}> {result && ( <Alert> <Typography sx={{ whiteSpace: "pre-line", wordBreak: "break-word", }} > {result} </Typography> </Alert> )} {error && <Alert severity="error">{error.message || error}</Alert>} </Stack> )} </Container> </Box> ); }

এই প্রতিক্রিয়া উপাদানটি ব্যবহারকারীদের একটি URL ইনপুট করতে, এটি জমা দিতে এবং জেনারেট করা সারাংশ প্রদর্শন করতে দেয়। এটি একটি ভাল ব্যবহারকারীর অভিজ্ঞতা প্রদানের জন্য লোডিং অবস্থা এবং ত্রুটি বার্তা পরিচালনা করে।


ধাপ 8: অ্যাপ্লিকেশন চালানো

আপনার পরিবেশের ভেরিয়েবলগুলি সংরক্ষণ করতে আপনার প্রকল্পের রুটে একটি .env ফাইল তৈরি করুন:

 SUPABASE_URL=your-supabase-url SUPABASE_ANON_KEY=your-supabase-anon-key OPENAI_API_KEY=your-openai-api-key


অবশেষে, আপনার Next.js অ্যাপ্লিকেশন শুরু করুন:

 npm run dev


এখন, আপনার একটি চলমান অ্যাপ্লিকেশন থাকা উচিত যেখানে আপনি ওয়েব পৃষ্ঠার URL ইনপুট করতে পারেন এবং পৃষ্ঠার সংক্ষিপ্ত প্রতিক্রিয়াগুলি পেতে পারেন৷


উপসংহার

অভিনন্দন! আপনি Next.js, OpenAI, LangChain, এবং Supabase ব্যবহার করে একটি সম্পূর্ণ কার্যকরী ওয়েব পৃষ্ঠা সংক্ষিপ্তকরণ অ্যাপ্লিকেশন তৈরি করেছেন। ব্যবহারকারীরা একটি ইউআরএল ইনপুট করতে পারে, বিষয়বস্তু আনতে পারে, এটি সুপাবেসে সংরক্ষণ করতে পারে এবং OpenAI এর ক্ষমতা ব্যবহার করে একটি সারাংশ তৈরি করতে পারে। এই সেটআপ আপনার প্রয়োজনের উপর ভিত্তি করে আরও উন্নতি এবং কাস্টমাইজেশনের জন্য একটি শক্তিশালী ভিত্তি প্রদান করে।


আরও বৈশিষ্ট্য যোগ করে, UI উন্নত করে, বা অতিরিক্ত API একত্রিত করে এই প্রকল্পে বিনা দ্বিধায় প্রসারিত হন৷

এই রেপোতে সোর্স কোড চেক করুন:

https://github.com/firstpersoncode/summarize-page


শুভ কোডিং!