این مقاله یک راهنمای عمیق در مورد نحوه ساخت یک سیستم RAG چند وجهی با استفاده از Milvus و نحوه باز کردن امکانات مختلف برای سیستمهای هوش مصنوعی ارائه میدهد.
محدود شدن به یک قالب داده دیگر به اندازه کافی خوب نیست. از آنجایی که کسبوکارها برای تصمیمگیریهای حیاتی به شدت به اطلاعات متکی هستند، به توانایی مقایسه دادهها در قالبهای متفاوت نیاز دارند. خوشبختانه، سیستمهای هوش مصنوعی سنتی که به یک نوع داده محدود شدهاند، جای خود را به سیستمهای چندوجهی دادهاند که میتوانند اطلاعات پیچیده را درک و پردازش کنند.
جستجوی چندوجهی و سیستمهای تولید افزوده بازیابی چندوجهی (RAG) اخیراً پیشرفتهای بزرگی را در این زمینه نشان دادهاند. این سیستمها انواع مختلفی از دادهها را پردازش میکنند، از جمله متن، تصویر و صدا، تا پاسخهای آگاه از زمینه را ارائه دهند.
در این پست وبلاگ، ما در مورد اینکه چگونه توسعه دهندگان می توانند سیستم RAG چندوجهی خود را با استفاده از Milvus بسازند، بحث خواهیم کرد. همچنین شما را در ساختن چنین سیستمی راهنمایی میکنیم که میتواند دادههای متن و تصویر را مدیریت کند، بهویژه، جستجوهای مشابه انجام دهد و از یک مدل زبان برای اصلاح خروجی استفاده کند. بنابراین، بیایید شروع کنیم.
پایگاه داده برداری نوع خاصی از پایگاه داده است که برای ذخیره، نمایه سازی و بازیابی جاسازی های برداری استفاده می شود، که نمایش های ریاضی داده ها هستند که به شما امکان می دهند داده ها را نه تنها برای هم ارزی بلکه شباهت معنایی مقایسه کنید.
Milvus به توسعه دهندگان کمک می کند تا راه حلی انعطاف پذیر برای مدیریت و جستجوی داده های برداری در مقیاس بزرگ ارائه دهند. کارایی آن، Milvus را به انتخابی ایدهآل برای توسعهدهندگانی تبدیل میکند که با استفاده از مدلهای یادگیری عمیق، برنامههایی مانند بازیابی نسل افزوده (RAG)، جستجوی چندوجهی، موتور توصیهها، و تشخیص ناهنجاریها را ایجاد میکنند.
Milvus چندین گزینه استقرار را برای مطابقت با نیازهای توسعه دهندگان ارائه می دهد.
قبل از ساختن سیستم، مهم است که RAG مبتنی بر متن سنتی و تکامل آن به RAG Multimodal را درک کنید.
Retrieval Augmented Generation (RAG) روشی برای بازیابی اطلاعات متنی از منابع خارجی و تولید خروجی دقیق تر از مدل های زبان بزرگ (LLMs) است. RAG سنتی یک استراتژی بسیار موثر برای بهبود خروجی LLM است، اما به داده های متنی محدود می شود. در بسیاری از برنامههای کاربردی دنیای واقعی، دادهها فراتر از متن گسترش مییابند – با ترکیب تصاویر، نمودارها و سایر روشها، زمینه حیاتی فراهم میشود.
RAG چندوجهی محدودیت فوق را با فعال کردن استفاده از انواع داده های مختلف برطرف می کند و زمینه بهتری را برای LLM ها فراهم می کند.
به بیان ساده، در یک سیستم RAG چندوجهی، جزء بازیابی اطلاعات مربوطه را در روشهای مختلف داده جستجو میکند و مؤلفه تولید نتایج دقیقتری را بر اساس اطلاعات بازیابی شده ایجاد میکند.
تعبیههای برداری و جستجوی شباهت دو مفهوم اساسی RAG چندوجهی هستند. بیایید هر دو را درک کنیم.
همانطور که بحث شد، جاسازی های برداری نمایش ریاضی/عددی داده ها هستند. ماشینها از این نمایش برای درک معنای معنایی انواع دادههای مختلف مانند متن، تصویر و صدا استفاده میکنند.
هنگام استفاده از پردازش زبان طبیعی (NLP)، تکههای سند به بردار تبدیل میشوند و کلمات مشابه از نظر معنایی به نقاط نزدیک در فضای برداری نگاشت میشوند. همین امر در مورد تصاویر نیز صدق میکند، جایی که تعبیهها نمایانگر ویژگیهای معنایی هستند. این به ما امکان می دهد معیارهایی مانند رنگ، بافت و اشکال اشیا را در قالب عددی درک کنیم.
هدف اصلی استفاده از تعبیههای برداری کمک به حفظ روابط و شباهتها بین قطعات مختلف داده است.
جستجوی شباهت برای یافتن و مکان یابی داده ها در یک مجموعه داده معین استفاده می شود. در زمینه جاسازی های برداری، جستجوی شباهت بردارهایی را در مجموعه داده داده شده پیدا می کند که نزدیک ترین به بردار پرس و جو هستند.
در زیر چند روش است که معمولاً برای اندازه گیری شباهت بین بردارها استفاده می شود:
انتخاب معیار تشابه معمولاً به داده های خاص برنامه و نحوه برخورد توسعه دهنده با مشکل بستگی دارد.
هنگام انجام جستجوی شباهت در مجموعه داده های بزرگ مقیاس، قدرت محاسباتی و منابع مورد نیاز بسیار بالا است. اینجاست که الگوریتمهای تقریبی نزدیکترین همسایه (ANN) وارد میشوند. الگوریتمهای ANN برای مبادله درصد یا مقدار کمی از دقت برای ارتقاء سرعت قابل توجه استفاده میشوند. این باعث می شود که آنها انتخابی مناسب برای کاربردهای در مقیاس بزرگ باشند.
Milvus همچنین از الگوریتمهای ANN پیشرفته، از جمله HNSW و DiskANN، برای انجام جستجوهای شباهت کارآمد در مجموعه دادههای بزرگ تعبیهشده بردار استفاده میکند و به توسعهدهندگان اجازه میدهد تا به سرعت نقاط داده مرتبط را پیدا کنند. علاوه بر این، Milvus از سایر الگوریتمهای نمایهسازی مانند HSNW، IVF، CAGRA و غیره پشتیبانی میکند و آن را به یک راهحل جستجوی برداری بسیار کارآمدتر تبدیل میکند.
حالا ما مفاهیم را یاد گرفتیم، زمان ساخت یک سیستم RAG چند وجهی با استفاده از Milvus است. برای این مثال، ما از Milvus Lite (نسخه سبک Milvus، ایده آل برای آزمایش و نمونه سازی) برای ذخیره و بازیابی برداری، BGE برای پردازش و جاسازی دقیق تصویر، و GPT-4o برای رتبه بندی مجدد نتایج پیشرفته استفاده می کنیم.
ابتدا برای ذخیره داده های خود به یک نمونه Milvus نیاز دارید. میتوانید Milvus Lite را با استفاده از pip راهاندازی کنید، یک نمونه محلی را با استفاده از Docker اجرا کنید، یا برای یک حساب میزبانی رایگان Milvus از طریق Zilliz Cloud ثبتنام کنید.
دوم، شما به یک LLM برای خط لوله RAG خود نیاز دارید، بنابراین به آن سر بزنید
سپس یک دایرکتوری جدید و یک پایتون ایجاد کنید
برای این آموزش، شما همچنین باید نصب کنید
pip install -U pymilvus
pip install --upgrade pymilvus openai datasets opencv-python timm einops ftfy peft tqdm git clone https://github.com/FlagOpen/FlagEmbedding.git pip install -e FlagEmbedding
دستور زیر داده های نمونه را دانلود کرده و آن را در یک پوشه محلی "./images_folder" استخراج می کند که شامل:
wget https://github.com/milvus-io/bootcamp/releases/download/data/amazon_reviews_2023_subset.tar.gz tar -xzf amazon_reviews_2023_subset.tar.gz
ما از مدل Visualized BGE "bge-visualized-base-en-v1.5" برای ایجاد جاسازی برای تصاویر و متن استفاده خواهیم کرد.
اکنون وزنه را از HuggingFace دانلود کنید.
wget https://huggingface.co/BAAI/bge-visualized/resolve/main/Visualized_base_en_v1.5.pth
سپس، بیایید یک رمزگذار بسازیم.
import torch from visual_bge.modeling import Visualized_BGE class Encoder: def __init__(self, model_name: str, model_path: str): self.model = Visualized_BGE(model_name_bge=model_name, model_weight=model_path) self.model.eval() def encode_query(self, image_path: str, text: str) -> list[float]: with torch.no_grad(): query_emb = self.model.encode(image=image_path, text=text) return query_emb.tolist()[0] def encode_image(self, image_path: str) -> list[float]: with torch.no_grad(): query_emb = self.model.encode(image=image_path) return query_emb.tolist()[0] model_name = "BAAI/bge-base-en-v1.5" model_path = "./Visualized_base_en_v1.5.pth" # Change to your own value if using a different model path encoder = Encoder(model_name, model_path)
این بخش شما را راهنمایی می کند که چگونه تصاویر نمونه را با جاسازی های مربوطه در پایگاه داده ما بارگذاری کنید.
جاسازی ها را ایجاد کنید
ابتدا باید برای همه تصاویر موجود در مجموعه داده جاسازی ایجاد کنیم.
همه تصاویر را از دایرکتوری داده بارگیری کنید و آنها را به جاسازی تبدیل کنید.
import os from tqdm import tqdm from glob import glob data_dir = ( "./images_folder" # Change to your own value if using a different data directory ) image_list = glob( os.path.join(data_dir, "images", "*.jpg") ) # We will only use images ending with ".jpg" image_dict = {} for image_path in tqdm(image_list, desc="Generating image embeddings: "): try: image_dict[image_path] = encoder.encode_image(image_path) except Exception as e: print(f"Failed to generate embedding for {image_path}. Skipped.") continue print("Number of encoded images:", len(image_dict))
در این بخش ابتدا تصاویر مربوطه را با استفاده از یک پرس و جو چند وجهی جستجو می کنیم و سپس از سرویس LLM برای رتبه بندی مجدد نتایج بازیابی شده و یافتن بهترین آنها با توضیح استفاده می کنیم.
جستجوی چندوجهی را اجرا کنید
اکنون ما آماده انجام جستجوی چندوجهی پیشرفته با پرس و جوی متشکل از دستورالعمل های تصویری و متنی هستیم.
query_image = os.path.join( data_dir, "leopard.jpg" ) # Change to your own query image path query_text = "phone case with this image theme" query_vec = encoder.encode_query(image_path=query_image, text=query_text) search_results = milvus_client.search( collection_name=collection_name, data=[query_vec], output_fields=["image_path"], limit=9, # Max number of search results to return search_params={"metric_type": "COSINE", "params": {}}, # Search parameters )[0] retrieved_images = [hit.get("entity").get("image_path") for hit in search_results] print(retrieved_images)
نتیجه در زیر نشان داده شده است:
['./images_folder/images/518Gj1WQ-RL._AC_.jpg', './images_folder/images/41n00AOfWhL._AC_.jpg'
رتبه بندی مجدد نتایج با GPT-4o
اکنون از GPT-4o برای رتبه بندی تصاویر بازیابی شده و یافتن بهترین نتایج منطبق استفاده خواهیم کرد. LLM همچنین توضیح خواهد داد که چرا این رتبه بندی را انجام می دهد.
1. یک نمای پانوراما ایجاد کنید.
import numpy as np import cv2 img_height = 300 img_width = 300 row_count = 3 def create_panoramic_view(query_image_path: str, retrieved_images: list) -> np.ndarray: """ creates a 5x5 panoramic view image from a list of images args: images: list of images to be combined returns: np.ndarray: the panoramic view image """ panoramic_width = img_width * row_count panoramic_height = img_height * row_count panoramic_image = np.full( (panoramic_height, panoramic_width, 3), 255, dtype=np.uint8 ) # create and resize the query image with a blue border query_image_null = np.full((panoramic_height, img_width, 3), 255, dtype=np.uint8) query_image = Image.open(query_image_path).convert("RGB") query_array = np.array(query_image)[:, :, ::-1] resized_image = cv2.resize(query_array, (img_width, img_height)) border_size = 10 blue = (255, 0, 0) # blue color in BGR bordered_query_image = cv2.copyMakeBorder( resized_image, border_size, border_size, border_size, border_size, cv2.BORDER_CONSTANT, value=blue, ) query_image_null[img_height * 2 : img_height * 3, 0:img_width] = cv2.resize( bordered_query_image, (img_width, img_height) ) # add text "query" below the query image text = "query" font_scale = 1 font_thickness = 2 text_org = (10, img_height * 3 + 30) cv2.putText( query_image_null, text, text_org, cv2.FONT_HERSHEY_SIMPLEX, font_scale, blue, font_thickness, cv2.LINE_AA, ) # combine the rest of the images into the panoramic view retrieved_imgs = [ np.array(Image.open(img).convert("RGB"))[:, :, ::-1] for img in retrieved_images ] for i, image in enumerate(retrieved_imgs): image = cv2.resize(image, (img_width - 4, img_height - 4)) row = i // row_count col = i % row_count start_row = row * img_height start_col = col * img_width border_size = 2 bordered_image = cv2.copyMakeBorder( image, border_size, border_size, border_size, border_size, cv2.BORDER_CONSTANT, value=(0, 0, 0), ) panoramic_image[ start_row : start_row + img_height, start_col : start_col + img_width ] = bordered_image # add red index numbers to each image text = str(i) org = (start_col + 50, start_row + 30) (font_width, font_height), baseline = cv2.getTextSize( text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2 ) top_left = (org[0] - 48, start_row + 2) bottom_right = (org[0] - 48 + font_width + 5, org[1] + baseline + 5) cv2.rectangle( panoramic_image, top_left, bottom_right, (255, 255, 255), cv2.FILLED ) cv2.putText( panoramic_image, text, (start_col + 10, start_row + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA, ) # combine the query image with the panoramic view panoramic_image = np.hstack([query_image_null, panoramic_image]) return panoramic_image
2. تصویر پرس و جو و تصاویر بازیابی شده را با شاخص ها در نمای پانوراما ترکیب کنید.
from PIL import Image combined_image_path = os.path.join(data_dir, "combined_image.jpg") panoramic_image = create_panoramic_view(query_image, retrieved_images) cv2.imwrite(combined_image_path, panoramic_image) combined_image = Image.open(combined_image_path) show_combined_image = combined_image.resize((300, 300)) show_combined_image.show()
3. نتایج را دوباره رتبه بندی کنید و توضیح دهید
ما تمام تصاویر ترکیبی را همراه با اعلان های مناسب برای رتبه بندی نتایج بازیابی شده با توضیح به سرویس چندوجهی LLM ارسال می کنیم. توجه: برای فعال کردن GPT-4o به عنوان LLM، باید خود را آماده کنید
import requests import base64 openai_api_key = "sk-***" # Change to your OpenAI API Key def generate_ranking_explanation( combined_image_path: str, caption: str, infos: dict = None ) -> tuple[list[int], str]: with open(combined_image_path, "rb") as image_file: base64_image = base64.b64encode(image_file.read()).decode("utf-8") information = ( "You are responsible for ranking results for a Composed Image Retrieval. " "The user retrieves an image with an 'instruction' indicating their retrieval intent. " "For example, if the user queries a red car with the instruction 'change this car to blue,' a similar type of car in blue would be ranked higher in the results. " "Now you would receive instruction and query image with blue border. Every item has its red index number in its top left. Do not misunderstand it. " f"User instruction: {caption} \n\n" ) # add additional information for each image if infos: for i, info in enumerate(infos["product"]): information += f"{i}. {info}\n" information += ( "Provide a new ranked list of indices from most suitable to least suitable, followed by an explanation for the top 1 most suitable item only. " "The format of the response has to be 'Ranked list: []' with the indices in brackets as integers, followed by 'Reasons:' plus the explanation why this most fit user's query intent." ) headers = { "Content-Type": "application/json", "Authorization": f"Bearer {openai_api_key}", } payload = { "model": "gpt-4o", "messages": [ { "role": "user", "content": [ {"type": "text", "text": information}, { "type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}, }, ], } ], "max_tokens": 300, } response = requests.post( "https://api.openai.com/v1/chat/completions", headers=headers, json=payload ) result = response.json()["choices"][0]["message"]["content"] # parse the ranked indices from the response start_idx = result.find("[") end_idx = result.find("]") ranked_indices_str = result[start_idx + 1 : end_idx].split(",") ranked_indices = [int(index.strip()) for index in ranked_indices_str] # extract explanation explanation = result[end_idx + 1 :].strip() return ranked_indices, explanation
شاخص های تصویر را پس از رتبه بندی و دلیل بهترین نتیجه دریافت کنید:
ranked_indices, explanation = generate_ranking_explanation( combined_image_path, query_text )
4. بهترین نتیجه را با توضیح نمایش دهید
print(explanation) best_index = ranked_indices[0] best_img = Image.open(retrieved_images[best_index]) best_img = best_img.resize((150, 150)) best_img.show()
نتایج:
Reasons: The most suitable item for the user's query intent is index 6 because the instruction specifies a phone case with the theme of the image, which is a leopard. The phone case with index 6 has a thematic design resembling the leopard pattern, making it the closest match to the user's request for a phone case with the image theme.
کد کامل را در این نوت بوک بررسی کنید. برای کسب اطلاعات بیشتر در مورد نحوه شروع یک نسخه نمایشی آنلاین با این آموزش، لطفاً به ادامه مطلب مراجعه کنید
در این پست وبلاگ، درباره ساختن یک سیستم RAG چندوجهی با استفاده از آن بحث کردیم
راهحلهای RAG چندوجهی، امکانات مختلفی را برای سیستمهای هوش مصنوعی باز میکنند که به راحتی میتوانند اشکال مختلف داده را درک و پردازش کنند. برخی از احتمالات رایج عبارتند از موتورهای جستجوی تصویر بهبود یافته، نتایج بهتر مبتنی بر زمینه، و موارد دیگر.