লার্জ ল্যাঙ্গুয়েজ মডেলের উত্থান এবং তাদের চিত্তাকর্ষক ক্ষমতার সাথে, অনেক অভিনব অ্যাপ্লিকেশন ওপেনএআই এবং অ্যানথ্রপিকের মতো বিশাল LLM প্রদানকারীদের উপরে তৈরি করা হচ্ছে। এই ধরনের অ্যাপ্লিকেশনের পিছনে পৌরাণিক কাহিনী হল RAG ফ্রেমওয়ার্ক, যা নিম্নলিখিত নিবন্ধগুলিতে পুঙ্খানুপুঙ্খভাবে ব্যাখ্যা করা হয়েছে:
RAG এর সাথে পরিচিত হওয়ার জন্য, আমি এই নিবন্ধগুলি দিয়ে যাওয়ার পরামর্শ দিই। যাইহোক, এই পোস্টটি মৌলিক বিষয়গুলি এড়িয়ে যাবে এবং ডেটা গোপনীয়তা এবং টোকেন খরচ সম্পর্কে কোনও উদ্বেগ ছাড়াই আপনার ল্যাপটপে স্থানীয়ভাবে চালানো যেতে পারে এমন আপনার নিজস্ব RAG অ্যাপ্লিকেশন তৈরিতে সরাসরি আপনাকে গাইড করবে।
আমরা এমন একটি অ্যাপ্লিকেশন তৈরি করব যা ChatPD F এর মতই কিন্তু সহজ। যেখানে ব্যবহারকারীরা একটি পিডিএফ ডকুমেন্ট আপলোড করতে পারে এবং একটি সহজবোধ্য UI এর মাধ্যমে প্রশ্ন জিজ্ঞাসা করতে পারে৷ Langchain, Ollama, এবং Streamlit এর সাথে আমাদের টেক স্ট্যাক খুবই সহজ।
ঠিক আছে, এর সেট আপ করা শুরু করা যাক।
উপরে উল্লিখিত হিসাবে, ওল্লামা সেট আপ এবং চালানো সোজা। প্রথম, পরিদর্শন করুন
এর পরে, আপনার টার্মিনাল খুলুন, এবং সর্বশেষ টানতে নিম্নলিখিত কমান্ডটি চালান
ollama pull mistral
এর পরে, মডেলটি সঠিকভাবে টানা হয়েছে কিনা তা যাচাই করতে ollama list
চালান। টার্মিনাল আউটপুট নিম্নলিখিত অনুরূপ হওয়া উচিত:
এখন, যদি LLM সার্ভার ইতিমধ্যেই চালু না হয়, তাহলে ollama serve
দিয়ে শুরু করুন। আপনি যদি "Error: listen tcp 127.0.0.1:11434: bind: address already in use"
মতো একটি ত্রুটির বার্তার সম্মুখীন হন, তাহলে এটি নির্দেশ করে যে সার্ভারটি ইতিমধ্যেই ডিফল্টরূপে চলছে এবং আপনি পরবর্তী ধাপে যেতে পারেন৷
আমাদের প্রক্রিয়ার দ্বিতীয় ধাপ হল RAG পাইপলাইন তৈরি করা। আমাদের আবেদনের সরলতার পরিপ্রেক্ষিতে, আমাদের প্রাথমিকভাবে দুটি পদ্ধতির প্রয়োজন: ingest
এবং ask
।
ingest
পদ্ধতিটি একটি ফাইল পাথ গ্রহণ করে এবং এটি দুটি ধাপে ভেক্টর স্টোরেজে লোড করে: প্রথমত, এটি LLM-এর টোকেন সীমা মিটমাট করার জন্য নথিটিকে ছোট খণ্ডে বিভক্ত করে; দ্বিতীয়ত, এটি Qdrant FastEmbeddings ব্যবহার করে এই অংশগুলিকে ভেক্টরাইজ করে এবং ক্রোমাতে সংরক্ষণ করে।
ask
পদ্ধতি ব্যবহারকারীর প্রশ্নগুলি পরিচালনা করে। ব্যবহারকারীরা একটি প্রশ্ন উত্থাপন করতে পারে, এবং তারপর RetrievalQAChain ভেক্টর সাদৃশ্য অনুসন্ধান কৌশল ব্যবহার করে প্রাসঙ্গিক প্রসঙ্গ (ডকুমেন্ট খণ্ড) পুনরুদ্ধার করে।
ব্যবহারকারীর প্রশ্ন এবং পুনরুদ্ধার করা প্রসঙ্গে, আমরা একটি প্রম্পট রচনা করতে পারি এবং LLM সার্ভার থেকে একটি পূর্বাভাসের অনুরোধ করতে পারি।
from langchain.vectorstores import Chroma from langchain.chat_models import ChatOllama from langchain.embeddings import FastEmbedEmbeddings from langchain.schema.output_parser import StrOutputParser from langchain.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.schema.runnable import RunnablePassthrough from langchain.prompts import PromptTemplate from langchain.vectorstores.utils import filter_complex_metadata class ChatPDF: vector_store = None retriever = None chain = None def __init__(self): self.model = ChatOllama(model="mistral") self.text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024, chunk_overlap=100) self.prompt = PromptTemplate.from_template( """ <s> [INST] You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise. [/INST] </s> [INST] Question: {question} Context: {context} Answer: [/INST] """ ) def ingest(self, pdf_file_path: str): docs = PyPDFLoader(file_path=pdf_file_path).load() chunks = self.text_splitter.split_documents(docs) chunks = filter_complex_metadata(chunks) vector_store = Chroma.from_documents(documents=chunks, embedding=FastEmbedEmbeddings()) self.retriever = vector_store.as_retriever( search_type="similarity_score_threshold", search_kwargs={ "k": 3, "score_threshold": 0.5, }, ) self.chain = ({"context": self.retriever, "question": RunnablePassthrough()} | self.prompt | self.model | StrOutputParser()) def ask(self, query: str): if not self.chain: return "Please, add a PDF document first." return self.chain.invoke(query) def clear(self): self.vector_store = None self.retriever = None self.chain = None
প্রম্পটটি ল্যাংচেইন হাব থেকে নেওয়া হয়েছে:
আপনি এলএলএম প্রম্পটিং কৌশল সম্পর্কে আরও জানতে পারেন
বাস্তবায়ন সম্পর্কে আরও বিশদ:
ingest
: ব্যবহারকারীর দ্বারা আপলোড করা PDF ফাইল লোড করতে আমরা PyPDFLloader ব্যবহার করি। Langchain দ্বারা প্রদত্ত Recursive CharacterSplitter, তারপর এই PDF কে ছোট ছোট খন্ডে বিভক্ত করে। Langchain থেকে filter_complex_metadata
ফাংশন ব্যবহার করে ChromaDB দ্বারা সমর্থিত নয় এমন জটিল মেটাডেটা ফিল্টার করা গুরুত্বপূর্ণ।
ভেক্টর স্টোরেজের জন্য, ক্রোমা ব্যবহার করা হয়, এর সাথে মিলিত
ask
: এই পদ্ধতিটি ব্যবহারকারীর প্রশ্নকে আমাদের পূর্বনির্ধারিত চেইনে পাস করে এবং তারপর ফলাফল প্রদান করে।
clear
: এই পদ্ধতিটি একটি নতুন PDF ফাইল আপলোড করার সময় পূর্ববর্তী চ্যাট সেশন এবং স্টোরেজ সাফ করতে ব্যবহৃত হয়। একটি সাধারণ ইউজার ইন্টারফেসের জন্য, আমরা ব্যবহার করব
import os import tempfile import streamlit as st from streamlit_chat import message from rag import ChatPDF st.set_page_config(page_title="ChatPDF") def display_messages(): st.subheader("Chat") for i, (msg, is_user) in enumerate(st.session_state["messages"]): message(msg, is_user=is_user, key=str(i)) st.session_state["thinking_spinner"] = st.empty() def process_input(): if st.session_state["user_input"] and len(st.session_state["user_input"].strip()) > 0: user_text = st.session_state["user_input"].strip() with st.session_state["thinking_spinner"], st.spinner(f"Thinking"): agent_text = st.session_state["assistant"].ask(user_text) st.session_state["messages"].append((user_text, True)) st.session_state["messages"].append((agent_text, False)) def read_and_save_file(): st.session_state["assistant"].clear() st.session_state["messages"] = [] st.session_state["user_input"] = "" for file in st.session_state["file_uploader"]: with tempfile.NamedTemporaryFile(delete=False) as tf: tf.write(file.getbuffer()) file_path = tf.name with st.session_state["ingestion_spinner"], st.spinner(f"Ingesting {file.name}"): st.session_state["assistant"].ingest(file_path) os.remove(file_path) def page(): if len(st.session_state) == 0: st.session_state["messages"] = [] st.session_state["assistant"] = ChatPDF() st.header("ChatPDF") st.subheader("Upload a document") st.file_uploader( "Upload document", type=["pdf"], key="file_uploader", on_change=read_and_save_file, label_visibility="collapsed", accept_multiple_files=True, ) st.session_state["ingestion_spinner"] = st.empty() display_messages() st.text_input("Message", key="user_input", on_change=process_input) if __name__ == "__main__": page()
এটি কেমন দেখাচ্ছে তা দেখতে streamlit run app.py
কমান্ড দিয়ে এই কোডটি চালান।
ঠিক আছে, এটা! আমাদের এখন একটি ChatPDF অ্যাপ্লিকেশন রয়েছে যা সম্পূর্ণরূপে আপনার ল্যাপটপে চলে। যেহেতু এই পোস্টটি মূলত কীভাবে আপনার নিজস্ব RAG অ্যাপ্লিকেশন তৈরি করতে হয় তার একটি উচ্চ-স্তরের ওভারভিউ প্রদানের উপর ফোকাস করে, তাই এমন বেশ কয়েকটি দিক রয়েছে যার জন্য সূক্ষ্ম-টিউনিং প্রয়োজন। আপনার অ্যাপটি উন্নত করতে এবং আপনার দক্ষতা আরও বিকাশ করতে আপনি নিম্নলিখিত পরামর্শগুলি বিবেচনা করতে পারেন:
পরিশেষে, পড়ার জন্য আপনাকে ধন্যবাদ. যদি আপনি এই তথ্য দরকারী খুঁজে, আমার সদস্যতা বিবেচনা করুন
সম্পূর্ণ উৎস কোড: