ساخت یک برنامه RAG با استفاده از LangChain و LangSmith

Summarize this content to 400 words in Persian Lang
چرا RAG؟
LLM ها از زمان پیدایش خود راه طولانی را پیموده اند. با این حال، یکی از مشکلات اصلی LLM ها این است که آنها بر روی داده های در دسترس عموم یا داده های آموزشی عمومی آموزش می بینند. این بدان معنی است که آنها قادر به عملکرد خوبی در سناریوهای خاص دامنه نیستند. برای غلبه بر این، یا باید مدل را با دادههای اختصاصی دامنه که پرهزینه است، دوباره آموزش دهیم یا از چیزی مانند RAG استفاده کنیم.
یکی دیگر از نیازهای مهم این است که LLM ها شناخته شده باشند توهم داشتن(پاسخی ایجاد کنید که درست به نظر می رسد اما در داده های آموزشی موجود نیست/در واقع نادرست است). یکی از راههای غلبه بر این موضوع این است زمین پاسخ با اطلاعات قابل اعتماد مربوطه
RAG چیست؟
RAG مخفف بازیابی نسل افزوده. اصل اساسی این است که وقتی یک LLM را پرس و جو می کنیم، در زمینه مرتبط با پرس و جو ارسال می کنیم تا LLM بتواند به راحتی با اطلاعات مرتبط پاسخ دهد. اکنون میتوانیم این کار را انجام دهیم، زیرا پنجرههای زمینهای که قبلاً توکنهای 2048/4096 را داشتند، اکنون به حدود 1 میلیون برای مدلهای جدیدتر رسیدهاند. 3 مرحله اساسی در RAG وجود دارد،
نمایه سازی
بازیابی
نسل
ما یک مورد ساده استفاده می کنیم و LLM ها را در عمل می بینیم. من یک پست وبلاگی را که قبلا نوشتم با استفاده از آن برای زمینه می گیرم و یک سوال مرتبط برای آن می پرسم. در اینجا یک نمودار سریع توضیح داده شده است که جریان را توضیح می دهد.
برای رسیدن به این هدف از LangChain، HuggingFace (درخواست رایگان API) و LangSmith (برای ردیابی) استفاده خواهیم کرد. ابتدا ماژول های مورد نیاز را نصب کنید.
! pip install langchain_community tiktoken langchainhub chromadb langchain langchain_huggingface
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یک فایل env ایجاد کنید و کلیدهای API مورد استفاده در این مقاله را اضافه کنید.
LANGCHAIN_API_KEY=”
HF_TOKEN=”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
چند متغیر محیطی را که می توان در فایل .env تنظیم کرد، مقداردهی اولیه کنید.
import os
os.environ[‘LANGCHAIN_TRACING_V2’] = ‘true’
os.environ[‘LANGCHAIN_ENDPOINT’] = ‘https://api.smith.langchain.com’
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
نمایه سازی
اولین مرحله در RAG ایندکس کردن است. ما اساساً باید سند را به یک نمایش برداری به نام embeddings تبدیل کنیم. دلیل این امر این است که یافتن ارتباط بین متن های مشابه زمانی که در قالب برداری هستند آسان تر است. چند مرحله در نمایه سازی داده ها وجود دارد.
بارگذاری
تقسیم شدن
جاسازی
بارگذاری
LangChain راه های زیادی برای بارگیری داده ها ارائه می دهد. ما از یک ساده استفاده خواهیم کرد WebBaseLoader برای بارگذاری مقاله در حافظه
# Load blog
import bs4
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader(
web_paths=(“https://vignesh.page/posts/kafka/”,),
bs_kwargs=dict(
# parse_only=bs4.SoupStrainer(
# class_=(“main-content”)
# )
),
)
blog_docs = loader.load()
blog_docs
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
تقسیم شدن
ما باید دادهها را برای Embedding تقسیم کنیم، زیرا محدودیت اندازه برای تعداد دادههایی که میتوان در یک حرکت جاسازی کرد وجود دارد. ما در حال استفاده از RecursiveCharacterTextSplitter برای مثال ما
# Split
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=300,
chunk_overlap=50)
# Make splits
splits = text_splitter.split_documents(blog_docs)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
نمایه سازی
آخرین مرحله ایندکس کردن داده ها در فروشگاه Vector است. برای این مثال، از یک نمونه در حافظه استفاده خواهیم کرد کروما. ما در حال استفاده از HuggingFaceEmbeddings برای جاسازی داده ها ما ذخیره بردار را به عنوان یک بازیابی با k = 1 تنظیم می کنیم (از الگوی k نزدیکترین همسایگان برای یافتن اسناد مربوطه استفاده می کنیم، بنابراین 1 فقط اسناد مربوطه را برمی گرداند).
# Index
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vector stores import Chroma
vector store = Chroma.from_documents(documents=splits,
embedding=HuggingFaceEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={“k”: 1})
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بازیابی
مرحله بعدی کاملاً ساده است، فقط باید تکههای سند مربوطه را هر زمان که درخواستی دریافت کردیم، بازیابی کنیم. پرسش من “کافکا چیست؟” 4 سند را با داده های مربوطه برگرداند که به عنوان زمینه به LLM ارسال می شود.
docs = retriever.get_relevant_documents(“What is Kafka?”)
len(docs)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ما می توانیم ردیابی LangSmith را ببینیم که به ما اطلاع می دهد که چه چیزی بازیابی شده است.
نسل
اکنون، تنها چیزی که باقی میماند این است که اسناد مربوطه را به LLM ارسال کنیم تا پاسخ ما را به درخواست دریافت کنیم.
ما در این مثال از مدل Falcon-7B از HuggingFace استفاده می کنیم، با خیال راحت با هر LLM انتخابی خود تعویض کنید.
# LLM
from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace
llm = HuggingFaceEndpoint(
repo_id=”tiiuae/falcon-7b”,
task=”text-generation”,
max_new_tokens=512,
do_sample=False,
repetition_penalty=1.03,
)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در مرحله بعد، یک الگوی اعلان برای ارسال پرس و جو و زمینه ایجاد می کنیم.
from langchain.prompts import ChatPromptTemplate
# Prompt
template = “””Answer the question based only on the following context:
{context}
Question: {question}
“””
prompt = ChatPromptTemplate.from_template(template)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ما از LangChain برای زنجیر کردن اینها به هم و ایجاد یک زنجیره ساده استفاده خواهیم کرد. سپس زنجیر را فراخوانی می کنیم.
# Chain
chain = prompt | llm
# Run
chain.invoke({“context”:docs,”question”:”What is Kafka?”})
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
پس از افزودن مقداری قند نحوی، میتوان آن را آسانتر خواند. ما همچنین یک اعلان RAG پیشفرض را اضافه میکنیم که در هاب LangChain موجود است.
from langchain import hub
prompt_hub_rag = hub.pull(“rlm/rag-prompt”)
rag_chain = (
{“context”: retriever, “question”: RunnablePassthrough()}
| prompt_hub_rag
| llm
| StrOutputParser()
)
rag_chain.invoke(“What is Kafka?”)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
رد اجرای این زنجیره را در لانگ اسمیت هم می توانیم ببینیم.
کد در github من موجود است. لطفا آن را انجام دهید. تمام منابع مورد استفاده در زیر لایه رایگان قرار دارند و به راحتی قابل دسترسی هستند.
بنابراین با چند خط کد، میتوانیم یک برنامه RAG ساده بسازیم. ما ابزارهای زیادی در داخل LangChain داریم که می تواند یک مقاله جداگانه باشد.
در اصل در vignesh.page ارسال شده است.
اگر مقاله را مفید یافتید، لطفاً آن را به اشتراک بگذارید. امیدواریم که این به شما در شروع سفر توسعه برنامه هوش مصنوعی Gener کمک کند.
چرا RAG؟
LLM ها از زمان پیدایش خود راه طولانی را پیموده اند. با این حال، یکی از مشکلات اصلی LLM ها این است که آنها بر روی داده های در دسترس عموم یا داده های آموزشی عمومی آموزش می بینند. این بدان معنی است که آنها قادر به عملکرد خوبی در سناریوهای خاص دامنه نیستند. برای غلبه بر این، یا باید مدل را با دادههای اختصاصی دامنه که پرهزینه است، دوباره آموزش دهیم یا از چیزی مانند RAG استفاده کنیم.
یکی دیگر از نیازهای مهم این است که LLM ها شناخته شده باشند توهم داشتن(پاسخی ایجاد کنید که درست به نظر می رسد اما در داده های آموزشی موجود نیست/در واقع نادرست است). یکی از راههای غلبه بر این موضوع این است زمین پاسخ با اطلاعات قابل اعتماد مربوطه
RAG چیست؟
RAG مخفف بازیابی نسل افزوده. اصل اساسی این است که وقتی یک LLM را پرس و جو می کنیم، در زمینه مرتبط با پرس و جو ارسال می کنیم تا LLM بتواند به راحتی با اطلاعات مرتبط پاسخ دهد. اکنون میتوانیم این کار را انجام دهیم، زیرا پنجرههای زمینهای که قبلاً توکنهای 2048/4096 را داشتند، اکنون به حدود 1 میلیون برای مدلهای جدیدتر رسیدهاند. 3 مرحله اساسی در RAG وجود دارد،
- نمایه سازی
- بازیابی
- نسل
ما یک مورد ساده استفاده می کنیم و LLM ها را در عمل می بینیم. من یک پست وبلاگی را که قبلا نوشتم با استفاده از آن برای زمینه می گیرم و یک سوال مرتبط برای آن می پرسم. در اینجا یک نمودار سریع توضیح داده شده است که جریان را توضیح می دهد.
برای رسیدن به این هدف از LangChain، HuggingFace (درخواست رایگان API) و LangSmith (برای ردیابی) استفاده خواهیم کرد. ابتدا ماژول های مورد نیاز را نصب کنید.
! pip install langchain_community tiktoken langchainhub chromadb langchain langchain_huggingface
یک فایل env ایجاد کنید و کلیدهای API مورد استفاده در این مقاله را اضافه کنید.
LANGCHAIN_API_KEY=''
HF_TOKEN=''
چند متغیر محیطی را که می توان در فایل .env تنظیم کرد، مقداردهی اولیه کنید.
import os
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com'
نمایه سازی
اولین مرحله در RAG ایندکس کردن است. ما اساساً باید سند را به یک نمایش برداری به نام embeddings تبدیل کنیم. دلیل این امر این است که یافتن ارتباط بین متن های مشابه زمانی که در قالب برداری هستند آسان تر است. چند مرحله در نمایه سازی داده ها وجود دارد.
- بارگذاری
- تقسیم شدن
- جاسازی
بارگذاری
LangChain راه های زیادی برای بارگیری داده ها ارائه می دهد. ما از یک ساده استفاده خواهیم کرد WebBaseLoader برای بارگذاری مقاله در حافظه
# Load blog
import bs4
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader(
web_paths=("https://vignesh.page/posts/kafka/",),
bs_kwargs=dict(
# parse_only=bs4.SoupStrainer(
# class_=("main-content")
# )
),
)
blog_docs = loader.load()
blog_docs
تقسیم شدن
ما باید دادهها را برای Embedding تقسیم کنیم، زیرا محدودیت اندازه برای تعداد دادههایی که میتوان در یک حرکت جاسازی کرد وجود دارد. ما در حال استفاده از RecursiveCharacterTextSplitter برای مثال ما
# Split
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=300,
chunk_overlap=50)
# Make splits
splits = text_splitter.split_documents(blog_docs)
نمایه سازی
آخرین مرحله ایندکس کردن داده ها در فروشگاه Vector است. برای این مثال، از یک نمونه در حافظه استفاده خواهیم کرد کروما. ما در حال استفاده از HuggingFaceEmbeddings برای جاسازی داده ها ما ذخیره بردار را به عنوان یک بازیابی با k = 1 تنظیم می کنیم (از الگوی k نزدیکترین همسایگان برای یافتن اسناد مربوطه استفاده می کنیم، بنابراین 1 فقط اسناد مربوطه را برمی گرداند).
# Index
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vector stores import Chroma
vector store = Chroma.from_documents(documents=splits,
embedding=HuggingFaceEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
بازیابی
مرحله بعدی کاملاً ساده است، فقط باید تکههای سند مربوطه را هر زمان که درخواستی دریافت کردیم، بازیابی کنیم. پرسش من “کافکا چیست؟” 4 سند را با داده های مربوطه برگرداند که به عنوان زمینه به LLM ارسال می شود.
docs = retriever.get_relevant_documents("What is Kafka?")
len(docs)
ما می توانیم ردیابی LangSmith را ببینیم که به ما اطلاع می دهد که چه چیزی بازیابی شده است.
نسل
اکنون، تنها چیزی که باقی میماند این است که اسناد مربوطه را به LLM ارسال کنیم تا پاسخ ما را به درخواست دریافت کنیم.
ما در این مثال از مدل Falcon-7B از HuggingFace استفاده می کنیم، با خیال راحت با هر LLM انتخابی خود تعویض کنید.
# LLM
from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace
llm = HuggingFaceEndpoint(
repo_id="tiiuae/falcon-7b",
task="text-generation",
max_new_tokens=512,
do_sample=False,
repetition_penalty=1.03,
)
در مرحله بعد، یک الگوی اعلان برای ارسال پرس و جو و زمینه ایجاد می کنیم.
from langchain.prompts import ChatPromptTemplate
# Prompt
template = """Answer the question based only on the following context:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
ما از LangChain برای زنجیر کردن اینها به هم و ایجاد یک زنجیره ساده استفاده خواهیم کرد. سپس زنجیر را فراخوانی می کنیم.
# Chain
chain = prompt | llm
# Run
chain.invoke({"context":docs,"question":"What is Kafka?"})
پس از افزودن مقداری قند نحوی، میتوان آن را آسانتر خواند. ما همچنین یک اعلان RAG پیشفرض را اضافه میکنیم که در هاب LangChain موجود است.
from langchain import hub
prompt_hub_rag = hub.pull("rlm/rag-prompt")
rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt_hub_rag
| llm
| StrOutputParser()
)
rag_chain.invoke("What is Kafka?")
رد اجرای این زنجیره را در لانگ اسمیت هم می توانیم ببینیم.
کد در github من موجود است. لطفا آن را انجام دهید. تمام منابع مورد استفاده در زیر لایه رایگان قرار دارند و به راحتی قابل دسترسی هستند.
بنابراین با چند خط کد، میتوانیم یک برنامه RAG ساده بسازیم. ما ابزارهای زیادی در داخل LangChain داریم که می تواند یک مقاله جداگانه باشد.
در اصل در vignesh.page ارسال شده است.
اگر مقاله را مفید یافتید، لطفاً آن را به اشتراک بگذارید. امیدواریم که این به شما در شروع سفر توسعه برنامه هوش مصنوعی Gener کمک کند.