Milvus
Zilliz
  • Home
  • Blog
  • Membuka Kunci Pengambilan Tingkat Entitas yang Sebenarnya: Kemampuan Array-of-Structs dan MAX_SIM yang baru di Milvus

Membuka Kunci Pengambilan Tingkat Entitas yang Sebenarnya: Kemampuan Array-of-Structs dan MAX_SIM yang baru di Milvus

  • Engineering
December 05, 2025
Jeremy Zhu, Min Tian

Jika Anda telah membangun aplikasi AI di atas basis data vektor, Anda mungkin mengalami masalah yang sama: basis data mengambil penyematan potongan-potongan individu, tetapi aplikasi Anda peduli dengan entitas. Ketidaksesuaian ini membuat seluruh alur kerja pengambilan menjadi rumit.

Anda mungkin telah melihat hal ini berulang kali:

  • Basis pengetahuan RAG: Artikel dipotong-potong menjadi beberapa paragraf, sehingga mesin pencari mengembalikan potongan-potongan yang tersebar, bukan dokumen lengkap.

  • Rekomendasi e-commerce: Sebuah produk memiliki beberapa penyematan gambar, dan sistem Anda mengembalikan lima sudut pandang dari item yang sama, bukan lima produk unik.

  • Platform video: Video dipecah menjadi penyematan klip, tetapi hasil penelusuran menampilkan potongan-potongan video yang sama, bukan satu entri yang terkonsolidasi.

  • Pengambilan gaya ColBERT / ColPali: Dokumen meluas menjadi ratusan penyematan token atau patch-level, dan hasil pencarian Anda kembali sebagai potongan-potongan kecil yang masih perlu digabungkan.

Semua masalah ini berasal dari kesenjangan arsitektur yang sama: sebagian besar basis data vektor memperlakukan setiap penyematan sebagai baris yang terisolasi, sementara aplikasi nyata beroperasi pada entitas tingkat yang lebih tinggi - dokumen, produk, video, item, adegan. Akibatnya, tim teknik dipaksa untuk merekonstruksi entitas secara manual menggunakan logika deduplikasi, pengelompokan, bucketing, dan pemeringkatan ulang. Cara ini berhasil, tetapi rapuh, lambat, dan membebani lapisan aplikasi Anda dengan logika yang seharusnya tidak pernah ada di sana.

Milvus 2.6.4 menutup celah ini dengan fitur baru: Array of Structs dengan tipe metrik MAX_SIM. Bersama-sama, keduanya memungkinkan semua penyematan untuk satu entitas disimpan dalam satu catatan dan memungkinkan Milvus untuk menilai dan mengembalikan entitas secara holistik. Tidak ada lagi set hasil yang diisi dengan duplikat. Tidak ada lagi post-processing yang rumit seperti pemeringkatan ulang dan penggabungan

Pada artikel ini, kita akan membahas cara kerja Array of Structs dan MAX_SIM-dan mendemonstrasikannya melalui dua contoh nyata: Pengambilan dokumen Wikipedia dan pencarian dokumen berbasis gambar ColPali.

Apa yang dimaksud dengan Array of Structs?

Dalam Milvus, sebuah bidang Array of Structs memungkinkan sebuah catatan tunggal untuk berisi daftar elemen Struct yang terurut, masing-masing mengikuti skema yang sudah ditentukan sebelumnya. Sebuah Struct dapat menampung beberapa vektor serta bidang skalar, string, atau jenis lain yang didukung. Dengan kata lain, struktur ini memungkinkan Anda menggabungkan semua bagian yang termasuk dalam satu entitas-penyematan paragraf, tampilan gambar, vektor token, metadata-langsung di dalam satu baris.

Berikut ini contoh entitas dari koleksi yang berisi bidang Array of Structs.

{
    'id': 0,
    'title': 'Walden',
    'title_vector': [0.1, 0.2, 0.3, 0.4, 0.5],
    'author': 'Henry David Thoreau',
    'year_of_publication': 1845,
    // highlight-start
    'chunks': [
        {
            'text': 'When I wrote the following pages, or rather the bulk of them...',
            'text_vector': [0.3, 0.2, 0.3, 0.2, 0.5],
            'chapter': 'Economy',
        },
        {
            'text': 'I would fain say something, not so much concerning the Chinese and...',
            'text_vector': [0.7, 0.4, 0.2, 0.7, 0.8],
            'chapter': 'Economy'
        }
    ]
    // hightlight-end
}

Pada contoh di atas, bidang chunks adalah bidang Array of Structs, dan setiap elemen Struct berisi bidangnya sendiri, yaitu text, text_vector, dan chapter.

Pendekatan ini memecahkan masalah pemodelan yang sudah lama ada dalam database vektor. Secara tradisional, setiap penyematan atau atribut harus menjadi barisnya sendiri, yang memaksa entitas multi-vektor (dokumen, produk, video) untuk dipecah menjadi puluhan, ratusan, atau bahkan ribuan record. Dengan Array of Structs, Milvus memungkinkan Anda menyimpan seluruh entitas multi-vektor dalam satu bidang, sehingga cocok untuk daftar paragraf, penyematan token, urutan klip, gambar multi-tampilan, atau skenario apa pun di mana satu item logis terdiri dari banyak vektor.

Bagaimana Cara Kerja Larik Struktur dengan MAX_SIM?

Di atas larik struktur struktur baru ini terdapat MAX_SIM, sebuah strategi penilaian baru yang membuat pengambilan semantik menjadi sadar akan entitas. Ketika sebuah kueri masuk, Milvus membandingkannya dengan setiap vektor di dalam setiap larik struktur dan mengambil kemiripan maksimum sebagai skor akhir entitas. Entitas tersebut kemudian diberi peringkat - dan dikembalikan - berdasarkan skor tunggal tersebut. Hal ini menghindari masalah vektor-database klasik dalam mengambil fragmen-fragmen yang tersebar dan mendorong beban pengelompokan, deduping, dan pemeringkatan ulang ke dalam lapisan aplikasi. Dengan MAX_SIM, pengambilan tingkat entitas menjadi built-in, konsisten, dan efisien.

Untuk memahami cara kerja MAX_SIM dalam praktiknya, mari kita lihat contoh konkretnya.

Catatan: Semua vektor dalam contoh ini dihasilkan oleh model penyematan yang sama, dan kemiripan diukur dengan kemiripan kosinus dalam rentang [0,1].

Misalkan seorang pengguna mencari "Kursus Pemula Pembelajaran Mesin."

Kueri tersebut di-token menjadi tiga token:

  • Pembelajaran mesin

  • pemula

  • kursus

Masing-masing token ini kemudian diubah menjadi vektor penyematan dengan model penyematan yang sama dengan yang digunakan untuk dokumen.

Sekarang, bayangkan basis data vektor berisi dua dokumen:

  • doc_1: Panduan Pengenalan Jaringan Syaraf Tiruan dengan Python

  • doc_2: Panduan Tingkat Lanjut untuk Membaca Makalah LLM

Kedua dokumen tersebut telah dimasukkan ke dalam vektor dan disimpan di dalam Array of Structs.

Langkah 1: Hitung MAX_SIM untuk doc_1

Untuk setiap vektor kueri, Milvus menghitung kemiripan kosinus terhadap setiap vektor dalam doc_1:

Pengantarpanduanjaringan syaraf tiruan dalampython
pembelajaran mesin0.00.00.90.3
pemula0.80.10.00.3
kursus0.30.70.10.1

Untuk setiap vektor kueri, MAX_SIM memilih kemiripan tertinggi dari barisnya:

  • pembelajaran mesin → jaringan syaraf tiruan dalam (0.9)

  • pemula → pengenalan (0.8)

  • kursus → panduan (0,7)

Menjumlahkan kecocokan terbaik memberikan skor MAX_SIM sebesar 2,4 kepada doc_1.

Langkah 2: Menghitung MAX_SIM untuk doc_2

Sekarang kita ulangi proses ini untuk doc_2:

lanjutanpanduanLLMkertasmembaca
pembelajaran mesin0.10.20.90.30.1
pemula0.40.60.00.20.5
kursus saja.0.50.80.10.40.7

Match (kecocokan) terbaik untuk doc_2 adalah:

  • "pembelajaran mesin" → "LLM" (0.9)

  • "pemula" → "panduan" (0.6)

  • "kursus" → "panduan" (0.8)

Menjumlahkan keduanya akan memberikan skor MAX_SIM doc_2 sebesar 2,3.

Langkah 3: Bandingkan Skor

Karena 2.4 > 2.3, doc_1 memiliki peringkat yang lebih tinggi daripada doc_2, yang secara intuitif masuk akal, karena doc_1 lebih dekat dengan panduan pembelajaran mesin.

Dari contoh ini, kita dapat menyoroti tiga karakteristik inti dari MAX_SIM:

  • Semantik terlebih dahulu, bukan berbasis kata kunci: MAX_SIM membandingkan sematan, bukan literal teks. Meskipun "pembelajaran mesin" dan "jaringan syaraf tiruan" tidak memiliki kata yang tumpang tindih, kemiripan semantiknya adalah 0,9. Hal ini membuat MAX_SIM kuat terhadap sinonim, parafrase, tumpang tindih konseptual, dan beban kerja yang kaya akan penyematan modern.

  • Tidak sensitif terhadap panjang dan urutan: MAX_SIM tidak mengharuskan kueri dan dokumen memiliki jumlah vektor yang sama (misalnya, doc_1 memiliki 4 vektor sementara doc_2 memiliki 5 vektor, dan keduanya berfungsi dengan baik). MAX_SIM juga mengabaikan urutan vektor - "pemula" yang muncul lebih awal dalam kueri dan "pendahuluan" yang muncul kemudian dalam dokumen tidak berdampak pada skor.

  • Setiap vektor kueri penting: MAX_SIM mengambil kecocokan terbaik untuk setiap vektor kueri dan menjumlahkan skor terbaik tersebut. Hal ini mencegah vektor yang tidak cocok untuk mempengaruhi hasil dan memastikan bahwa setiap token kueri yang penting berkontribusi pada skor akhir. Sebagai contoh, kecocokan berkualitas rendah untuk "pemula" di doc_2 secara langsung mengurangi skor keseluruhannya.

Mengapa MAX_SIM + Larik Struktur Penting dalam Basis Data Vektor

Milvus adalah basis data vektor sumber terbuka dan berkinerja tinggi dan sekarang sepenuhnya mendukung MAX_SIM bersama dengan Array of Structs, yang memungkinkan pengambilan multi-vektor tingkat entitas secara asli:

  • Menyimpan entitas multi-vektor secara native: Array of Structs memungkinkan Anda untuk menyimpan kelompok vektor terkait dalam satu bidang tanpa memisahkannya ke dalam baris atau tabel tambahan yang terpisah.

  • Komputasi pencocokan terbaik yang efisien: Dikombinasikan dengan indeks vektor seperti IVF dan HNSW, MAX_SIM dapat menghitung kecocokan terbaik tanpa memindai setiap vektor, sehingga menjaga kinerja tetap tinggi bahkan dengan dokumen yang besar.

  • Dibuat khusus untuk beban kerja yang berat secara semantik: Pendekatan ini unggul dalam pencarian teks panjang, pencocokan semantik multi-segi, penyelarasan ringkasan dokumen, kueri multi-kata kunci, dan skenario AI lainnya yang membutuhkan penalaran semantik yang fleksibel dan berbutir halus.

Kapan Menggunakan Array of Structs

Nilai Array of Structs menjadi jelas ketika Anda melihat apa yang dimungkinkannya. Pada intinya, fitur ini menyediakan tiga kemampuan dasar:

  • Fiturini menggabungkan data heterogen-vektor, skalar, string, metadata-ke dalam satu objek terstruktur.

  • Fiturini menyelaraskan penyimpanan dengan entitas dunia nyata, sehingga setiap baris basis data dipetakan dengan jelas ke item aktual seperti artikel, produk, atau video.

  • Ketika dikombinasikan dengan fungsi agregat seperti MAX_SIM, ini memungkinkan pengambilan multi-vektor tingkat entitas yang sebenarnya langsung dari basis data, menghilangkan deduplikasi, pengelompokan, atau pengurutan ulang di lapisan aplikasi.

Karena sifat-sifat ini, Array of Structs sangat cocok setiap kali entitas logis tunggal diwakili oleh beberapa vektor. Contoh umum termasuk artikel yang dipecah menjadi beberapa paragraf, dokumen yang diuraikan menjadi penyematan token, atau produk yang diwakili oleh beberapa gambar. Jika hasil pencarian Anda mengalami duplikat hit, fragmen yang tersebar, atau entitas yang sama muncul beberapa kali di hasil teratas, Array of Structs menyelesaikan masalah ini pada lapisan penyimpanan dan pengambilan - bukan melalui penambalan setelah fakta dalam kode aplikasi.

Pola ini sangat kuat untuk sistem AI modern yang mengandalkan pengambilan multi-vektor, sebagai contoh:

  • ColBERT merepresentasikan satu dokumen sebagai 100-500 penyematan token untuk pencocokan semantik berbutir halus di seluruh domain seperti teks hukum dan penelitian akademis.

  • ColPali mengubah setiap halaman PDF menjadi 256-1024 tambalan gambar untuk pencarian lintas-modal di seluruh laporan keuangan, kontrak, faktur, dan dokumen pindaian lainnya.

Sebuah array Structs memungkinkan Milvus menyimpan semua vektor ini di bawah satu entitas dan menghitung kemiripan agregat (mis., MAX_SIM) secara efisien dan native. Untuk memperjelas hal ini, berikut adalah dua contoh konkret.

Sebelumnya, produk dengan banyak gambar disimpan dalam skema datar-satu gambar per baris. Sebuah produk dengan foto depan, samping, dan miring menghasilkan tiga baris. Hasil pencarian sering kali mengembalikan beberapa gambar dari produk yang sama, sehingga membutuhkan deduplikasi manual dan pemeringkatan ulang.

Dengan Array Struktur, setiap produk menjadi satu baris. Semua penyematan gambar dan metadata (angle, is_primary, dll.) berada di dalam bidang images sebagai array of structs. Milvus memahami bahwa mereka adalah bagian dari produk yang sama dan mengembalikan produk tersebut secara keseluruhan - bukan gambar individualnya.

Sebelumnya, satu artikel Wikipedia dibagi menjadi N baris paragraf. Hasil pencarian mengembalikan paragraf yang tersebar, memaksa sistem untuk mengelompokkannya dan menebak artikel mana yang termasuk di dalamnya.

Dengan Array of Structs, seluruh artikel menjadi satu baris. Semua paragraf dan penyematannya dikelompokkan di bawah bidang paragraf, dan basis data mengembalikan artikel lengkap, bukan potongan-potongan yang terpecah-pecah.

Tutorial Praktis: Pengambilan Tingkat Dokumen dengan Array of Structs

1. Pengambilan Dokumen Wikipedia

Dalam tutorial ini, kita akan membahas cara menggunakan Array of Structs untuk mengubah data tingkat paragraf menjadi catatan dokumen lengkap - memungkinkan Milvus untuk melakukan pengambilan tingkat dokumen yang sebenarnya daripada mengembalikan fragmen-fragmen yang terisolasi.

Banyak pipeline basis pengetahuan menyimpan artikel Wikipedia sebagai potongan paragraf. Hal ini bekerja dengan baik untuk penyematan dan pengindeksan, tetapi ini merusak pengambilan: kueri pengguna biasanya mengembalikan paragraf yang terpencar-pencar, memaksa Anda untuk mengelompokkan dan merekonstruksi artikel secara manual. Dengan Array of Structs dan MAX_SIM, kita dapat mendesain ulang skema penyimpanan sehingga setiap artikel menjadi satu baris, dan Milvus dapat mengurutkan dan mengembalikan seluruh dokumen secara native.

Di langkah selanjutnya, kami akan menunjukkan caranya:

  1. Memuat dan melakukan praproses data paragraf Wikipedia

  2. Mengelompokkan semua paragraf yang termasuk dalam artikel yang sama ke dalam Array of Structs

  3. Masukkan dokumen terstruktur ini ke dalam Milvus

  4. Menjalankan kueri MAX_SIM untuk mengambil artikel lengkap - dengan bersih, tanpa melakukan deduping atau pengurutan ulang

Pada akhir tutorial ini, Anda akan memiliki pipeline yang berfungsi di mana Milvus menangani pengambilan tingkat entitas secara langsung, persis seperti yang diharapkan pengguna.

Model Data:

{
    "wiki_id": int,                  # WIKI ID(primary key) 
    "paragraphs": ARRAY<STRUCT<      # Array of paragraph structs
        text:VARCHAR                 # Paragraph text
        emb: FLOAT_VECTOR(768)       # Embedding for each paragraph
    >>
}

Langkah 1: Mengelompokkan dan Mengubah Data

Untuk demo ini, kita menggunakan dataset Wikipedia Embeddings Sederhana.

import pandas as pd
import pyarrow as pa

# Load the dataset and group by wiki_id df = pd.read_parquet(“train-*.parquet”) grouped = df.groupby(‘wiki_id’)

# Build the paragraph array for each article wiki_data = [] for wiki_id, group in grouped: wiki_data.append({ ‘wiki_id’: wiki_id, ‘paragraphs’: [{‘text’: row[‘text’], ‘emb’: row[‘emb’]} for _, row in group.iterrows()] })

Langkah 2: Membuat Koleksi Milvus

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri=“http://localhost:19530”) schema = client.create_schema() schema.add_field(“wiki_id”, DataType.INT64, is_primary=True)

# Define the Struct schema struct_schema = client.create_struct_field_schema() struct_schema.add_field(“text”, DataType.VARCHAR, max_length=65535) struct_schema.add_field(“emb”, DataType.FLOAT_VECTOR, dim=768)

schema.add_field(“paragraphs”, DataType.ARRAY, element_type=DataType.STRUCT, struct_schema=struct_schema, max_capacity=200)

client.create_collection(“wiki_docs”, schema=schema)

Langkah 3: Memasukkan Data dan Membangun Indeks

# Batch insert documents
client.insert("wiki_docs", wiki_data)

# Create an HNSW index index_params = client.prepare_index_params() index_params.add_index( field_name="paragraphs[emb]", index_type=“HNSW”, metric_type=“MAX_SIM_COSINE”, params={“M”: 16, “efConstruction”: 200} ) client.create_index(“wiki_docs”, index_params) client.load_collection(“wiki_docs”)

Langkah 4: Mencari Dokumen

# Search query
import cohere
from pymilvus.client.embedding_list import EmbeddingList

# The dataset uses Cohere’s multilingual-22-12 embedding model, so we must embed the query using the same model. co = cohere.Client(f"<>") query = ‘Who founded Youtube’ response = co.embed(texts=[query], model=‘multilingual-22-12’) query_embedding = response.embeddings query_emb_list = EmbeddingList()

for vec in query_embedding[0]: query_emb_list.add(vec)

results = client.search( collection_name=“wiki_docs”, data=[query_emb_list], anns_field="paragraphs[emb]", search_params={ “metric_type”: “MAX_SIM_COSINE”, “params”: {“ef”: 200, “retrieval_ann_ratio”: 3} }, limit=10, output_fields=[“wiki_id”] )

# Results: directly return 10 full articles! for hit in results[0]: print(f"Article {hit[‘entity’][‘wiki_id’]}: Score {hit[‘distance’]:.4f}")

Langkah 5: Membandingkan Keluaran: Pengambilan Tradisional vs Array of Structs

Dampak dari Array of Structs menjadi jelas ketika kita melihat apa yang sebenarnya dihasilkan oleh database:

DimensiPendekatan TradisionalLarik Struktur
Keluaran Basis DataMengembalikan 100 paragraf teratas (redundansi tinggi)Mengembalikan 10 dokumen lengkap teratas - bersih dan akurat
Logika AplikasiMembutuhkan pengelompokan, deduplikasi, dan pengurutan ulang (kompleks)Tidak perlu pemrosesan pasca - hasil tingkat entitas datang langsung dari Milvus

Dalam contoh Wikipedia, kami hanya mendemonstrasikan kasus yang paling sederhana: menggabungkan vektor paragraf ke dalam representasi dokumen terpadu. Tetapi kekuatan sebenarnya dari Array of Structs adalah bahwa ia dapat digeneralisasi ke model data multi-vektor apa pun - baik jalur pengambilan klasik maupun arsitektur AI modern.

Skenario Pengambilan Multi-Vektor Tradisional

Banyak sistem pencarian dan rekomendasi yang sudah mapan secara alami beroperasi pada entitas dengan beberapa vektor terkait. Array of Structs memetakan kasus-kasus penggunaan ini dengan jelas:

SkenarioModel DataVektor per Entitas
🛍️ Produk e-commerceSatu produk → beberapa gambar5-20
🎬 Pencarian videoSatu video → beberapa klip20-100
📖 Pengambilan kertasSatu kertas → beberapa bagian5-15

Beban Kerja Model AI (Kasus Penggunaan Multi-Vektor Utama)

Array of Structs menjadi semakin penting dalam model AI modern yang secara sengaja menghasilkan kumpulan besar vektor per entitas untuk penalaran semantik berbutir halus.

ModelModel DataVektor per EntitasAplikasi
ColBERTSatu dokumen → banyak penyematan token100-500Teks hukum, makalah akademis, pengambilan dokumen berbutir halus
ColPaliSatu halaman PDF → banyak penyematan tambalan256-1024Laporan keuangan, kontrak, faktur, pencarian dokumen multimodal

Model-model ini membutuhkan pola penyimpanan multi-vektor. Sebelum Array of Structs, pengembang harus membagi vektor menjadi beberapa baris dan secara manual menyatukan hasilnya. Dengan Milvus, entitas-entitas ini sekarang dapat disimpan dan diambil secara native, dengan MAX_SIM yang menangani penilaian tingkat dokumen secara otomatis.

ColPali adalah model yang kuat untuk pengambilan PDF lintas-modal. Alih-alih mengandalkan teks, ColPali memproses setiap halaman PDF sebagai gambar dan mengirisnya menjadi hingga 1024 tambalan visual, menghasilkan satu penyematan per tambalan. Dalam skema database tradisional, hal ini memerlukan penyimpanan satu halaman sebagai ratusan atau ribuan baris terpisah, sehingga database tidak dapat memahami bahwa baris-baris tersebut adalah bagian dari halaman yang sama. Akibatnya, pencarian tingkat entitas menjadi terfragmentasi dan tidak praktis.

Array of Structs memecahkan masalah ini dengan menyimpan semua patch yang disematkan di dalam satu bidang, sehingga Milvus dapat memperlakukan halaman sebagai satu entitas multi-vektor yang kohesif.

Pencarian PDF tradisional sering kali bergantung pada OCR, yang mengubah gambar halaman menjadi teks. Ini berfungsi untuk teks biasa tetapi kehilangan bagan, tabel, tata letak, dan isyarat visual lainnya. ColPali menghindari keterbatasan ini dengan bekerja secara langsung pada gambar halaman, mempertahankan semua informasi visual dan tekstual. Pengorbanannya adalah skala: setiap halaman sekarang berisi ratusan vektor, yang membutuhkan basis data yang dapat menggabungkan banyak penyematan ke dalam satu entitas - persis seperti yang disediakan oleh Array of Structs + MAX_SIM.

Kasus penggunaan yang paling umum adalah Vision RAG, di mana setiap halaman PDF menjadi entitas multi-vektor. Skenario umum meliputi:

  • Laporan keuangan: mencari ribuan PDF untuk halaman yang berisi bagan atau tabel tertentu.

  • Kontrak: mengambil klausul dari dokumen hukum yang dipindai atau difoto.

  • Faktur: menemukan faktur berdasarkan vendor, jumlah, atau tata letak.

  • Presentasi: menemukan slide yang berisi gambar atau diagram tertentu.

Model Data:

{
    "page_id": int,                     # Page ID (primary key) 
    "page_number": int,                 # Page number within the document 
    "doc_name": VARCHAR,                # Document name
    "patches": ARRAY<STRUCT<            # Array of patch objects
        patch_embedding: FLOAT_VECTOR(128)  # Embedding for each patch
    >>
}

Langkah 1: Siapkan DataAnda dapat merujuk ke dokumen untuk mengetahui detail tentang bagaimana ColPali mengubah gambar atau teks menjadi representasi multi-vektor.

import torch
from PIL import Image

from colpali_engine.models import ColPali, ColPaliProcessor

model_name = “vidore/colpali-v1.3”

model = ColPali.from_pretrained( model_name, torch_dtype=torch.bfloat16, device_map=“cuda:0”, # or “mps” if on Apple Silicon ).eval()

processor = ColPaliProcessor.from_pretrained(model_name) # Example: 2 documents, 5 pages each, total 10 images images = [ Image.open(“path/to/your/image1.png”), Image.open(“path/to/your/image2.png”), … Image.open(“path/to/your/image10.png”) ] # Convert each image into multiple patch embeddings batch_images = processor.process_images(images).to(model.device) with torch.no_grad(): image_embeddings = model(**batch_images)

Langkah 2: Membuat Koleksi Milvus

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri=“http://localhost:19530”) schema = client.create_schema() schema.add_field(“page_id”, DataType.INT64, is_primary=True) schema.add_field(“page_number”, DataType.INT64) schema.add_field(“doc_name”, DataType.VARCHAR, max_length=500)

# Struct Array for patches struct_schema = client.create_struct_field_schema() struct_schema.add_field(“patch_embedding”, DataType.FLOAT_VECTOR, dim=128)

schema.add_field(“patches”, DataType.ARRAY, element_type=DataType.STRUCT, struct_schema=struct_schema, max_capacity=2048)

client.create_collection(“doc_pages”, schema=schema)

Langkah 3: Memasukkan Data dan Membangun Indeks

# Prepare data for insertion
page_data=[
    {
        "page_id": 0,
        "page_number": 0,
        "doc_name": "Q1_Financial_Report.pdf",
        "patches": [
            {"patch_embedding": emb} for emb in image_embeddings[0]
        ],
    },
    ...,
    {
        "page_id": 9,
        "page_number": 4,
        "doc_name": "Product_Manual.pdf",
        "patches": [
            {"patch_embedding": emb} for emb in image_embeddings[9]
        ],
    },
]

client.insert(“doc_pages”, page_data)

# Create index index_params = client.prepare_index_params() index_params.add_index( field_name="patches[patch_embedding]", index_type=“HNSW”, metric_type=“MAX_SIM_IP”, params={“M”: 32, “efConstruction”: 200} ) client.create_index(“doc_pages”, index_params) client.load_collection(“doc_pages”)

Langkah 4: Pencarian Lintas Moda: Kueri Teks → Hasil Gambar

# Run the search
from pymilvus.client.embedding_list import EmbeddingList

queries = [ “quarterly revenue growth chart”
] # Convert the text query into a multi-vector representation batch_queries = processor.process_queries(queries).to(model.device) with torch.no_grad(): query_embeddings = model(**batch_queries)

query_emb_list = EmbeddingList() for vec in query_embeddings[0]: query_emb_list.add(vec) results = client.search( collection_name=“doc_pages”, data=[query_emb_list], anns_field="patches[patch_embedding]", search_params={ “metric_type”: “MAX_SIM_IP”, “params”: {“ef”: 100, “retrieval_ann_ratio”: 3} }, limit=3, output_fields=[“page_id”, “doc_name”, “page_number”] )

print(f"Query: '{queries[0]}'") for i, hit in enumerate(results, 1): entity = hit[‘entity’] print(f"{i}. {entity[‘doc_name’]} - Page {entity[‘page_number’]}") print(f" Score: {hit[‘distance’]:.4f}\n")

Contoh Keluaran:

Query: 'quarterly revenue growth chart'
1. Q1_Financial_Report.pdf - Page 2
   Score: 0.9123

2. Q1_Financial_Report.pdf - Page 1 Score: 0.7654

3. Product_Manual.pdf - Page 1 Score: 0.5231

Di sini, hasilnya langsung mengembalikan halaman PDF penuh. Kita tidak perlu khawatir tentang penyematan patch 1024 yang mendasarinya-Milvus menangani semua agregasi secara otomatis.

Kesimpulan

Sebagian besar basis data vektor menyimpan setiap fragmen sebagai catatan independen, yang berarti aplikasi harus mengumpulkan kembali fragmen-fragmen tersebut ketika mereka membutuhkan dokumen, produk, atau halaman lengkap. Array Structs mengubah hal itu. Dengan menggabungkan skalar, vektor, teks, dan bidang lain ke dalam satu objek terstruktur, memungkinkan satu baris basis data mewakili satu entitas lengkap dari ujung ke ujung.

Hasilnya sederhana namun sangat kuat: pekerjaan yang dulunya membutuhkan pengelompokan, deduping, dan pengurutan ulang yang rumit di lapisan aplikasi menjadi kemampuan basis data asli. Dan itulah arah masa depan database vektor - struktur yang lebih kaya, pengambilan yang lebih cerdas, dan pipeline yang lebih sederhana.

Untuk informasi lebih lanjut tentang Array of Structs dan MAX_SIM, lihat dokumentasi di bawah ini:

Ada pertanyaan atau ingin mendalami fitur-fitur Milvus terbaru? Bergabunglah dengan saluran Discord kami atau ajukan pertanyaan di GitHub. Anda juga dapat memesan sesi tatap muka selama 20 menit untuk mendapatkan wawasan, panduan, dan jawaban atas pertanyaan Anda melalui Milvus Office Hours.

    Try Managed Milvus for Free

    Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

    Get Started

    Like the article? Spread the word

    Terus Baca