Menghasilkan Ekspresi Filter Kueri Milvus dengan Model Bahasa Besar
Dalam tutorial ini, kami akan mendemonstrasikan cara menggunakan Model Bahasa Besar (LLM) untuk secara otomatis menghasilkan ekspresi filter Milvus dari kueri bahasa alami. Pendekatan ini membuat kueri basis data vektor menjadi lebih mudah diakses dengan mengizinkan pengguna untuk mengekspresikan kondisi penyaringan yang kompleks dalam bahasa Inggris sederhana, yang kemudian dikonversi ke sintaks Milvus yang tepat.
Milvus mendukung kemampuan pemfilteran yang canggih termasuk:
- Operator Dasar: Operator perbandingan seperti
==,!=,>,<,>=,<= - Operator Boolean: Operator logika seperti
and,or,notuntuk kondisi yang kompleks - Operasi String: Pencocokan pola dengan
likedan fungsi string lainnya - Operasi Larik: Bekerja dengan bidang larik menggunakan
array_contains,array_length, dll. - Operasi JSON: Mengajukan pertanyaan ke bidang JSON dengan operator khusus
Dengan mengintegrasikan LLM dengan dokumentasi Milvus, kita dapat membuat sistem cerdas yang memahami kueri bahasa alami dan menghasilkan ekspresi filter yang benar secara sintaksis. Tutorial ini akan memandu Anda dalam proses menyiapkan sistem ini, menyoroti keefektifannya dalam berbagai skenario penyaringan.
Ketergantungan dan Lingkungan
$ pip install --upgrade pymilvus openai requests docling beautifulsoup4
print("Environment setup complete!")
Menyiapkan variabel lingkungan
Konfigurasikan kredensial API OpenAI Anda untuk mengaktifkan pembuatan embedding dan pembuatan ekspresi filter berbasis LLM. Ganti 'your_openai_api_key' dengan kunci API OpenAI Anda yang sebenarnya.
import os
import openai
os.environ["OPENAI_API_KEY"] = "your_openai_api_key"
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("Please set the OPENAI_API_KEY environment variable!")
openai.api_key = api_key
print("API key loaded.")
Membuat Koleksi Sampel
Sekarang mari kita buat contoh koleksi Milvus dengan data pengguna. Koleksi ini akan berisi bidang skalar (untuk penyaringan) dan penyematan vektor (untuk pencarian semantik). Kita akan menggunakan model penyematan teks OpenAI untuk menghasilkan representasi vektor dari informasi pengguna.
from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType
import os
from openai import OpenAI
import uuid
client = MilvusClient(uri="http://localhost:19530")
openai_client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
embedding_model = "text-embedding-3-small"
embedding_dim = 1536
fields = [
FieldSchema(
name="pk",
dtype=DataType.VARCHAR,
is_primary=True,
auto_id=False,
max_length=100,
),
FieldSchema(name="name", dtype=DataType.VARCHAR, max_length=128),
FieldSchema(name="age", dtype=DataType.INT64),
FieldSchema(name="city", dtype=DataType.VARCHAR, max_length=128),
FieldSchema(name="hobby", dtype=DataType.VARCHAR, max_length=128),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=embedding_dim),
]
schema = CollectionSchema(fields=fields, description="User data embedding example")
collection_name = "user_data_collection"
if client.has_collection(collection_name):
client.drop_collection(collection_name)
# Strong consistency waits for all loads to complete, adding latency with large datasets
# client.create_collection(
# collection_name=collection_name, schema=schema, consistency_level="Strong"
# )
client.create_collection(collection_name=collection_name, schema=schema)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="IVF_FLAT",
metric_type="COSINE",
params={"nlist": 128},
)
client.create_index(collection_name=collection_name, index_params=index_params)
data_to_insert = [
{"name": "John", "age": 23, "city": "Shanghai", "hobby": "Drinking coffee"},
{"name": "Alice", "age": 29, "city": "New York", "hobby": "Reading books"},
{"name": "Bob", "age": 31, "city": "London", "hobby": "Playing chess"},
{"name": "Eve", "age": 27, "city": "Paris", "hobby": "Painting"},
{"name": "Charlie", "age": 35, "city": "Tokyo", "hobby": "Cycling"},
{"name": "Grace", "age": 22, "city": "Berlin", "hobby": "Photography"},
{"name": "David", "age": 40, "city": "Toronto", "hobby": "Watching movies"},
{"name": "Helen", "age": 30, "city": "Sydney", "hobby": "Cooking"},
{"name": "Frank", "age": 28, "city": "Beijing", "hobby": "Hiking"},
{"name": "Ivy", "age": 26, "city": "Seoul", "hobby": "Dancing"},
{"name": "Tom", "age": 33, "city": "Madrid", "hobby": "Writing"},
]
def get_embeddings(texts):
return [
rec.embedding
for rec in openai_client.embeddings.create(
input=texts, model=embedding_model, dimensions=embedding_dim
).data
]
texts = [
f"{item['name']} from {item['city']} is {item['age']} years old and likes {item['hobby']}."
for item in data_to_insert
]
embeddings = get_embeddings(texts)
insert_data = []
for item, embedding in zip(data_to_insert, embeddings):
item_with_embedding = {
"pk": str(uuid.uuid4()),
"name": item["name"],
"age": item["age"],
"city": item["city"],
"hobby": item["hobby"],
"embedding": embedding,
}
insert_data.append(item_with_embedding)
client.insert(collection_name=collection_name, data=insert_data)
print(f"Collection '{collection_name}' has been created and data has been inserted.")
Mencetak 3 data sampel
Kode di atas membuat koleksi Milvus dengan struktur sebagai berikut:
- pk: Bidang kunci utama (VARCHAR)
- nama: Nama pengguna (VARCHAR)
- usia: Usia pengguna (INT64)
- kota: Kota pengguna (VARCHAR)
- hobi: Hobi pengguna (VARCHAR)
- penyematan: Penyematan vektor (FLOAT_VECTOR, 1536 dimensi)
Kami telah memasukkan 11 sampel pengguna dengan informasi pribadi mereka dan menghasilkan penyematan untuk kemampuan pencarian semantik. Setiap informasi pengguna diubah menjadi teks deskriptif yang menangkap nama, lokasi, usia, dan minat mereka sebelum disematkan. Mari kita verifikasi bahwa koleksi kita telah berhasil dibuat dan berisi data yang diharapkan dengan melakukan kueri pada beberapa catatan sampel.
from pymilvus import MilvusClient
import os
from openai import OpenAI
client = MilvusClient(uri="http://localhost:19530")
collection_name = "user_data_collection"
client.load_collection(collection_name=collection_name)
result = client.query(
collection_name=collection_name,
filter="",
output_fields=["name", "age", "city", "hobby"],
limit=3,
)
for record in result:
print(record)
Mengumpulkan Dokumentasi Ekspresi Filter Milvus
Untuk membantu model bahasa besar lebih memahami sintaks ekspresi filter Milvus, kita perlu menyediakan dokumentasi resmi yang relevan. Kita akan menggunakan pustaka docling untuk mengambil beberapa halaman utama dari situs web resmi Milvus.
Halaman-halaman ini berisi informasi rinci tentang:
- Operator Boolean:
and,or,notuntuk kondisi logika yang kompleks - Operator dasar: Operator perbandingan seperti
==,!=,>,<,>=,<= - Template pemfilteran: Pola dan sintaks pemfilteran tingkat lanjut
- Pencocokan string: Pencocokan pola dengan
likedan operasi string lainnya
Dokumentasi ini akan berfungsi sebagai basis pengetahuan bagi LLM kami untuk menghasilkan ekspresi filter yang akurat.
import docling
from docling.document_converter import DocumentConverter
converter = DocumentConverter()
docs = [
converter.convert(url)
for url in [
"https://milvus.io/docs/boolean.md",
"https://milvus.io/docs/basic-operators.md",
"https://milvus.io/docs/filtering-templating.md",
]
]
for doc in docs[:3]:
print(doc.document.export_to_markdown())
Penggalian dokumentasi menyediakan cakupan yang komprehensif dari sintaks filter Milvus. Basis pengetahuan ini akan memungkinkan LLM kami untuk memahami nuansa konstruksi ekspresi filter, termasuk penggunaan operator yang tepat, referensi bidang, dan kombinasi kondisi yang kompleks.
Pembuatan Filter yang Didukung LLM
Sekarang kita telah memiliki konteks dokumentasi, mari kita siapkan sistem LLM untuk menghasilkan ekspresi filter. Kita akan membuat prompt terstruktur yang menggabungkan dokumentasi yang telah di-scan dengan pertanyaan pengguna untuk menghasilkan ekspresi filter Milvus yang benar secara sintaksis.
Sistem pembuatan filter kami menggunakan prompt yang dibuat dengan hati-hati:
- Menyediakan konteks: Mencakup dokumentasi Milvus yang lengkap sebagai bahan referensi
- Menetapkan batasan: Memastikan LLM hanya menggunakan sintaks dan fitur yang terdokumentasi
- Menegakkan akurasi: Memerlukan ekspresi yang benar secara sintaksis
- Mempertahankan fokus: Hanya mengembalikan ekspresi filter tanpa penjelasan
Mari kita uji dengan kueri bahasa alami dan lihat seberapa baik kinerja LLM.
from openai import OpenAI
import json
from IPython.display import display, Markdown
context = "\n".join([doc.document.export_to_markdown() for doc in docs])
prompt = f"""
You are an expert Milvus vector database engineer. Your task is to convert a user's natural language query into a valid Milvus filter expression, using the provided Milvus documentation as your knowledge base.
Follow these rules strictly:
1. Only use the provided documents as your source of knowledge.
2. Ensure the generated filter expression is syntactically correct.
3. If there isn't enough information in the documents to create an expression, state that directly.
4. Only return the final filter expression. Do not include any explanations or extra text.
---
**Milvus Documentation Context:**
{context}
---
**User Query:**
{user_query}
---
**Filter Expression:**
"""
client = OpenAI()
def generate_filter_expr(user_query):
"""
Generates a Milvus filter expression from a user query using GPT-4o-mini.
"""
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": prompt},
{"role": "user", "content": user_query},
],
temperature=0.0,
)
return completion.choices[0].message.content
user_query = "Find people older than 30 who live in London, Tokyo, or Toronto"
filter_expr = generate_filter_expr(user_query)
print(f"Generated filter expression: {filter_expr}")
LLM berhasil menghasilkan ekspresi filter yang menggabungkan beberapa kondisi:
- Perbandingan usia menggunakan
> - Pencocokan beberapa kota menggunakan operator
in - Perujukan dan sintaksis bidang yang tepat
Hal ini menunjukkan kekuatan dari penyediaan konteks dokumentasi yang komprehensif untuk memandu pembuatan filter LLM.
Menguji Filter yang Dihasilkan
Sekarang mari kita uji ekspresi filter yang telah dihasilkan dengan menggunakannya dalam operasi pencarian Milvus yang sebenarnya. Kami akan menggabungkan pencarian semantik dengan penyaringan yang tepat untuk menemukan pengguna yang sesuai dengan maksud kueri dan kriteria tertentu.
from pymilvus import MilvusClient
from openai import OpenAI
import os
client = MilvusClient(uri="http://localhost:19530")
openai_client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
clean_filter = (
filter_expr.replace("```", "").replace('filter="', "").replace('"', "").strip()
)
print(f"Using filter: {clean_filter}")
query_embedding = (
openai_client.embeddings.create(
input=[user_query], model="text-embedding-3-small", dimensions=1536
)
.data[0]
.embedding
)
search_results = client.search(
collection_name="user_data_collection",
data=[query_embedding],
limit=10,
filter=clean_filter,
output_fields=["pk", "name", "age", "city", "hobby"],
search_params={
"metric_type": "COSINE",
"params": {"nprobe": 10},
},
)
print("Search results:")
for i, hits in enumerate(search_results):
print(f"Query {i}:")
for hit in hits:
print(f" - {hit}")
print()
Analisis Hasil
Hasil pencarian menunjukkan keberhasilan integrasi filter yang dihasilkan LLM dengan pencarian vektor Milvus. Penyaringan mengidentifikasi dengan tepat pengguna yang:
- Berusia lebih dari 30 tahun
- Tinggal di London, Tokyo, atau Toronto
- Sesuai dengan konteks semantik kueri
Pendekatan ini menggabungkan ketepatan pemfilteran terstruktur dengan fleksibilitas input bahasa alami, sehingga database vektor lebih mudah diakses oleh pengguna yang mungkin tidak terbiasa dengan sintaksis kueri tertentu.