Rag 2.0 کاربردی: از حافظه ماهی طلا گرفته تا مکالمات مانند چتپپ (10 برابر ربات باهوش)


نویسنده (ها): Aakash Makwana

در ابتدا منتشر شده در به سمت هوش مصنوعیبشر

Rag 2.0 کاربردی: از حافظه ماهی طلا گرفته تا مکالمات مانند چتپپ (10 برابر ربات باهوش)Rag 2.0 کاربردی: از حافظه ماهی طلا گرفته تا مکالمات مانند چتپپ (10 برابر ربات باهوش)

خوش آمدید! در قسمت 1، شما اولین برنامه تولید بازیابی (RAG) خود را ساخته اید. این به س questions الات یک سند پاسخ داد. اما کاربران فقط پاسخ های یک طرفه را نمی خواهند- آنها مکالمه ، کنترل و دقت می خواهند.

امروز ، ما برنامه RAG شما را به ارتقا خواهیم داد Rag 2.0 با:

  • حافظه گپ (بنابراین آخرین سوال شما را به یاد می آورد).
  • جستجوی کلمه کلیدی (برای اجازه دادن به کاربران “Google” در اسناد خود).
  • تقسیم متن باهوش تر (دیگر جمله های خرد شده!).

آنچه ما می سازیم

در پایان این آموزش ، شما Rag Chatbot مبتنی بر جریان با:

  • نوار جستجوی کلمه کلیدی (در بالای جستجوی بردار)
  • تاریخچه گپ (حافظه مکالمه)
  • بهبود یافته چاک دهی و پاسخ دادن به زمین

recap سریع: برنامه RAG چیست؟

یک برنامه RAG دو ابرقدرت را ترکیب می کند:

  1. بازیابی – مناسب ترین اسناد را بکشید.
  2. تولید – استفاده از LLM برای تولید پاسخ از آن اسناد.

این یک شروع عالی است! با چند ترفند ، می تواند حتی بهتر باشد. بیایید با هم روی آن کار کنیم. پیشنهاد می کنم مقاله اول را بخوانید در اینجا برای به دست آوردن درک واضح تر از این یکی.

مرحله 1: بیایید یک سند ایجاد کنیم

یک پوشه به نام داده ایجاد کرده و سند زیر را به عنوان Essay.txt ذخیره کنید

In the early days of a startup, speed and iteration matter more than elegance or scale. 
Founders are constantly experimenting, often pivoting from one idea to another based on user feedback.
Success depends less on building the perfect product and more on discovering what users truly need.
Many of today’s biggest tech companies started as something very different from what they are now.
Twitter began as a podcast platform. Instagram started as a location check-in app.
What made them successful was not their original vision, but their willingness to adapt quickly.
The lesson: the key to startup success is not perfection, but learning, listening, and iterating fast.

مرحله 2: وابستگی ها را نصب کنید

pip install streamlit langchain faiss-cpu streamlit transformers sentence-transformers

مرحله 3: کد واقعی پایتون

3.1 وارد کردن کتابخانه ها و ماژول های مربوطه:

import streamlit as st
from langchain.chains import ConversationalRetrievalChain
from langchain.llms import HuggingFacePipeline
from langchain.memory import ConversationBufferMemory
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
from langchain.prompts import PromptTemplate
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter,RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
import re

3.2 بیایید منطق تقسیم را برطرف کنیم

ممکن است به یاد بیاورید که ما استفاده کردیم CharacterTextSplitter در مقاله قبلیبشر اکنون ، بگذارید یک محدودیت اصلی آن را به شما نشان دهم.

کد:

loader = TextLoader("data/essay.txt")
documents = loader.load()

text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=10,separator="")
docs = text_splitter.split_documents(documents)

for i, doc in enumerate(docs):
print(f"Chunk {i+1}:\n{doc.page_content}\n")

خروجی:

Chunk 1:
In the early days of a startup, speed and iteration matter more than perfection.
Instagram started a

Chunk 2:
started as a check-in app. Twitter began as a podcast platform.
Many successful startups pivoted be

Chunk 3:
pivoted before becoming what they are today.
The key lesson: Learn fast, iterate faster, and listen

Chunk 4:
nd listen to users.

مشاهدات:
1. نگاه کنید که چگونه تکه 1 به پایان می رسد “اینستاگرام شروع کرد”بشر

2. به طور مشابه ، Chunk 2 با شروع می شود “به عنوان یک برنامه ورود به سیستم شروع شد”بشر چه چیزی شروع شد؟

می توانید اطلاعات مشابه را در بخش های مختلف مشاهده کنید. این در درجه اول است زیرا CharacterTextSplitter تقسیم در تعداد کاراکتر ، که بعضی اوقات منجر به مرزهای نادرست کلمه می شود.

به یاد داشته باشید وقتی ما در مورد چگونگی عملکرد این بخش ها به عنوان حافظه صحبت کردیم؟ اگر حافظه شما کامل نباشد ، عملکرد صحیح می تواند سخت باشد ، نمی تواند؟ همین ایده در مورد پارچه ما صدق می کند.

راه حل:
ما استفاده خواهیم کرد RecursiveCharacterTextSplitterبشر این یک نسخه باهوش تر و انعطاف پذیر تر از است CharacterTextSplitter از لانگچین، برای تقسیم متن طراحی شده است در مرزهای طبیعی -مانند پاراگراف ها ، جملات و کلمات-قبل از اینکه در صورت لزوم به شکاف های سطح شخصیت برگردید.

کد:

loader = TextLoader("data/essay.txt")
documents = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=10)
docs = text_splitter.split_documents(documents)

for i, doc in enumerate(docs):
print(f"Chunk {i+1}:\n{doc.page_content}\n")

خروجی:

Chunk 1:
In the early days of a startup, speed and iteration matter more than perfection.

Chunk 2:
Instagram started as a check-in app. Twitter began as a podcast platform.

Chunk 3:
Many successful startups pivoted before becoming what they are today.

Chunk 4:
The key lesson: Learn fast, iterate faster, and listen to users.

هر تکه کامل و بسیار بهتر از زودتر به نظر می رسد ، درست است؟

3.3 بیایید هنگام ساختن معماری یک مدل بزرگتر بگیریم

پیش از این ، ما از مدل “Google/Flan-T5-Base” استفاده کردیم که برای آن آموزش دیده است مختصر ، مبتنی بر دستورالعمل پاسخ ها همچنین ، بهینه نشده است مبهم ، متنی پاسخ ها از آنجا که ، ما می خواهیم یک Chatbot بسازیم ، از یک مدل بزرگتر مانند “Google/Flan-T5-Large” استفاده خواهیم کرد.

کد:

embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vector_store = FAISS.from_documents(docs, embedding_model)

model_id = "google/flan-t5-large"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSeq2SeqLM.from_pretrained(model_id)

tokenizer.pad_token = tokenizer.eos_token
pipe = pipeline("text2text-generation", model=model, tokenizer=tokenizer)
llm = HuggingFacePipeline(pipeline=pipe)

3.4 الگوی سریع برای خروجی های بهتر

بگذارید پاسخی را که از مدل باز می گردیم ، سفارشی کنیم. بیایید به آن بدهیم سریع و سریع آموزنده بنابراین مانند یک دستیار مفید عمل می کند.

custom_prompt = PromptTemplate.from_template("""
You are a helpful assistant. Use the context to answer the user's question.
If context is unclear, respond gracefully. Be clear and complete.

{context}

Chat History:
{chat_history}

Question:
{question}

Helpful Answer:
"""

)

3.5 اضافه کردن حافظه چت (بنابراین ربات شما را به یاد می آورد)

بدون حافظه ، ربات شما با هر سؤال جدید رفتار می کند. بیایید بگوییم 2 سوال زیر را می پرسیم:
1. “اینستاگرام چگونه شروع شد؟”
2. “و توییتر چیست؟”
ممکن است اتفاق بیفتد که پاسخ سوال اول صحیح است. با این حال ، نماینده ممکن است نتواند سوال 2 را به درستی درک کند.

مشکل: LLM آنچه را که کاربر قبلاً گفته است فراموش می کند.
راه حل: چرخش چت را ردیابی کنید و سؤالات گذشته را تغذیه کنید+پاسخ ها را به متن.

  • از Langchain استفاده کنید ConversationalRetrievalChainبشر پیش از این ، ما استفاده کرده بودیم RetrievalQA
  • چرخش چت را در حافظه ذخیره کنید (به عنوان مثال ، ConversationBufferMemory). به این ترتیب می توانیم به راحتی سؤالات پیگیری را بپرسیم ، زیرا کل تاریخ چت در حافظه نگه داشته می شود.

کد:

memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vector_store.as_retriever(),
memory=memory,
combine_docs_chain_kwargs={"prompt": custom_prompt}
)

3.6 دیدن آن در عمل

بیایید بگوییم شما می پرسید: “درس چیست؟” و سوالات زیر را دنبال کنید:
1 “چگونه اینستاگرام شروع شد؟”
2 “و توییتر چطور؟”

کد:


query = "What is the lesson?"
answer = qa_chain.invoke(query)
print(answer)

خروجی:

{
'question': 'What is the lesson?',
'chat_history': [HumanMessage(content = 'What is the lesson?',
additional_kwargs = {}, response_metadata = {}),
AIMessage(content = 'Learn fast, iterate faster, and listen to users. In the early days of a startup, speed and iteration matter more than perfection. Many successful startups pivoted before becoming what they are today.',
additional_kwargs = {}, response_metadata = {})],
'answer': 'Learn fast, iterate faster, and listen to users. In the early days of a startup, speed and iteration matter more than perfection. Many successful startups pivoted before becoming what they are today.'
}

حالا ، بیایید بپرسیم “چگونه اینستاگرام شروع شد؟”

query = "How did Instagram start?"
answer = qa_chain.invoke(query)
print(answer)

خروجی:

{
'question': 'How did Instagram start?',
'chat_history': [HumanMessage(content = 'What is the lesson?',
additional_kwargs = {}, response_metadata = {}),
AIMessage(content = 'Learn fast, iterate faster, and listen to users. In the early days of a startup, speed and iteration matter more than perfection. Many successful startups pivoted before becoming what they are today.',
additional_kwargs = {}, response_metadata = {}),
HumanMessage(content = 'How did Instagram start?',
additional_kwargs = {}, response_metadata = {}),
AIMessage(content = 'Instagram started as a check-in app.',
additional_kwargs = {}, response_metadata = {})],
'answer': 'Instagram started as a check-in app.'
}

مشاهدات:
با دقت به نحوه ذخیره پاسخ قبلی در بخش chat_history نگاه کنید. همچنین ، ما پاسخی گرفتیم که “اینستاگرام به عنوان یک برنامه چک شروع شده است.”

حالا ، بیایید بپرسیم “و توییتر چطور؟”

query = "and what about twitter?"
answer = qa_chain.invoke(query)
print(answer)

خروجی:

{
'question': 'and what about twitter?',
'chat_history': [HumanMessage(content = 'What is the lesson?',
additional_kwargs = {}, response_metadata = {}),
AIMessage(content = 'Learn fast, iterate faster, and listen to users. In the early days of a startup, speed and iteration matter more than perfection. Many successful startups pivoted before becoming what they are today.',
additional_kwargs = {}, response_metadata = {}),
HumanMessage(content = 'How did Instagram start?',
additional_kwargs = {}, response_metadata = {}),
AIMessage(content = 'Instagram started as a check-in app.',
additional_kwargs = {}, response_metadata = {}),
HumanMessage(content = 'and what about twitter?',
additional_kwargs = {}, response_metadata = {}),
AIMessage(content = 'Twitter began as a podcast platform.',
additional_kwargs = {}, response_metadata = {})],
'answer': 'Twitter began as a podcast platform.'
}

مشاهده:

کل تاریخ چت را می توان در اینجا مشاهده کرد. نکته جالب برای مشاهده این است که سوال 3 “و توییتر چطور؟” – پارچه قادر به انتخاب این سوال واقعی است “چگونه توییتر شروع شد؟”

3.7 جایزه: برای کنترل کاربران جستجو را اضافه کنید

چه چیزی از دست رفته است:
گاهی اوقات LLM اسناد غیرقانونی را انتخاب می کند. کاربران آرزو می کنند که بتوانند آنچه را که جستجو می شود ببینند یا تغییر دهند.

راه حل:
به کاربران اجازه دهید نتایج جستجوی برتر را مشاهده کنید، یا اجازه دهید آنها پرس و جو را اصلاح کنید با فیلترها ، کلمات کلیدی یا کنترل UI ساده.

کد:

search_term = 'Instagram'
results = vector_store.similarity_search_with_score(search_term, k=3)
for i, (doc, score) in enumerate(results, 1):
print('Match',str(i),':',doc.page_content)
print('Score:',score)
print()

خروجی:

Match 1 : Instagram started as a check-in app. Twitter began as a podcast platform.
Score: 0.7018475

Match 2 : Many successful startups pivoted before becoming what they are today.
Score: 1.7003077

Match 3 : The key lesson: Learn fast, iterate faster, and listen to users.
Score: 1.7073045

مشاهده در اینجا: Match 1 نمره 0.7018475 دارد و این تنها کسی است که کلمه اینستاگرام را دارد.
این به این دلیل است که عملکرد SOGINATY_SEARCH_WITH_SCORE لیستی از اسناد شبیه به متن پرس و جو با فاصله L2 در شناور را برمی گرداند. به زبان ساده: نمره پایین نشان دهنده شباهت بیشتر است.

4. قرار دادن همه آن به عنوان یک برنامه پرشور

با داشتن کد زیر یک App.py ایجاد کنید:

import streamlit as st
from langchain.chains import ConversationalRetrievalChain
from langchain.llms import HuggingFacePipeline
from langchain.memory import ConversationBufferMemory
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
from langchain.prompts import PromptTemplate
from langchain.text_splitter import CharacterTextSplitter,RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
import re

def chunk_text(text, chunk_size=100, overlap=20):
splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=overlap)
return splitter.split_text(text)

def create_vector_store(chunks):
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
return FAISS.from_texts(chunks, embeddings)

custom_prompt = PromptTemplate.from_template("""
You are a helpful assistant. Use the context to answer the user's question.
If context is unclear, respond gracefully. Be clear and complete.

{context}

Chat History:
{chat_history}

Question:
{question}

Helpful Answer:
"""

)

# Load and chunk document
with open("data/essay.txt") as f:
text = f.read()
chunks = chunk_text(text)
vector_store = create_vector_store(chunks)

# Setup model
model_id = "google/flan-t5-large"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSeq2SeqLM.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
pipe = pipeline("text2text-generation", model=model, tokenizer=tokenizer)
llm = HuggingFacePipeline(pipeline=pipe)

# Add memory to remember conversation
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

# Create RAG chain
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vector_store.as_retriever(),
memory=memory,
combine_docs_chain_kwargs={"prompt": custom_prompt}
)

# UI
st.title("🧠 RAG 2.0 – Smarter Chatbot")
query = st.text_input("Ask me anything:")

if query:
result = qa_chain.invoke(query)
st.write("🤖", result)

with st.expander("🧵 Chat Memory"):
for m in memory.chat_memory.messages:
st.markdown(f"**{m.type.capitalize()}**: {m.content}")

st.sidebar.title("🔍 Keyword Search")

search_term = st.sidebar.text_input("Enter keyword or phrase")

if search_term:
results = vector_store.similarity_search_with_score(search_term, k=3)
st.sidebar.markdown("### 🔍 Top Matches:")
for i, (doc, score) in enumerate(results, 1):
highlighted = re.sub(
f"({re.escape(search_term)})",
r"**\1**",
doc.page_content,
flags=re.IGNORECASE
)

st.sidebar.markdown(f"**Match {i} (Score: {score:.4f}):**")
st.sidebar.write(highlighted.strip())

دستور زیر را در پنجره Bash یا ترمینال خود اجرا کنید:

streamlit run app.py

این یک نمونه جریان را آغاز می کند ، و می توانید خروجی را مانند زیر مشاهده کنید:

نکته نهایی: اشکال زدایی پارچه خود را

اگر پاسخ ها خاموش به نظر می رسد:

  1. اندازه تکه ها را بررسی کنید (print(docs)).
  2. بازیابی تست به تنهایی (retriever.get_relevant_documents("your query")).
  3. الگوی سریع را تغییر دهید (به عنوان مثال ، “فقط از متن پاسخ دهید: {زمینه}”).

نتیجه گیری:

فقط با چند خط کد اضافی ، برنامه RAG خود را از یک نسخه ی نمایشی اسباب بازی به A منتقل کرده اید مکالمه ، دستیار AI قابل جستجوبشر بگذارید سریع RAG 1.0 در مقابل RAG 2.0 را مقایسه کنیم:

به اشتراک گذاشتن یک گردش کار بصری:

به عنوان یک یادداشت پایان ، من قیاس را به اشتراک می گذارم تا به راحتی بلوک های ساختمانی RAG را به خاطر بسپارم:

  • تکه = صفحات یک نوت بوک هوشمند
  • تعبیه = اثر انگشت هر صفحه
  • جستجوی بردار = یافتن اثر انگشت مشابه
  • پرسش = شما یک اثر انگشت در دست دارید و می پرسید: “کدام صفحه به این شکل است؟”
  • بازیابی = صفحات مشابه را پیدا می کند
  • LLM = صفحات را می خواند + به سوال شما پاسخ می دهد
  • خاطره = آنچه را که قبلاً در مورد آن صحبت کرده اید به یاد می آورد

امیدوارم این مقاله مفید باشد و درک شما را بهبود بخشد. من آن را در طول سفر یادگیری در مورد Rag نوشتم. مدتی طول کشید تا کامپایل شود ، و امیدوارم که به عنوان یک مرجع سریع برای تازه واردان علاقه مند به یادگیری و اجرای پارچه ها عمل کند.

منتشر شده از طریق به سمت هوش مصنوعی



منبع: https://towardsai.net/p/l/applied-rag-2-0-from-goldfish-memory-to-chatgpt-like-conversations-10x-smarter-bot