پیاده سازی RAG با استفاده از LlamaIndex، Pinecone و Langtrace: راهنمای گام به گام

Summarize this content to 400 words in Persian Lang در دنیای امروزی مبتنی بر داده، نیاز به روشهای سریعتر و کارآمدتر برای پردازش و استفاده از اطلاعات هرگز حیاتیتر نبوده است. اکثر LLM ها بر روی طیف گسترده ای از داده های عمومی تا یک نقطه زمانی خاص آموزش می بینند، بنابراین زمانی که یک مدل در مورد اطلاعاتی که به طور عمومی در دسترس نیست یا فراتر از تاریخ قطع آن (یعنی داده هایی که در آموزش آن استفاده نشده است) پرس و جو می شود، به احتمال زیاد توهم ایجاد می کند. چیزی بسازید یا با اطلاعات قدیمی پاسخ دهید. گاهی اوقات این توهمات می توانند کاملاً قانع کننده به نظر برسند، بنابراین ممکن است برای جلوگیری از آنها تلاش بیشتری لازم باشد (این جایی است که نظارت و ارزیابی نقش مهمی ایفا می کند، اما در ادامه در این پست بیشتر در مورد آن توضیح خواهیم داد).
برای LLMها برای دادن پاسخهای مرتبط و خاص خارج از دادههای آموزشی خود، زمینه اضافی توسط مدل مورد نیاز است. اینجاست که RAG (نسل تقویتشده بازیابی) وارد میشود. این پست وبلاگ قصد دارد شما را در مراحل پیادهسازی یک سیستم موثر RAG با استفاده از ابزارهایی مانند LlamaIndex، Pinecone و Langtrace راهنمایی کند.
همانطور که از نام آن مشخص است، 3 مرحله اصلی در ساخت RAG وجود دارد:
بازیابی – این فرآیند شامل شناسایی و واکشی دادههای مرتبط از یک مجموعه داده بزرگ با محدود کردن آن برای تمرکز بر مرتبطترین بخشهای اطلاعات است. این کمک می کند تا زیر محدودیت رمز LLM (تعداد نشانه های ورودی که یک LLM می تواند بپذیرد) باقی بماند.
افزایش – دادههای بهدستآمده از مرحله «بازیابی» را میتوان بهعنوان یک اعلان سیستم، اضافه به پرس و جو یا با استفاده از تکنیک دیگری به منظور در دسترس قرار دادن دادهها در اختیار LLM قرار داد تا زمینه لازم مرتبط با پرس و جو را فراهم کند.
نسل – با استفاده از داده های تقویت شده، یک خروجی منسجم و آگاه از زمینه تولید کنید. این کار با استفاده از مدلهای زبان بزرگی انجام میشود که میتوانند زمینه ارائه شده را برای تولید پاسخهای مفید درک کرده و از آن استفاده کنند.
برای نشان دادن این، ما از موارد زیر استفاده خواهیم کرد:
LlamaIndex: ما از LlamaIndex برای وارد کردن و فهرست کردن داده ها از یک فایل محلی استفاده خواهیم کرد. علاوه بر این، LlamaIndex همچنین میتواند دادهها را از منابع دیگر مانند پایگاههای داده، نقاط پایانی API و غیره وارد کند. سپس دادهها به جاسازیها تبدیل میشوند – نمایشهای عددی کلمات یا عباراتی که معانی آنها را به گونهای که میتواند توسط مدل پردازش شود. این ممکن است یک سادهسازی بیش از حد باشد، اما من دوست دارم به این فکر کنم که رابطه جاسازیها با LLM شبیه روشی است که سیستمهای عامل با بیتهای داده کار میکنند.
کاج: پس از تبدیل داده ها به جاسازی ها، جاسازی ها در یک پایگاه داده برداری ذخیره می شوند که از آنجا می توان از آنها پرس و جو کرد. ما از Pinecone به عنوان پایگاه داده برداری انتخابی خود برای ذخیره این جاسازی های برداری تولید شده از داده هایمان استفاده خواهیم کرد.
مجموعه داده مورد استفاده برای این نمایش فهرستی از حدود 17 هزار ماده غذایی از چندین رستوران در لاگوس، نیجریه است که در JSON ذخیره شده است.
[…,
{
“name”: “Spicy Seafood Soup”,
“price”: “3500”,
“description”: “Shrimps, scallop, mushroom, soya sauce”,
“place_name”: “Izanagi”,
“category”: “Soup”
},
…
]
LlamaIndex و Pinecone را نصب کنید
مرحله اول نصب و وارد کردن LlamaIndex و Pinecone است
توجه: به کلیدهای API از OpenAI و Pinecone نیاز دارید
pip install llama-index
pip install pinecone-client
pip install llama-index-vector-stores-pinecone
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from pinecone import Pinecone, ServerlessSpec
تنظیم متغیرهای محیطی
export PINECONE_API_KEY=<PINECONE-API-KEY>
export OPENAI_API_KEY=<OPENAI-API-KEY>
یک نمایه Pinecone ایجاد کنید
هنگام ایجاد یک نمایه Pinecone، باید یک نام منحصر به فرد برای این فهرست تعیین کنید که می تواند برای جستجو در جاسازی های ذخیره شده در آن فهرست استفاده شود. این شاخص دارای ابعاد 1536 است و از شباهت کسینوس استفاده می کند، که معیار توصیه شده برای مقایسه بردارهای تولید شده توسط مدل OpenAI-small-text-embedding-3-small است که ما از آن برای ایجاد جاسازی ها قبل از ذخیره در Pinecone استفاده خواهیم کرد.
import os
pc = Pinecone(api_key=os.getenv(“PINECONE_API_KEY”))
index_name = “food-listing”
# create the index if it doesnt already exist
if index_name not in pc.list_indexes().names():
pc.create_index(
name=index_name,
dimension=1536,
metric=”cosine”,
spec=ServerlessSpec(
cloud=”aws”,
region=”us-east-1″
)
)
pinecone_index = pc.Index(index_name)
LlamaIndex از بیش از 20 گزینه ذخیره برداری مختلف پشتیبانی می کند، از جمله Pinecone که ما از آن برای تعامل با نمونه Pinecone خود از طریق نمایه ایجاد شده قبلی استفاده خواهیم کرد. این شی به عنوان رابط ذخیره سازی و بازیابی برای جاسازی های سند ما در پایگاه داده برداری Pinecone عمل می کند.
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(
vector_store=vector_store
)
بعد، داده ها را از دایرکتوری به نام بارگیری می کنیم datastore با استفاده از SimpleDirectoryReader ماژول از LlamaIndex. سپس VectorStoreIndex را ایجاد کنید که فرآیند نمایه سازی و پرس و جو را کنترل می کند و از بسترهای ذخیره سازی و سرویس ارائه شده استفاده می کند.
documents = SimpleDirectoryReader(“datastore”).load_data()
vector_store_index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context
)
در نهایت می توانیم از ایندکسی که می سازیم یک موتور پرس و جو بسازیم و از این موتور برای انجام یک پرس و جو استفاده کنیم.
query = “What’s the price of the Quesadillas at Crepawayre?”
query_engine = index.as_query_engine()
response = query_engine.query(query)
print(response)
این همان چیزی است که کد در کنار هم به نظر می رسد
import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key=os.getenv(“PINECONE_API_KEY”))
index_name = “food-listing”
if index_name not in pc.list_indexes().names():
pc.create_index(
name=index_name,
dimension=1536,
metric=”cosine”,
spec=ServerlessSpec(
cloud=”aws”,
region=”us-east-1″
)
)
pinecone_index = pc.Index(index_name)
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(
vector_store=vector_store
)
documents = SimpleDirectoryReader(“datab”).load_data()
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
query_engine = index.as_query_engine()
response = query_engine.query(“What’s the price of the Quesadillas at Crepawayre?”)
print(response)
چگونه کار می کند
قبل از اجرای اسکریپت، بیایید نگاهی بیندازیم که دقیقاً قرار است چه اتفاقی بیفتد.
LlamaIndex جاسازیها را با استفاده از API تعبیهسازی OpenAI ایجاد میکند، با استفاده از نام ایندکس به نمونه Pinecone شما متصل میشود، آن جاسازیها را در Pinecone ذخیره میکند، متن مربوطه را، با توجه به پرس و جو، از فروشگاه جاسازی برداری بردار میکشد و در نهایت پرس و جو را (با متن) ارسال میکند. به LLM (در این مورد، OpenAI).
این اتفاقات زیادی است که در پشت صحنه اتفاق می افتد و ما ممکن است بخواهیم ببینیم که چگونه همه اینها انجام می شود، یعنی شکست فرآیندها. برای انجام این کار، ما به ابزاری نیاز داریم که این رویدادها را ضبط کند و به ما نشان دهد که هر یک از آنها چه چیزی را شامل می شود و اینجاست که Langtrace وارد می شود (قبلاً به نظارت اشاره کردم که نقش مهمی در اشکال زدایی دارد).
Langtrace یک پلت فرم مشاهده پذیر LLM است که به شما امکان می دهد عملکرد برنامه های کاربردی LLM را نظارت و ارزیابی کنید. این یکپارچه با اکثر LLM ها، چارچوب های LLM، پایگاه های داده برداری کار می کند.
افزودن Langtrace به یک پروژه ساده است زیرا برای اجرای آن فقط به ۲ خط کد نیاز دارد. ابتدا یک حساب کاربری در Langtrace ایجاد می کنیم، یک پروژه ایجاد می کنیم، سپس یک کلید API برای پروژه ایجاد می کنیم.
export LANGTRACE_API_KEY=<YOUR LANGTRACE API KEY>
Langtrace را به کد خود اضافه کنید (خط دوم و آخر زیر)
import os
from langtrace_python_sdk import langtrace # this line must precede all llm imports
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from pinecone import Pinecone, ServerlessSpec
langtrace.init(api_key=os.getenv(“LANGTRACE_API_KEY”))
در نهایت کد را اجرا می کنیم تا ببینیم چه پاسخی دریافت می کنیم
python3 main.py
پاسخ به شرح زیر است:
The price of the Quesadillas at Crepawayre is 5100.
با نگاه کردن به داده ها می توانیم متوجه شویم که پاسخ دقیق بوده است
حالا بیایید نگاهی به داشبورد Langtrace خود بیندازیم تا همه چیزهایی که هنگام اجرای کد اتفاق افتاد را ببینیم.
ما میتوانیم ردیابیهایی را برای تعدادی از جاسازیهایی که ایجاد میشوند ببینیم و این به این دلیل است که LlamaIndex سند اولیه را به تکههایی تقسیم میکند و هر تکه را با استفاده از OpenAI به یک جاسازی تبدیل میکند. text-embedding-ada-002 مدل ما همچنین می توانیم ببینیم pinecone.index.upsert اقدامی که به این صورت است که جاسازیها در Pinecon ذخیره میشوند.
با نگاهی به بیشترین ردیابی، می توانیم ببینیم که llamaindex.RetrieverQueryEngine.query، که وقتی می دویم اتفاق می افتد query_engine.query(“What’s the price of the Quesadillas at Crepawayre?”)، سه عمل مختلف را اجرا می کند: پرس و جو را به جاسازی ها تبدیل می کند، از Pinecone پرس و جو می کند تا داده های مربوطه را بر اساس پرس و جو دریافت کند و در نهایت پرس و جو را به LLM (OpenAI) می فرستد. ما همچنین میتوانیم مدت زمان ردیابی و همچنین مدت زمان بازههای فردی را که آن ردیابی را تشکیل میدهند، ببینیم.
با این تفکیک، میتوانیم بیشتر برویم و با کلیک کردن روی آن نگاهی به آنچه در هر یک از این بازهها میافتد، داشته باشیم. بیایید پرس و جوی دقیق ارسال شده به OpenAI را ببینیم (ما انتظار داریم این مورد با زمینه مربوطه بر اساس پرس و جو اولیه تقویت شود What’s the price of the Quesadillas at Crepawayre?)
می بینیم که پرس و جو به لیستی از اقلام بازگشتی از جستجوی برداری الحاق می شود (در این مورد، تمام مواد غذایی با place_name روی Crepawayre تنظیم کنید) و این همان چیزی است که به API تکمیل چت OpenAI ارسال می شود. با پرس و جو و زمینه مربوطه، OpenAI قادر است پاسخ صحیحی را ارائه دهد.
برای پرسوجوهای بعدی، چون جاسازیها قبلاً در Pinecone ذخیره شدهاند، تنها کاری که باید انجام دهیم این است که از ایندکس برای پرسوجویی از آن جاسازیها استفاده کنیم تا زمینه مربوطه را که برای پرسجویی از LLM نیاز داریم، به دست آوریم. همچنین این پرسوجوها بسیار سریعتر اجرا میشوند، زیرا فهرستسازی و درج جاسازیها در Pinecone فقط باید یک بار اتفاق بیفتد (به جز اینکه دادههای بیشتری اضافه میکنیم یا نمایه جدیدی ایجاد میکنیم).
pc = Pinecone(api_key=os.getenv(“PINECONE_API_KEY”))
index_name = “food-listing-chatbot”
if index_name not in pc.list_indexes().names():
raise Exception(“Index not found”)
pinecone_index = pc.Index(index_name)
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
index = VectorStoreIndex.from_vector_store(vector_store=vector_store)
query_engine = index.as_query_engine()
response = query_engine.query(“I’m craving something spicy, can you recommend something and where can I get it?”)
print(response)
# You might enjoy the “CHICKEN / GOAT MEAT PEPPER SOUP,” which is a spicy broth of chicken or goat meat. You can get it at Yellow Chilli in Ikeja.
نتیجه گیری
همانطور که LLM ها قدرتمند هستند، تا حدودی محدود به داده هایی هستند که روی آنها آموزش دیده اند. در حالی که LLM ها در پاسخ سریع به درخواست های عمومی بسیار مفید هستند، اغلب زمانی که کاربران به دنبال بررسی عمیق تر در موضوعات فعلی یا خاص تر هستند، کوتاهی می کنند. این محدودیت نیاز به Retrieval-Augmented Generation (RAG) را برجسته می کند که از داده های واکشی شده از منابع خارجی استفاده می کند. با ادغام RAG، میتوانیم قابلیتهای LLM را افزایش دهیم و پاسخهای دقیقتر و بهروزتری را به کاربران ارائه دهیم که متناسب با نیازهای خاص آنها باشد.
در این پست نحوه پیاده سازی یک سیستم استاندارد RAG با استفاده از LlamaIndex، Pinecone و OpenAI را توضیح دادیم. ما همچنین از Langtrace برای نظارت بر عملکرد هر یک از این اجزا و نحوه کار آنها با یکدیگر استفاده کردیم. همچنین، میتوانید مسیر دیگری را انتخاب کنید، مثلاً از یک LLM متفاوت مانند Anthropic به جای OpenAI یا یک پایگاه داده برداری متفاوت مانند Weaviate به جای Pinecone استفاده کنید. LlamaIndex، و همچنین Langtrace، دارای ادغام برای تعدادی از LLM ها، فریمورک ها و فروشگاه های برداری هستند که در نتیجه سفارشی سازی را یکپارچه می کند.
منابع مفید
شروع کار با LlamaIndex https://docs.llamaindex.ai/en/stable/
فروشگاههای وکتور LlamaIndex https://docs.llamaindex.ai/en/stable/module_guides/storing/vector_stores/
شروع کار با Pinecone https://docs.pinecone.io/guides/get-started/quickstart
شروع کار با Langtrace https://docs.langtrace.ai/introduction
OpenAI https://platform.openai.com/docs/introduction
در دنیای امروزی مبتنی بر داده، نیاز به روشهای سریعتر و کارآمدتر برای پردازش و استفاده از اطلاعات هرگز حیاتیتر نبوده است. اکثر LLM ها بر روی طیف گسترده ای از داده های عمومی تا یک نقطه زمانی خاص آموزش می بینند، بنابراین زمانی که یک مدل در مورد اطلاعاتی که به طور عمومی در دسترس نیست یا فراتر از تاریخ قطع آن (یعنی داده هایی که در آموزش آن استفاده نشده است) پرس و جو می شود، به احتمال زیاد توهم ایجاد می کند. چیزی بسازید یا با اطلاعات قدیمی پاسخ دهید. گاهی اوقات این توهمات می توانند کاملاً قانع کننده به نظر برسند، بنابراین ممکن است برای جلوگیری از آنها تلاش بیشتری لازم باشد (این جایی است که نظارت و ارزیابی نقش مهمی ایفا می کند، اما در ادامه در این پست بیشتر در مورد آن توضیح خواهیم داد).
برای LLMها برای دادن پاسخهای مرتبط و خاص خارج از دادههای آموزشی خود، زمینه اضافی توسط مدل مورد نیاز است. اینجاست که RAG (نسل تقویتشده بازیابی) وارد میشود. این پست وبلاگ قصد دارد شما را در مراحل پیادهسازی یک سیستم موثر RAG با استفاده از ابزارهایی مانند LlamaIndex، Pinecone و Langtrace راهنمایی کند.
همانطور که از نام آن مشخص است، 3 مرحله اصلی در ساخت RAG وجود دارد:
- بازیابی – این فرآیند شامل شناسایی و واکشی دادههای مرتبط از یک مجموعه داده بزرگ با محدود کردن آن برای تمرکز بر مرتبطترین بخشهای اطلاعات است. این کمک می کند تا زیر محدودیت رمز LLM (تعداد نشانه های ورودی که یک LLM می تواند بپذیرد) باقی بماند.
- افزایش – دادههای بهدستآمده از مرحله «بازیابی» را میتوان بهعنوان یک اعلان سیستم، اضافه به پرس و جو یا با استفاده از تکنیک دیگری به منظور در دسترس قرار دادن دادهها در اختیار LLM قرار داد تا زمینه لازم مرتبط با پرس و جو را فراهم کند.
- نسل – با استفاده از داده های تقویت شده، یک خروجی منسجم و آگاه از زمینه تولید کنید. این کار با استفاده از مدلهای زبان بزرگی انجام میشود که میتوانند زمینه ارائه شده را برای تولید پاسخهای مفید درک کرده و از آن استفاده کنند.
برای نشان دادن این، ما از موارد زیر استفاده خواهیم کرد:
LlamaIndex: ما از LlamaIndex برای وارد کردن و فهرست کردن داده ها از یک فایل محلی استفاده خواهیم کرد. علاوه بر این، LlamaIndex همچنین میتواند دادهها را از منابع دیگر مانند پایگاههای داده، نقاط پایانی API و غیره وارد کند. سپس دادهها به جاسازیها تبدیل میشوند – نمایشهای عددی کلمات یا عباراتی که معانی آنها را به گونهای که میتواند توسط مدل پردازش شود. این ممکن است یک سادهسازی بیش از حد باشد، اما من دوست دارم به این فکر کنم که رابطه جاسازیها با LLM شبیه روشی است که سیستمهای عامل با بیتهای داده کار میکنند.
کاج: پس از تبدیل داده ها به جاسازی ها، جاسازی ها در یک پایگاه داده برداری ذخیره می شوند که از آنجا می توان از آنها پرس و جو کرد. ما از Pinecone به عنوان پایگاه داده برداری انتخابی خود برای ذخیره این جاسازی های برداری تولید شده از داده هایمان استفاده خواهیم کرد.
مجموعه داده مورد استفاده برای این نمایش فهرستی از حدود 17 هزار ماده غذایی از چندین رستوران در لاگوس، نیجریه است که در JSON ذخیره شده است.
[
...,
{
"name": "Spicy Seafood Soup",
"price": "3500",
"description": "Shrimps, scallop, mushroom, soya sauce",
"place_name": "Izanagi",
"category": "Soup"
},
...
]
LlamaIndex و Pinecone را نصب کنید
مرحله اول نصب و وارد کردن LlamaIndex و Pinecone است
توجه: به کلیدهای API از OpenAI و Pinecone نیاز دارید
pip install llama-index
pip install pinecone-client
pip install llama-index-vector-stores-pinecone
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from pinecone import Pinecone, ServerlessSpec
تنظیم متغیرهای محیطی
export PINECONE_API_KEY=<PINECONE-API-KEY>
export OPENAI_API_KEY=<OPENAI-API-KEY>
یک نمایه Pinecone ایجاد کنید
هنگام ایجاد یک نمایه Pinecone، باید یک نام منحصر به فرد برای این فهرست تعیین کنید که می تواند برای جستجو در جاسازی های ذخیره شده در آن فهرست استفاده شود. این شاخص دارای ابعاد 1536 است و از شباهت کسینوس استفاده می کند، که معیار توصیه شده برای مقایسه بردارهای تولید شده توسط مدل OpenAI-small-text-embedding-3-small است که ما از آن برای ایجاد جاسازی ها قبل از ذخیره در Pinecone استفاده خواهیم کرد.
import os
pc = Pinecone(api_key=os.getenv("PINECONE_API_KEY"))
index_name = "food-listing"
# create the index if it doesnt already exist
if index_name not in pc.list_indexes().names():
pc.create_index(
name=index_name,
dimension=1536,
metric="cosine",
spec=ServerlessSpec(
cloud="aws",
region="us-east-1"
)
)
pinecone_index = pc.Index(index_name)
LlamaIndex از بیش از 20 گزینه ذخیره برداری مختلف پشتیبانی می کند، از جمله Pinecone که ما از آن برای تعامل با نمونه Pinecone خود از طریق نمایه ایجاد شده قبلی استفاده خواهیم کرد. این شی به عنوان رابط ذخیره سازی و بازیابی برای جاسازی های سند ما در پایگاه داده برداری Pinecone عمل می کند.
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(
vector_store=vector_store
)
بعد، داده ها را از دایرکتوری به نام بارگیری می کنیم datastore
با استفاده از SimpleDirectoryReader
ماژول از LlamaIndex. سپس VectorStoreIndex را ایجاد کنید که فرآیند نمایه سازی و پرس و جو را کنترل می کند و از بسترهای ذخیره سازی و سرویس ارائه شده استفاده می کند.
documents = SimpleDirectoryReader("datastore").load_data()
vector_store_index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context
)
در نهایت می توانیم از ایندکسی که می سازیم یک موتور پرس و جو بسازیم و از این موتور برای انجام یک پرس و جو استفاده کنیم.
query = "What's the price of the Quesadillas at Crepawayre?"
query_engine = index.as_query_engine()
response = query_engine.query(query)
print(response)
این همان چیزی است که کد در کنار هم به نظر می رسد
import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key=os.getenv("PINECONE_API_KEY"))
index_name = "food-listing"
if index_name not in pc.list_indexes().names():
pc.create_index(
name=index_name,
dimension=1536,
metric="cosine",
spec=ServerlessSpec(
cloud="aws",
region="us-east-1"
)
)
pinecone_index = pc.Index(index_name)
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(
vector_store=vector_store
)
documents = SimpleDirectoryReader("datab").load_data()
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
query_engine = index.as_query_engine()
response = query_engine.query("What's the price of the Quesadillas at Crepawayre?")
print(response)
چگونه کار می کند
قبل از اجرای اسکریپت، بیایید نگاهی بیندازیم که دقیقاً قرار است چه اتفاقی بیفتد.
LlamaIndex جاسازیها را با استفاده از API تعبیهسازی OpenAI ایجاد میکند، با استفاده از نام ایندکس به نمونه Pinecone شما متصل میشود، آن جاسازیها را در Pinecone ذخیره میکند، متن مربوطه را، با توجه به پرس و جو، از فروشگاه جاسازی برداری بردار میکشد و در نهایت پرس و جو را (با متن) ارسال میکند. به LLM (در این مورد، OpenAI).
این اتفاقات زیادی است که در پشت صحنه اتفاق می افتد و ما ممکن است بخواهیم ببینیم که چگونه همه اینها انجام می شود، یعنی شکست فرآیندها. برای انجام این کار، ما به ابزاری نیاز داریم که این رویدادها را ضبط کند و به ما نشان دهد که هر یک از آنها چه چیزی را شامل می شود و اینجاست که Langtrace وارد می شود (قبلاً به نظارت اشاره کردم که نقش مهمی در اشکال زدایی دارد).
Langtrace یک پلت فرم مشاهده پذیر LLM است که به شما امکان می دهد عملکرد برنامه های کاربردی LLM را نظارت و ارزیابی کنید. این یکپارچه با اکثر LLM ها، چارچوب های LLM، پایگاه های داده برداری کار می کند.
افزودن Langtrace به یک پروژه ساده است زیرا برای اجرای آن فقط به ۲ خط کد نیاز دارد. ابتدا یک حساب کاربری در Langtrace ایجاد می کنیم، یک پروژه ایجاد می کنیم، سپس یک کلید API برای پروژه ایجاد می کنیم.
export LANGTRACE_API_KEY=<YOUR LANGTRACE API KEY>
Langtrace را به کد خود اضافه کنید (خط دوم و آخر زیر)
import os
from langtrace_python_sdk import langtrace # this line must precede all llm imports
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from pinecone import Pinecone, ServerlessSpec
langtrace.init(api_key=os.getenv("LANGTRACE_API_KEY"))
در نهایت کد را اجرا می کنیم تا ببینیم چه پاسخی دریافت می کنیم
python3 main.py
پاسخ به شرح زیر است:
The price of the Quesadillas at Crepawayre is 5100.
با نگاه کردن به داده ها می توانیم متوجه شویم که پاسخ دقیق بوده است
حالا بیایید نگاهی به داشبورد Langtrace خود بیندازیم تا همه چیزهایی که هنگام اجرای کد اتفاق افتاد را ببینیم.
ما میتوانیم ردیابیهایی را برای تعدادی از جاسازیهایی که ایجاد میشوند ببینیم و این به این دلیل است که LlamaIndex سند اولیه را به تکههایی تقسیم میکند و هر تکه را با استفاده از OpenAI به یک جاسازی تبدیل میکند. text-embedding-ada-002
مدل ما همچنین می توانیم ببینیم pinecone.index.upsert
اقدامی که به این صورت است که جاسازیها در Pinecon ذخیره میشوند.
با نگاهی به بیشترین ردیابی، می توانیم ببینیم که llamaindex.RetrieverQueryEngine.query
، که وقتی می دویم اتفاق می افتد query_engine.query("What's the price of the Quesadillas at Crepawayre?")
، سه عمل مختلف را اجرا می کند: پرس و جو را به جاسازی ها تبدیل می کند، از Pinecone پرس و جو می کند تا داده های مربوطه را بر اساس پرس و جو دریافت کند و در نهایت پرس و جو را به LLM (OpenAI) می فرستد. ما همچنین میتوانیم مدت زمان ردیابی و همچنین مدت زمان بازههای فردی را که آن ردیابی را تشکیل میدهند، ببینیم.
با این تفکیک، میتوانیم بیشتر برویم و با کلیک کردن روی آن نگاهی به آنچه در هر یک از این بازهها میافتد، داشته باشیم. بیایید پرس و جوی دقیق ارسال شده به OpenAI را ببینیم (ما انتظار داریم این مورد با زمینه مربوطه بر اساس پرس و جو اولیه تقویت شود What's the price of the Quesadillas at Crepawayre?
)
می بینیم که پرس و جو به لیستی از اقلام بازگشتی از جستجوی برداری الحاق می شود (در این مورد، تمام مواد غذایی با place_name
روی Crepawayre تنظیم کنید) و این همان چیزی است که به API تکمیل چت OpenAI ارسال می شود. با پرس و جو و زمینه مربوطه، OpenAI قادر است پاسخ صحیحی را ارائه دهد.
برای پرسوجوهای بعدی، چون جاسازیها قبلاً در Pinecone ذخیره شدهاند، تنها کاری که باید انجام دهیم این است که از ایندکس برای پرسوجویی از آن جاسازیها استفاده کنیم تا زمینه مربوطه را که برای پرسجویی از LLM نیاز داریم، به دست آوریم. همچنین این پرسوجوها بسیار سریعتر اجرا میشوند، زیرا فهرستسازی و درج جاسازیها در Pinecone فقط باید یک بار اتفاق بیفتد (به جز اینکه دادههای بیشتری اضافه میکنیم یا نمایه جدیدی ایجاد میکنیم).
pc = Pinecone(api_key=os.getenv("PINECONE_API_KEY"))
index_name = "food-listing-chatbot"
if index_name not in pc.list_indexes().names():
raise Exception("Index not found")
pinecone_index = pc.Index(index_name)
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
index = VectorStoreIndex.from_vector_store(vector_store=vector_store)
query_engine = index.as_query_engine()
response = query_engine.query("I'm craving something spicy, can you recommend something and where can I get it?")
print(response)
# You might enjoy the "CHICKEN / GOAT MEAT PEPPER SOUP," which is a spicy broth of chicken or goat meat. You can get it at Yellow Chilli in Ikeja.
نتیجه گیری
همانطور که LLM ها قدرتمند هستند، تا حدودی محدود به داده هایی هستند که روی آنها آموزش دیده اند. در حالی که LLM ها در پاسخ سریع به درخواست های عمومی بسیار مفید هستند، اغلب زمانی که کاربران به دنبال بررسی عمیق تر در موضوعات فعلی یا خاص تر هستند، کوتاهی می کنند. این محدودیت نیاز به Retrieval-Augmented Generation (RAG) را برجسته می کند که از داده های واکشی شده از منابع خارجی استفاده می کند. با ادغام RAG، میتوانیم قابلیتهای LLM را افزایش دهیم و پاسخهای دقیقتر و بهروزتری را به کاربران ارائه دهیم که متناسب با نیازهای خاص آنها باشد.
در این پست نحوه پیاده سازی یک سیستم استاندارد RAG با استفاده از LlamaIndex، Pinecone و OpenAI را توضیح دادیم. ما همچنین از Langtrace برای نظارت بر عملکرد هر یک از این اجزا و نحوه کار آنها با یکدیگر استفاده کردیم. همچنین، میتوانید مسیر دیگری را انتخاب کنید، مثلاً از یک LLM متفاوت مانند Anthropic به جای OpenAI یا یک پایگاه داده برداری متفاوت مانند Weaviate به جای Pinecone استفاده کنید. LlamaIndex، و همچنین Langtrace، دارای ادغام برای تعدادی از LLM ها، فریمورک ها و فروشگاه های برداری هستند که در نتیجه سفارشی سازی را یکپارچه می کند.
منابع مفید
- شروع کار با LlamaIndex https://docs.llamaindex.ai/en/stable/
- فروشگاههای وکتور LlamaIndex https://docs.llamaindex.ai/en/stable/module_guides/storing/vector_stores/
- شروع کار با Pinecone https://docs.pinecone.io/guides/get-started/quickstart
- شروع کار با Langtrace https://docs.langtrace.ai/introduction
- OpenAI https://platform.openai.com/docs/introduction