Энэ нийтлэлд Milvus ашиглан олон төрлийн RAG системийг хэрхэн бүтээх, AI системүүдийн янз бүрийн боломжуудыг хэрхэн нээх талаар гүнзгий гарын авлага өгдөг.
Ганц өгөгдлийн форматаар хязгаарлагдах нь хангалттай сайн биш болсон. Бизнесүүд чухал шийдвэр гаргахдаа мэдээлэлд илүү найддаг тул өөр өөр форматтай өгөгдлийг харьцуулах чадвартай байх шаардлагатай. Аз болоход, нэг өгөгдлийн төрлөөр хязгаарлагддаг уламжлалт хиймэл оюун ухааны системүүд нь нарийн төвөгтэй мэдээллийг ойлгож, боловсруулж чаддаг мультимодаль системд байр сууриа өгсөн.
Мультимодал хайлт болон олон төрлийн хайлтыг нэмэгдүүлэх (RAG) системүүд саяхан энэ салбарт томоохон дэвшлийг харуулсан. Эдгээр системүүд нь текст, зураг, аудио зэрэг олон төрлийн өгөгдлийг боловсруулдаг бөгөөд контекстийг мэддэг хариултуудыг өгдөг.
Энэ блог нийтлэлд бид хөгжүүлэгчид Milvus ашиглан өөрсдийн multimodal RAG системийг хэрхэн бүтээх талаар ярилцах болно. Мөн бид танд текст болон зургийн өгөгдөл, ялангуяа ижил төстэй байдлын хайлт хийх, гаралтыг сайжруулахын тулд хэлний загварыг ашиглах боломжтой ийм системийг бий болгоход туслах болно. За ингээд эхэлцгээе.
Вектор мэдээллийн сан нь зөвхөн эквивалент төдийгүй утгын ижил төстэй байдлын үүднээс өгөгдлийг харьцуулах боломжийг олгодог өгөгдлийн математик дүрслэл болох вектор оруулгыг хадгалах, индексжүүлэх, сэргээхэд ашигладаг тусгай төрлийн мэдээллийн сан юм.
Milvus нь хөгжүүлэгчдэд том хэмжээний вектор өгөгдлийг удирдах, асуух уян хатан шийдлээр хангахад тусалдаг. Үүний үр ашиг нь Milvus-ийг сэргээх өргөтгөсөн үүсгүүр (RAG), олон төрлийн хайлт, зөвлөмжийн систем, гажиг илрүүлэх зэрэг гүнзгий суралцах загваруудыг ашиглан програм бүтээх хөгжүүлэгчдэд хамгийн тохиромжтой сонголт болгодог.
Milvus нь хөгжүүлэгчдийн хэрэгцээнд нийцүүлэн байршуулах олон сонголтыг санал болгодог.
Системийг бүтээхээс өмнө уламжлалт текстэд суурилсан RAG болон түүний Мультимодал RAG болж хувирах хувьслыг ойлгох нь чухал юм.
Retrieval Augmented Generation (RAG) нь гадны эх сурвалжаас контекст мэдээлэл авах, том хэлний загвараас (LLM) илүү нарийвчлалтай гаралтыг бий болгох арга юм. Уламжлалт RAG нь LLM-ийн гаралтыг сайжруулах өндөр үр дүнтэй стратеги боловч текстийн өгөгдөлд хязгаарлагдмал хэвээр байна. Бодит хэрэглээний олон программд өгөгдөл нь текстээс давж гардаг бөгөөд зураг, диаграм болон бусад аргуудыг агуулсан байх нь чухал нөхцөл байдлыг хангадаг.
Multimodal RAG нь дээрх хязгаарлалтыг өөр өөр төрлийн өгөгдлийн хэрэглээг идэвхжүүлж, LLM-д илүү сайн контекстээр хангадаг.
Энгийнээр хэлбэл, мультимодаль RAG системд хайлт хийх бүрэлдэхүүн хэсэг нь өөр өөр өгөгдлийн горимд холбогдох мэдээллийг хайж олох ба үүсгэх бүрэлдэхүүн хэсэг нь олж авсан мэдээлэлд үндэслэн илүү нарийвчлалтай үр дүнг бий болгодог.
Вектор оруулах ба ижил төстэй байдлын хайлт нь мультимодал RAG-ийн үндсэн хоёр ойлголт юм. Хоёуланг нь ойлгоцгооё.
Өмнө дурьдсанчлан вектор оршуулга нь өгөгдлийн математик/тоон дүрслэл юм. Машинууд энэ дүрслэлийг текст, зураг, аудио гэх мэт өөр өөр төрлийн өгөгдлийн утгыг ойлгоход ашигладаг.
Байгалийн хэлний боловсруулалтыг (NLP) ашиглах үед баримт бичгийн хэсгүүдийг вектор болгон хувиргаж, утгын хувьд ижил төстэй үгсийг вектор орон зайн ойролцоох цэгүүдэд буулгадаг. Суулгац нь семантик шинж чанарыг илэрхийлдэг зургуудын хувьд мөн адил юм. Энэ нь өнгө, бүтэц, объектын хэлбэр зэрэг хэмжигдэхүүнийг тоон форматаар ойлгох боломжийг бидэнд олгодог.
Вектор суулгацыг ашиглах гол зорилго нь янз бүрийн өгөгдлийн хэсгүүдийн хоорондын харилцаа, ижил төстэй байдлыг хадгалахад туслах явдал юм.
Ижил төстэй байдлын хайлт нь өгөгдсөн өгөгдлийн багц дахь өгөгдлийг хайж олоход ашиглагддаг. Вектор оруулах контекстэд ижил төстэй байдлын хайлт нь өгөгдсөн өгөгдлийн багцаас асуулгын вектортой хамгийн ойр байгаа векторуудыг олдог.
Дараахь нь векторуудын ижил төстэй байдлыг хэмжихэд түгээмэл хэрэглэгддэг хэд хэдэн аргууд юм.
Ижил төстэй байдлын хэмжүүрийг сонгох нь ихэвчлэн програмын тусгай өгөгдөл болон хөгжүүлэгчид асуудалд хэрхэн хандаж байгаагаас хамаарна.
Том хэмжээний өгөгдлийн багц дээр ижил төстэй байдлын хайлт хийх үед тооцоолох хүч, шаардлагатай нөөц маш өндөр байдаг. Эндээс хамгийн ойрын хөршийн (ANN) алгоритмууд орж ирдэг. ANN алгоритмууд нь хурдыг мэдэгдэхүйц сайжруулахын тулд бага хувь эсвэл хэмжээний нарийвчлалыг арилжаалахад ашиглагддаг. Энэ нь тэдгээрийг том хэмжээний хэрэглээнд тохиромжтой сонголт болгодог.
Milvus нь мөн HNSW болон DiskANN зэрэг дэвшилтэт ANN алгоритмуудыг ашигладаг бөгөөд том вектор оруулах өгөгдлийн багц дээр ижил төстэй байдлын үр дүнтэй хайлт хийж, хөгжүүлэгчдэд холбогдох өгөгдлийн цэгүүдийг хурдан олох боломжийг олгодог. Нэмж дурдахад Milvus нь HSNW, IVF, CAGRA гэх мэт бусад индексжүүлэх алгоритмуудыг дэмждэг бөгөөд энэ нь илүү үр дүнтэй вектор хайлтын шийдэл болгодог.
Одоо бид ойлголтуудыг сурсан тул Milvus ашиглан олон төрлийн RAG системийг бүтээх цаг болжээ. Энэ жишээнд бид Milvus Lite (Милвусын хөнгөн хувилбар, туршилт хийх, загвар гаргахад нэн тохиромжтой) векторыг хадгалах, хайхад, BGE-г зураг боловсруулах, оруулахад, GPT-4o-г ахисан түвшний үр дүнг дахин эрэмбэлэхэд ашиглах болно.
Эхлээд та мэдээллээ хадгалахын тулд Milvus instance хэрэгтэй болно. Та Milvus Lite-г pip ашиглан тохируулах, Docker ашиглан локал жишээ ажиллуулах эсвэл Zilliz Cloud-ээр дамжуулан үнэгүй зохион байгуулсан Milvus дансанд бүртгүүлэх боломжтой.
Хоёрдугаарт, танд RAG дамжуулах хоолойд LLM хэрэгтэй тул түүн рүү очоорой
Дараа нь шинэ лавлах болон Python үүсгэ
Энэ зааварчилгааны хувьд та мөн суулгах хэрэгтэй болно
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))
Энэ хэсэгт бид эхлээд multimodal асуулга ашиглан холбогдох зургуудыг хайж, дараа нь LLM үйлчилгээг ашиглан олж авсан илэрцүүдийг дахин эрэмбэлж, тайлбар бүхий хамгийн сайныг нь олох болно.
Multimodal хайлтыг ажиллуул
Одоо бид зураг болон текстийн заавраас бүрдсэн хайлтыг ашиглан дэвшилтэт мультимодаль хайлт хийхэд бэлэн боллоо.
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. Үр дүнг дахин эрэмбэлж, тайлбар өгнө үү
Бид бүх нийлмэл зургийг multimodal 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 шийдлүүд нь олон хэлбэрийн өгөгдлийг хялбархан ойлгож, боловсруулах боломжтой хиймэл оюун ухааны системд янз бүрийн боломжийг нээж өгдөг. Зарим нийтлэг боломжууд нь сайжруулсан зургийн хайлтын систем, илүү сайн контекст тулгуурласан үр дүн гэх мэт.