লার্জ ল্যাঙ্গুয়েজ মডেলের উত্থান এবং তাদের চিত্তাকর্ষক ক্ষমতার সাথে, অনেক অভিনব অ্যাপ্লিকেশন ওপেনএআই এবং অ্যানথ্রপিকের মতো বিশাল LLM প্রদানকারীদের উপরে তৈরি করা হচ্ছে। এই ধরনের অ্যাপ্লিকেশনের পিছনে পৌরাণিক কাহিনী হল RAG ফ্রেমওয়ার্ক, যা নিম্নলিখিত নিবন্ধগুলিতে পুঙ্খানুপুঙ্খভাবে ব্যাখ্যা করা হয়েছে: উৎপাদনের জন্য RAG-ভিত্তিক LLM অ্যাপ্লিকেশন তৈরি করা পুনরুদ্ধার অগমেন্টেড জেনারেশন (RAG) ব্যাখ্যা করা হয়েছে: মূল ধারণাগুলি বোঝা পুনরুদ্ধার-বর্ধিত প্রজন্ম কি? RAG এর সাথে পরিচিত হওয়ার জন্য, আমি এই নিবন্ধগুলি দিয়ে যাওয়ার পরামর্শ দিই। যাইহোক, এই পোস্টটি মৌলিক বিষয়গুলি এড়িয়ে যাবে এবং ডেটা গোপনীয়তা এবং টোকেন খরচ সম্পর্কে কোনও উদ্বেগ ছাড়াই আপনার ল্যাপটপে স্থানীয়ভাবে চালানো যেতে পারে এমন আপনার নিজস্ব RAG অ্যাপ্লিকেশন তৈরিতে সরাসরি আপনাকে গাইড করবে। আমরা এমন একটি অ্যাপ্লিকেশন তৈরি করব যা F এর মতই কিন্তু সহজ। যেখানে ব্যবহারকারীরা একটি পিডিএফ ডকুমেন্ট আপলোড করতে পারে এবং একটি সহজবোধ্য UI এর মাধ্যমে প্রশ্ন জিজ্ঞাসা করতে পারে৷ Langchain, Ollama, এবং Streamlit এর সাথে আমাদের টেক স্ট্যাক খুবই সহজ। ChatPD : এই অ্যাপের সবচেয়ে গুরুত্বপূর্ণ উপাদান হল এলএলএম সার্ভার। ধন্যবাদ , আমাদের কাছে একটি শক্তিশালী LLM সার্ভার রয়েছে যা স্থানীয়ভাবে এমনকি একটি ল্যাপটপেও সেট আপ করা যায়৷ যখন একটি বিকল্প, আমি Go-তে লেখা ওল্লামা খুঁজে পাই, সেট আপ করা এবং চালানো সহজ। এলএলএম সার্ভার ওল্লামা llama.cpp : নিঃসন্দেহে, এলএলএম ডোমেনে দুটি নেতৃস্থানীয় লাইব্রেরি এবং . এই প্রকল্পের জন্য, আমি ল্যাংচেইন ব্যবহার করব কারণ আমার পেশাদার অভিজ্ঞতা থেকে এটির সাথে আমার পরিচিতি রয়েছে। যেকোনো RAG কাঠামোর একটি অপরিহার্য উপাদান হল ভেক্টর স্টোরেজ। আমরা ব্যবহার করা হবে এখানে, যেহেতু এটি ল্যাংচেইনের সাথে ভালভাবে সংহত করে। RAG ল্যাংচেইন LLamIndex ক্রোমা : ইউজার ইন্টারফেসও একটি গুরুত্বপূর্ণ উপাদান। যদিও অনেক প্রযুক্তি উপলব্ধ আছে, আমি ব্যবহার করতে পছন্দ করি , একটি পাইথন লাইব্রেরি, মনের শান্তির জন্য। চ্যাট UI স্ট্রিমলিট ঠিক আছে, এর সেট আপ করা শুরু করা যাক। ওল্লামা সেটআপ করুন উপরে উল্লিখিত হিসাবে, ওল্লামা সেট আপ এবং চালানো সোজা। প্রথম, পরিদর্শন করুন এবং আপনার অপারেটিং সিস্টেমের জন্য উপযুক্ত অ্যাপটি ডাউনলোড করুন। ollama.ai এর পরে, আপনার টার্মিনাল খুলুন, এবং সর্বশেষ টানতে নিম্নলিখিত কমান্ডটি চালান . যদিও অন্যান্য অনেক আছে , আমি এর কমপ্যাক্ট আকার এবং প্রতিযোগিতামূলক মানের জন্য Mistral-7B বেছে নিই। Mistral-7B এলএলএম মডেল উপলব্ধ ollama pull mistral এর পরে, মডেলটি সঠিকভাবে টানা হয়েছে কিনা তা যাচাই করতে চালান। টার্মিনাল আউটপুট নিম্নলিখিত অনুরূপ হওয়া উচিত: ollama list এখন, যদি LLM সার্ভার ইতিমধ্যেই চালু না হয়, তাহলে দিয়ে শুরু করুন। আপনি যদি মতো একটি ত্রুটির বার্তার সম্মুখীন হন, তাহলে এটি নির্দেশ করে যে সার্ভারটি ইতিমধ্যেই ডিফল্টরূপে চলছে এবং আপনি পরবর্তী ধাপে যেতে পারেন৷ ollama serve "Error: listen tcp 127.0.0.1:11434: bind: address already in use" RAG পাইপলাইন তৈরি করুন আমাদের প্রক্রিয়ার দ্বিতীয় ধাপ হল RAG পাইপলাইন তৈরি করা। আমাদের আবেদনের সরলতার পরিপ্রেক্ষিতে, আমাদের প্রাথমিকভাবে দুটি পদ্ধতির প্রয়োজন: এবং । ingest ask পদ্ধতিটি একটি ফাইল পাথ গ্রহণ করে এবং এটি দুটি ধাপে ভেক্টর স্টোরেজে লোড করে: প্রথমত, এটি LLM-এর টোকেন সীমা মিটমাট করার জন্য নথিটিকে ছোট খণ্ডে বিভক্ত করে; দ্বিতীয়ত, এটি Qdrant FastEmbeddings ব্যবহার করে এই অংশগুলিকে ভেক্টরাইজ করে এবং ক্রোমাতে সংরক্ষণ করে। ingest পদ্ধতি ব্যবহারকারীর প্রশ্নগুলি পরিচালনা করে। ব্যবহারকারীরা একটি প্রশ্ন উত্থাপন করতে পারে, এবং তারপর RetrievalQAChain ভেক্টর সাদৃশ্য অনুসন্ধান কৌশল ব্যবহার করে প্রাসঙ্গিক প্রসঙ্গ (ডকুমেন্ট খণ্ড) পুনরুদ্ধার করে। ask ব্যবহারকারীর প্রশ্ন এবং পুনরুদ্ধার করা প্রসঙ্গে, আমরা একটি প্রম্পট রচনা করতে পারি এবং 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 প্রম্পটটি ল্যাংচেইন হাব থেকে নেওয়া হয়েছে: . এই প্রম্পটটি হাজার হাজার বার পরীক্ষিত এবং ডাউনলোড করা হয়েছে, যা এলএলএম প্রম্পটিং কৌশল সম্পর্কে শেখার জন্য একটি নির্ভরযোগ্য সংস্থান হিসেবে কাজ করে। মিস্ট্রালের জন্য ল্যাংচেইন RAG প্রম্পট আপনি এলএলএম প্রম্পটিং কৌশল সম্পর্কে আরও জানতে পারেন . এখানে বাস্তবায়ন সম্পর্কে আরও বিশদ: : ব্যবহারকারীর দ্বারা আপলোড করা PDF ফাইল লোড করতে আমরা PyPDFLloader ব্যবহার করি। Langchain দ্বারা প্রদত্ত Recursive CharacterSplitter, তারপর এই PDF কে ছোট ছোট খন্ডে বিভক্ত করে। Langchain থেকে ফাংশন ব্যবহার করে ChromaDB দ্বারা সমর্থিত নয় এমন জটিল মেটাডেটা ফিল্টার করা গুরুত্বপূর্ণ। ingest filter_complex_metadata ভেক্টর স্টোরেজের জন্য, ক্রোমা ব্যবহার করা হয়, এর সাথে মিলিত আমাদের এমবেডিং মডেল হিসাবে। এই লাইটওয়েট মডেলটি 0.5 এবং k=3 এর স্কোর থ্রেশহোল্ড সহ একটি পুনরুদ্ধারকারীতে রূপান্তরিত হয়, যার অর্থ এটি 0.5 এর উপরে সর্বোচ্চ স্কোর সহ শীর্ষ 3টি অংশ প্রদান করে। অবশেষে, আমরা ব্যবহার করে একটি সাধারণ কথোপকথন চেইন তৈরি করি . Qdrant FastEmbed এলইসিএল : এই পদ্ধতিটি ব্যবহারকারীর প্রশ্নকে আমাদের পূর্বনির্ধারিত চেইনে পাস করে এবং তারপর ফলাফল প্রদান করে। ask : এই পদ্ধতিটি একটি নতুন PDF ফাইল আপলোড করার সময় পূর্ববর্তী চ্যাট সেশন এবং স্টোরেজ সাফ করতে ব্যবহৃত হয়। clear একটি সাধারণ UI খসড়া একটি সাধারণ ইউজার ইন্টারফেসের জন্য, আমরা ব্যবহার করব , AI/ML অ্যাপ্লিকেশনগুলির দ্রুত প্রোটোটাইপিংয়ের জন্য ডিজাইন করা একটি UI ফ্রেমওয়ার্ক৷ স্ট্রিমলিট 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 অ্যাপ্লিকেশন তৈরি করতে হয় তার একটি উচ্চ-স্তরের ওভারভিউ প্রদানের উপর ফোকাস করে, তাই এমন বেশ কয়েকটি দিক রয়েছে যার জন্য সূক্ষ্ম-টিউনিং প্রয়োজন। আপনার অ্যাপটি উন্নত করতে এবং আপনার দক্ষতা আরও বিকাশ করতে আপনি নিম্নলিখিত পরামর্শগুলি বিবেচনা করতে পারেন: : বর্তমানে, এটি কথোপকথনের প্রবাহ মনে রাখে না। অস্থায়ী মেমরি যোগ করা আপনার সহকারীকে প্রসঙ্গ সম্পর্কে সচেতন হতে সাহায্য করবে। কথোপকথন চেইনে মেমরি যোগ করুন : একবারে একটি নথির বিষয়ে চ্যাট করা ঠিক। কিন্তু কল্পনা করুন যদি আমরা একাধিক নথি সম্পর্কে চ্যাট করতে পারি — আপনি সেখানে আপনার পুরো বুকশেলফ রাখতে পারেন। যে সুপার শান্ত হবে! একাধিক ফাইল আপলোডের অনুমতি দিন : মিস্ট্রাল কার্যকর হলেও, অন্যান্য অনেক বিকল্প উপলব্ধ রয়েছে। আপনি এমন একটি মডেল খুঁজে পেতে পারেন যা আপনার প্রয়োজনের সাথে আরও ভালভাবে ফিট করে, যেমন ডেভেলপারদের জন্য LlamaCode। যাইহোক, মনে রাখবেন যে মডেলের পছন্দ আপনার হার্ডওয়্যারের উপর নির্ভর করে, বিশেষ করে আপনার কাছে কতটা RAM আছে 💵 অন্যান্য এলএলএম মডেল ব্যবহার করুন : RAG-এর মধ্যে পরীক্ষা-নিরীক্ষার জায়গা আছে। আপনি পুনরুদ্ধার মেট্রিক, এমবেডিং মডেল,.. পরিবর্তন করতে চাইতে পারেন বা ফলাফল উন্নত করতে পুনরায় র্যাঙ্কারের মতো স্তর যুক্ত করতে চাইতে পারেন। RAG পাইপলাইন উন্নত করুন পরিশেষে, পড়ার জন্য আপনাকে ধন্যবাদ. যদি আপনি এই তথ্য দরকারী খুঁজে, আমার সদস্যতা বিবেচনা করুন অথবা আমার ব্যক্তিগত . আমি আরএজি এবং এলএলএম অ্যাপ্লিকেশনগুলি সম্পর্কে আরও লেখার পরিকল্পনা করছি, এবং নীচে একটি মন্তব্য রেখে বিষয়গুলির পরামর্শ দেওয়ার জন্য আপনাকে স্বাগত জানাই৷ চিয়ার্স! সাবস্ট্যাক ব্লগ সম্পূর্ণ উৎস কোড: https://github.com/vndee/local-rag-example