Artikel ini menyediakan panduan mendalam tentang cara membina sistem RAG multimodal menggunakan Milvus dan cara membuka pelbagai kemungkinan untuk sistem AI. Mengekang kepada satu format data adalah tidak cukup baik lagi. Memandangkan perniagaan lebih bergantung pada maklumat untuk membuat keputusan penting, mereka memerlukan keupayaan untuk membandingkan data dalam format yang berbeza. Nasib baik, sistem AI tradisional yang terhad kepada satu jenis data telah memberi laluan kepada sistem multimodal yang boleh memahami dan memproses maklumat yang kompleks. Sistem carian berbilang mod dan (RAG) baru-baru ini telah menunjukkan kemajuan hebat dalam bidang ini. Sistem ini memproses berbilang jenis data, termasuk teks, imej dan audio, untuk memberikan respons yang menyedari konteks. penjanaan tambahan perolehan berbilang mod Dalam catatan blog ini, kami akan membincangkan cara pembangun boleh membina sistem RAG multimodal mereka sendiri menggunakan Milvus. Kami juga akan membimbing anda membina sistem sedemikian yang boleh mengendalikan data teks dan imej, khususnya, melakukan carian persamaan dan memanfaatkan model bahasa untuk memperhalusi output. Jadi, mari kita mulakan. Apakah Milvus? Pangkalan data vektor ialah jenis pangkalan data khas yang digunakan untuk menyimpan, mengindeks dan mendapatkan semula benam vektor, yang merupakan perwakilan matematik data yang membolehkan anda membandingkan data bukan sahaja untuk kesetaraan tetapi kesamaan semantik. ialah pangkalan data vektor berprestasi tinggi sumber terbuka yang dibina untuk skala. Anda boleh menemuinya di GitHub dengan lesen Apache-2.0 dan lebih daripada 30K bintang. Milvus Milvus membantu pembangun menyediakan penyelesaian yang fleksibel untuk mengurus dan menanyakan data vektor berskala besar. Kecekapannya menjadikan Milvus sebagai pilihan ideal untuk pembangun membina aplikasi menggunakan model pembelajaran mendalam, seperti penjanaan tambahan perolehan (RAG), carian berbilang mod, enjin pengesyoran dan pengesanan anomali. Milvus menawarkan berbilang pilihan penggunaan untuk memadankan keperluan pembangun. ialah versi ringan yang berjalan di dalam aplikasi Python dan sesuai untuk aplikasi prototaip dalam persekitaran tempatan. Milvus Standalone dan Milvus Distributed ialah pilihan berskala dan sedia pengeluaran. Milvus Lite Multimodal RAG: Mengembangkan Melebihi Teks Sebelum membina sistem, adalah penting untuk memahami RAG berasaskan teks tradisional dan evolusinya kepada RAG Multimodal. (RAG) ialah kaedah untuk mendapatkan maklumat kontekstual daripada sumber luaran dan menjana output yang lebih tepat daripada model bahasa besar (LLM). RAG tradisional ialah strategi yang sangat berkesan untuk meningkatkan output LLM, tetapi tetap terhad kepada data teks. Dalam banyak aplikasi dunia nyata, data melangkaui teks—menggabungkan imej, carta dan modaliti lain menyediakan konteks kritikal. Retrieval Augmented Generation menangani had di atas dengan mendayakan penggunaan jenis data yang berbeza, memberikan konteks yang lebih baik kepada LLM. Multimodal RAG Ringkasnya, dalam sistem RAG berbilang mod, komponen perolehan mencari maklumat yang berkaitan merentas modaliti data yang berbeza, dan komponen penjanaan menjana hasil yang lebih tepat berdasarkan maklumat yang diambil. Memahami Pembenaman Vektor dan Carian Persamaan dan ialah dua konsep asas RAG multimodal. Mari kita fahami kedua-duanya. Pembenaman vektor carian persamaan Pembenaman Vektor Seperti yang dibincangkan, pembenaman vektor ialah perwakilan matematik/berangka data. Mesin menggunakan perwakilan ini untuk memahami makna semantik jenis data yang berbeza, seperti teks, imej dan audio. Apabila menggunakan pemprosesan bahasa semula jadi (NLP), ketulan dokumen diubah menjadi vektor, dan perkataan yang serupa secara semantik dipetakan ke titik berdekatan dalam ruang vektor. Perkara yang sama berlaku untuk imej, di mana pembenaman mewakili ciri semantik. Ini membolehkan kami memahami metrik seperti warna, tekstur dan bentuk objek dalam format berangka. Matlamat utama menggunakan benam vektor adalah untuk membantu mengekalkan hubungan dan persamaan antara kepingan data yang berbeza. Carian Persamaan Carian persamaan digunakan untuk mencari dan mencari data dalam set data tertentu. Dalam konteks pembenaman vektor, carian persamaan mencari vektor dalam set data yang diberikan yang paling hampir dengan vektor pertanyaan. Berikut adalah beberapa kaedah yang biasa digunakan untuk mengukur persamaan antara vektor: : Mengukur jarak garis lurus antara dua titik dalam ruang vektor. Jarak Euclidean : Mengukur kosinus sudut antara dua vektor (dengan fokus pada arahnya dan bukannya magnitud). Kesamaan Kosinus : Pendaraban mudah unsur sepadan yang disimpulkan. Produk Dot Pilihan ukuran persamaan biasanya bergantung pada data khusus aplikasi dan cara pembangun mendekati masalah tersebut. Apabila melakukan carian persamaan pada set data berskala besar, kuasa pengiraan dan sumber yang diperlukan adalah sangat tinggi. Di sinilah algoritma anggaran jiran terdekat (ANN) masuk. Algoritma ANN digunakan untuk menukar peratusan atau jumlah ketepatan yang kecil untuk peningkatan kelajuan yang ketara. Ini menjadikan mereka pilihan yang sesuai untuk aplikasi berskala besar. Milvus juga menggunakan algoritma ANN lanjutan, termasuk HNSW dan DiskANN, untuk melakukan carian persamaan yang cekap pada set data benam vektor yang besar, membolehkan pembangun mencari titik data yang berkaitan dengan cepat. Selain itu, Milvus menyokong algoritma pengindeksan lain, seperti HSNW, IVF, CAGRA, dll., menjadikannya penyelesaian carian vektor yang lebih cekap. Membina Multimodal RAG dengan Milvus Sekarang kita telah mempelajari konsep, tiba masanya untuk membina sistem RAG multimodal menggunakan Milvus. Untuk contoh ini, kami akan menggunakan Milvus Lite (versi Milvus yang ringan, sesuai untuk percubaan dan prototaip) untuk penyimpanan dan pengambilan vektor, BGE untuk pemprosesan dan pembenaman imej yang tepat dan GPT-4o untuk penyusunan semula hasil lanjutan. Prasyarat Pertama, anda memerlukan tika Milvus untuk menyimpan data anda. Anda boleh menyediakan Milvus Lite menggunakan pip, menjalankan instance tempatan menggunakan Docker, atau mendaftar untuk akaun Milvus dihoskan percuma melalui Zilliz Cloud. Kedua, anda memerlukan LLM untuk saluran paip RAG anda, jadi pergi ke dan dapatkan kunci API. Peringkat percuma sudah memadai untuk membolehkan kod ini berfungsi. OpenAI Seterusnya, buat direktori baharu dan Python (atau ambil apa sahaja langkah yang anda gunakan untuk mengurus Python). persekitaran maya Untuk tutorial ini, anda juga perlu memasang perpustakaan, yang merupakan SDK Python rasmi Milvus, dan beberapa alat biasa. pymilvus Sediakan Milvus Lite pip install -U pymilvus Pasang Ketergantungan 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 Muat Turun Data Perintah berikut akan memuat turun data contoh dan mengekstraknya ke folder tempatan "./images_folder", yang termasuk: Subset daripada mengandungi kira-kira 900 imej daripada kategori "Perkakas", "Telefon_selidik_dan_Aksesori", dan "Elektronik". Imej: Ulasan Amazon 2023 leopard.jpg Contoh imej pertanyaan: wget https://github.com/milvus-io/bootcamp/releases/download/data/amazon_reviews_2023_subset.tar.gz tar -xzf amazon_reviews_2023_subset.tar.gz Muatkan Model Benam Kami akan menggunakan model Visualized BGE "bge-visualized-base-en-v1.5" untuk menjana benam untuk kedua-dua imej dan teks. Sekarang muat turun berat dari HuggingFace. wget https://huggingface.co/BAAI/bge-visualized/resolve/main/Visualized_base_en_v1.5.pth Kemudian, mari kita bina pengekod. 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) Hasilkan Pembenaman dan Muatkan Data ke dalam Milvus Bahagian ini akan membimbing anda cara memuatkan imej contoh ke dalam pangkalan data kami dengan pembenamannya yang sepadan. Hasilkan benam Pertama, kita perlu membuat pembenaman untuk semua imej dalam set data. Muatkan semua imej daripada direktori data dan tukarkannya kepada pembenaman. 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)) Lakukan Carian Berbilang Modal dan Susun Semula Keputusan Dalam bahagian ini, kami mula-mula akan mencari imej yang berkaitan menggunakan pertanyaan multimodal dan kemudian menggunakan perkhidmatan LLM untuk menyusun semula hasil yang diperoleh dan mencari yang terbaik dengan penjelasan. Jalankan carian multimodal Kini kami bersedia untuk melakukan carian multimodal lanjutan dengan pertanyaan yang terdiri daripada arahan imej dan teks. 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) Hasilnya ditunjukkan di bawah: ['./images_folder/images/518Gj1WQ-RL._AC_.jpg', './images_folder/images/41n00AOfWhL._AC_.jpg' Susun semula keputusan dengan GPT-4o Sekarang, kami akan menggunakan GPT-4o untuk menentukan kedudukan imej yang diambil dan mencari hasil yang paling sepadan. LLM juga akan menerangkan mengapa kedudukannya seperti itu. 1. Cipta pemandangan panorama. 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. Gabungkan imej pertanyaan dan imej yang diambil dengan indeks dalam paparan panorama. 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. Susun semula keputusan dan berikan penjelasan Kami akan menghantar semua imej gabungan ke perkhidmatan LLM multimodal bersama-sama dengan gesaan yang betul untuk menentukan kedudukan keputusan yang diambil dengan penjelasan. Nota: Untuk mendayakan GPT-4o sebagai LLM, anda perlu menyediakan anda terlebih dahulu. Kunci API OpenAI 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 Dapatkan indeks imej selepas kedudukan dan sebab untuk hasil terbaik: ranked_indices, explanation = generate_ranking_explanation( combined_image_path, query_text ) 4. Paparkan hasil terbaik dengan penerangan 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() Keputusan: 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. Lihat kod penuh dalam . Untuk mengetahui lebih lanjut tentang cara memulakan demo dalam talian dengan tutorial ini, sila rujuk kepada . buku nota ini contoh aplikasi Kesimpulan Dalam catatan blog ini, kami membincangkan membina sistem RAG multimodal menggunakan (pangkalan data vektor sumber terbuka). Kami membincangkan cara pembangun boleh menyediakan Milvus, memuatkan data imej, melakukan carian persamaan dan menggunakan LLM untuk menyusun semula hasil yang diperoleh untuk respons yang lebih tepat. Milvus Penyelesaian RAG multimodal membuka pelbagai kemungkinan untuk sistem AI yang boleh memahami dan memproses pelbagai bentuk data dengan mudah. Beberapa kemungkinan biasa termasuk enjin carian imej yang dipertingkatkan, hasil terdorong konteks yang lebih baik dan banyak lagi.