Využití vektorové databáze Milvus v aplikacích psaných v Pythonu

Včera
Doba čtení: 33 minut

Sdílet

Milvus
Autor: Milvus, Duck.ai
Pomocí několika praktických příkladů se seznámíme se způsobem využití vektorové databáze Milvus v aplikacích, které jsou naprogramovány v Pythonu. Milvus lze využít například pro konstrukci RAGu (Retrieval-augmented generation).

V současnosti můžeme sledovat poměrně výrazné a stále častější nasazování vektorových databází, a to jak čistě vektorových databází, tak i databází umožňujících hybridní vyhledávání. Jedná se (alespoň většinou) o specializované databáze, které umožňují ukládat vektory numerických hodnot a především efektivně vyhledávat vektory podle jejich podobnosti (například se zadaným vzorem), přičemž podobností (similarity) může být v tomto kontextu myšlena například vzdálenost koncových bodů vektorů v Eukleidovském prostoru, kosinus úhlu mezi vektory, výsledek skalárního součinu (pro normalizované vektory) atd.

Co se dozvíte v článku
  1. Instalace balíčku pymilvus a jeho závislostí
  2. Skript realizující připojení k (nové) vektorové databázi
  3. Struktura adresářů a souborů s prázdnou vektorovou databází
  4. Vytvoření nové databáze při každém spuštění aplikace
  5. Struktura adresářů a souborů s dvojicí vektorových databází
  6. Zápis vektorů s přidanými texty do databáze
  7. Struktura výsledné databáze
  8. Vyhledávání vektorů na základě jejich podobnosti
  9. Skript realizující vyhledávání vektorů na základě jejich podobnosti
  10. Vizualizace získaných výsledků
  11. Použití odlišné metriky pro vyhledávání vektorů na základě jejich podobnosti
  12. Úprava skriptu: vyhledávání vektorů s využitím metriky skalárního součinu
  13. Metrika založená na skalárním součinu a normalizace vektorů
  14. Vliv normalizace vektorů při vyhledávání s využitím metriky založené na skalárním součinu
  15. Specifikace schématu databáze
  16. Demonstrační příklad: specifikace schématu databáze
  17. Repositář s demonstračními příklady
  18. Články o vektorových databázích i jejich využití při realizaci RAGu
  19. Odkazy na Internetu

Tyto operace se používají v mnoha oblastech, například při rozpoznávání a zpracování přirozeného jazyka (NLP – Natural Language Processing), při rozpoznávání obrázků, rozpoznávání hlasů, detekci anomálií, ale i (a to zejména) v souvislosti s velkými jazykovými modely (k tomuto tématu se ještě vrátíme v samostatném článku).

Poznámka: do této kategorie spadají i RAG databáze.

V dnešním článku se s využitím několika praktických příkladů seznámíme se způsobem využití vektorové databáze Milvus v aplikacích, které jsou naprogramovány v Pythonu. Navážeme tak na články, ve kterých jsme se věnovali rozšíření databáze Postgres o vektorové operace a vyhledávání vektorů na základě jejich podobnosti [1] [2] [3] [4] a taktéž na článek o rozšíření SQLite-Vec [5] i na čtveřici článků o knihovně FAISS [6] [7] [8] [9].

Instalace balíčku pymilvus a jeho závislostí

V praktické části dnešního článku si ukážeme základní způsoby použití balíčku nazvaného pymilvus. Ten není součástí standardní knihovny, takže je nutné ho doinstalovat, například s využitím nástroje pip, pdm, uv atd. V článku použiji nástroj uv, ovšem naprosto stejným způsobem (jen záměnou příkazu) lze použít i pdm.

Nejprve si necháme vygenerovat nový projekt:

$ uv init milvus
 
Initialized project `milvus` at `/tmp/ramdisk/milvus`
Poznámka: obecně není dobrý nápad pojmenovat projekt stejně jako knihovnu resp. balíček, který bude v projektu použit. Ovšem my nebudeme používat balíček milvus, ale pymilvus, takže by k žádným problémům nemělo dojít.

Dále do projektu přidáme balíček pymilvus, což je snadné:

$ uv add pymilvus
 
Using CPython 3.13.9 interpreter at: /usr/bin/python3.13
Creating virtual environment at: .venv
Resolved 19 packages in 1.18s
Prepared 3 packages in 637ms
░░░░░░░░░░░░░░░░░░░░ [0/17] Installing wheels...
warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
         If the cache and target directories are on different filesystems, hardlinking may not be supported.
         If this is intentional, set `export UV_LINK_MODE=copy` or use `--link-mode=copy` to suppress this warning.
Installed 17 packages in 349ms
 + cachetools==7.1.4
 + certifi==2026.6.17
 + charset-normalizer==3.4.7
 + grpcio==1.81.1
 + idna==3.18
 + numpy==2.4.6
 + orjson==3.11.9
 + pandas==3.0.3
 + protobuf==7.35.1
 + pymilvus==3.0.0
 + python-dateutil==2.9.0.post0
 + python-dotenv==1.2.2
 + requests==2.34.2
 + setuptools==82.0.1
 + six==1.17.0
 + typing-extensions==4.15.0
 + urllib3==2.7.0
Poznámka: povšimněte si tranzitivních závislostí, které byly taktéž doinstalovány.

Ve skutečnosti však budeme potřebovat variantu využívající databázi milvus_lite, takže ještě přidáme další balíček. Tento krok schválně provádím samostatným příkazem, aby bylo patrné, jaké jsou tranzitivní závislosti jednotlivých balíčků:

$ uv add pymilvus[milvus_lite]
 
Resolved 23 packages in 991ms
Prepared 2 packages in 27.90s
░░░░░░░░░░░░░░░░░░░░ [0/4] Installing wheels...
warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
         If the cache and target directories are on different filesystems, hardlinking may not be supported.
         If this is intentional, set `export UV_LINK_MODE=copy` or use `--link-mode=copy` to suppress this warning.
Installed 4 packages in 414ms
 + faiss-cpu==1.14.3
 + milvus-lite==3.0
 + packaging==26.2
 + pyarrow==24.0.0

Verze nainstalovaných balíčků i s jejich závislostmi zjistíme snadno:

$ uv tree
 
Resolved 23 packages in 1ms
milvus2 v0.1.0
└── pymilvus[milvus-lite] v3.0.0
    ├── cachetools v7.1.4
    ├── grpcio v1.81.1
    │   └── typing-extensions v4.15.0
    ├── orjson v3.11.9
    ├── pandas v3.0.3
    │   ├── numpy v2.4.6
    │   └── python-dateutil v2.9.0.post0
    │       └── six v1.17.0
    ├── protobuf v7.35.1
    ├── python-dotenv v1.2.2
    ├── requests v2.34.2
    │   ├── certifi v2026.6.17
    │   ├── charset-normalizer v3.4.7
    │   ├── idna v3.18
    │   └── urllib3 v2.7.0
    ├── setuptools v82.0.1
    └── milvus-lite v3.0 (extra: milvus-lite)
        ├── faiss-cpu v1.14.3
        │   ├── numpy v2.4.6
        │   └── packaging v26.2
        ├── grpcio v1.81.1 (*)
        ├── numpy v2.4.6
        └── pyarrow v24.0.0
(*) Package tree already displayed

Skript realizující připojení k (nové) vektorové databázi

První program napsaný v Pythonu, který bude s databází Milvus komunikovat, je realizován jednoduchým skriptem, ve kterém dochází k inicializaci klienta (tedy třídy nabízející rozhraní mezi skriptem a databází). Konstrukce klienta vyžaduje v tom nejjednodušším případě pouze zadání cesty k adresáři, ve kterém je databáze uložena:.

class MilvusClient(pymilvus.milvus_client.base.BaseMilvusClient)
 |  MilvusClient(
 |      uri: str = 'http://localhost:19530',
 |      user: str = '',
 |      password: str = '',
 |      db_name: str = '',
 |      token: str = '',
 |      timeout: Optional[float] = None,
 |      **kwargs
 |  ) -> None

V našem konkrétním případě:

# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")

Následně je nutné databázi vytvořit; předpokládáme totiž, že zpočátku neexistuje. Pro tento účel se používá metoda klienta pojmenovaná create_collection:

create_collection(
    collection_name: str,
    dimension: Optional[int] = None,
    primary_field_name: str = 'id',
    id_type: str = 'int',
    vector_field_name: str = 'vector',
    metric_type: str = 'COSINE',
    auto_id: bool = False,
    timeout: Optional[float] = None,
    schema: Optional[pymilvus.orm.schema.CollectionSchema] = None,
    index_params: Optional[pymilvus.milvus_client.index.IndexParams] = None,
    **kwargs

Nastavíme tedy jméno databáze, počet dimenzí vektorů i metriku (L2):

# jméno databáze
COLLECTION_NAME = "milvus_db_1"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "L2"
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)

Výsledný skript realizující dnešní první demonstrační příklad bude vypadat následovně:

"""Připojení k vektorové databázi."""
 
from pymilvus import MilvusClient
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_1"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "L2"
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)

Struktura adresářů a souborů s prázdnou vektorovou databází

Po spuštění skriptu uvedeného v předchozí kapitole by se měl v pracovním adresáři objevit nový podadresář nazvaný hf_milvus_demo.db. Toto jméno odpovídá hodnotě parametru uri předávaného do konstruktoru MilvusClient. Struktura tohoto podadresáře vypadá následovně:

hf_milvus_demo.db/
├── collections
│   └── milvus_db_1
│       ├── manifest.json
│       ├── schema.json
│       └── wal
└── LOCK

V této chvíli je pro nás nejzajímavější obsah souboru manifest.json, ve kterém jsou uloženy metainformace o vektorové databázi, například použitá metrika:

{
  "active_wal_number": null,
  "current_seq": 0,
  "index_specs": {
    "vector": {
      "build_params": {},
      "field_name": "vector",
      "index_type": "AUTOINDEX",
      "metric_type": "L2",
      "search_params": {}
    }
  },
  "manifest_format_version": 2,
  "partitions": {
    "_default": {
      "data_files": [],
      "delta_files": []
    }
  },
  "schema_version": 1,
  "version": 1
}

Soubor nazvaný schema.json obsahuje, jak již ostatně jeho jméno napovídá, schéma vektorové databáze. Definovány jsou dva atributy („sloupce“) nazvané id (primární klíč) a vector, který obsahuje dvoudimenzionální vektory. Struktura databáze popsaná v JSONu sice nemusí být tak čitelná, jako SQL DDL, ale na druhou stranu je lépe strojově zpracovatelná:

{
  "collection_name": "milvus_db_1",
  "enable_dynamic_field": true,
  "fields": [
    {
      "auto_id": false,
      "default_value": null,
      "dim": null,
      "dtype": "int64",
      "element_type": null,
      "is_primary": true,
      "max_capacity": null,
      "max_length": null,
      "name": "id",
      "nullable": false
    },
    {
      "auto_id": false,
      "default_value": null,
      "dim": 2,
      "dtype": "float_vector",
      "element_type": null,
      "is_primary": false,
      "max_capacity": null,
      "max_length": null,
      "name": "vector",
      "nullable": false
    }
  ],
  "schema_format_version": 2,
  "version": 1
}

Vytvoření nové databáze při každém spuštění aplikace

Metoda create_collection, kterou jsme použili v předchozím demonstračním příkladu, se bude po každém spuštění skriptu snažit o inicializaci nové databáze, což nemusí být (minimálně pro první pokusy) ideální – zpočátku totiž budeme vyžadovat, aby byla vytvořená databáze v přesně definovaném stavu (a ne aby se do ní například po každém spuštění znovu zapsaly ty stejné vektory, jen s odlišným klíčem).

Z tohoto důvodu využijeme další vlastnost klienta databáze Milvus – metodou has_collection zjistíme, zda již databáze (resp. datová kolekce) existuje a pokud ano, metodou drop_collection ji odstraníme. Obě tyto metody se používají velmi snadno, protože jako svůj povinný parametr očekávají jméno kolekce:

has_collection(collection_name: str, timeout: Optional[float] = None, **kwargs)
method of pymilvus.milvus_client.milvus_client.MilvusClient instance

a:

drop_collection(collection_name: str, timeout: Optional[float] = None, **kwargs)
method of pymilvus.milvus_client.milvus_client.MilvusClient instance
    Delete the collection stored in this object

V praxi bude použití snadné, pouze je zapotřebí kolekci vhodně pojmenovat:

# jméno databáze
COLLECTION_NAME = "milvus_db_2"

V inicializační části programů provedeme test na existenci kolekce s jejím případným smazáním:

# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)

Výsledný skript může vypadat následovně:

"""Vytvoření nové databáze při každém spuštění skriptu."""
 
from pymilvus import MilvusClient
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_2"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "L2"
 
# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)

Struktura adresářů a souborů s dvojicí vektorových databází

Po spuštění předchozích skriptů by měl v adresáři hf_milvus_demo.db existovat podadresář collections a v něm by měly být vytvořeny dva podadresáře milvus_db1 a milvus_db2 (což jsou pochopitelně jména, která byla použita ve skriptech). Celá adresářová struktura i se všemi soubory bude vypadat takto:

hf_milvus_demo.db
├── collections
│   ├── milvus_db_1
│   │   ├── manifest.json
│   │   ├── schema.json
│   │   └── wal
│   └── milvus_db_2
│       ├── manifest.json
│       ├── schema.json
│       └── wal
└── LOCK

Obě databáze budou prázdné a jejich schémata budou totožná:

$ cat hf_milvus_demo.db/collections/milvus_db_1/schema.json
{
  "collection_name": "milvus_db_1",
  "enable_dynamic_field": true,
  "fields": [
    {
      "auto_id": false,
      "default_value": null,
      "dim": null,
      "dtype": "int64",
      "element_type": null,
      "is_primary": true,
      "max_capacity": null,
      "max_length": null,
      "name": "id",
      "nullable": false
    },
    {
      "auto_id": false,
      "default_value": null,
      "dim": 2,
      "dtype": "float_vector",
      "element_type": null,
      "is_primary": false,
      "max_capacity": null,
      "max_length": null,
      "name": "vector",
      "nullable": false
    }
  ],
  "schema_format_version": 2,
  "version": 1
}

Zápis vektorů s přidanými texty do databáze

Pro zjištění, jak je vlastně realizováno vyhledávání vektorů na základě jejich podobnosti, je pochopitelně nejdříve nutné naplnit databázi nějakými vektory doplněnými o další data a metadata. Do nové (a tedy prázdné) databáze vložíme patnáct dvouprvkových vektorů:

[-5, 5]
[-4, 3]
[-3, 5]
[3, –5]
[4, –3]
[5, –5]
[3, 3]
[3, 4]
[3, 5]
[4, 3]
[4, 4]
[4, 5]
[5, 3]
[5, 4]
[5, 5]

Definice vektorů v Pythonu (rozdělení na x-ové a y-ové souřadnice):

# x-ové souřadnice bodů v rovině
x = [-5, -4, -3,    3,  4,  5,   3, 3, 3,  4, 4, 4,  5, 5, 5]
 
# y-ové souřadnice bodů v rovině
y = [ 5,  3,  5,   -5, -3, -5,   3, 4, 5,  3, 4, 5,  3, 4, 5]
 

Na tyto 2D vektory se můžeme (i když to není zcela přesné) dívat jako na koncové souřadnice orientovaných šipek vycházejících z počátku kartézské soustavy souřadnic. V případě, že si tyto souřadnice vykreslíme, získáme následující graf (do kterého jsem doplnil numerické souřadnice u vybraných koncových bodů, viz tabulku uvedenou před tímto odstavcem):

                                       │ y
                                       │
                                       │
                                       │
                                       │                [5,5]
                     o       o         │          o   o   o
                                       │          o   o   o
                         o             │          o   o   o
                      [-4,3]           │        [3,3]   [5,3]
                                       │
─────────────────────────────────────[0,0]──────────────────────────────────────
                                       │                                       x
                                       │              o
                                       │
                                       │          o       o
                                       │                [5,-5]
                                       │
                                       │
                                       │
                                       │

Pro vložení kolekce vektorů (nikoli tedy jen jednoho vektoru) do databáze slouží metoda MilvusClient.insert. Povšimněte si, že je této metodě nutné mj. předat i data ve formě slovníku popř. seznamu slovníků:

insert(
    collection_name: str,
    data: Union[Dict, List[Dict]],
    timeout: Optional[float] = None,
    partition_name: Optional[str] = '',
    **kwargs
) -> Dict method of pymilvus.milvus_client.milvus_client.MilvusClient instance
    Insert data into the collection.
 
    If the Milvus Client was initiated without an existing Collection, the first dict passed
    in will be used to initiate the collection.
 
    Args:
        data (List[Dict[str, any]]): A list of dicts to pass in. If list not provided, will
            cast to list.
        timeout (float, optional): The timeout to use, will override init timeout. Defaults
            to None.
 
    Raises:
        DataNotMatchException: If the data has missing fields an exception will be thrown.
        MilvusException: General Milvus error on insert.
 
    Returns:
        Dict: Number of rows that were inserted and the inserted primary key list.

V praxi může být zápis realizován relativně snadno. Nejdříve si připravíme seznam s vektory doplněnými o další metainformace. Povšimněte si, že se do seznamu vkládají skutečně slovníky, konkrétně slovníky s klíči id, vector a text:

# příprava datové struktury pro zápis do databáze
data = []
 
for i in range(len(x)):
    vec = [x[i], y[i]]
    print(i, vec)
    # další záznam
    data.append({"id": i, "vector": vec, "text": f"vector [{x[i]}, {y[i]}]"})

Následně se celý seznam zapíše do databáze jedinou operací insert:

# provedení zápisu
insert_res = milvus_client.insert(collection_name=COLLECTION_NAME, data=data)
print("Insertions: ", insert_res["insert_count"])

Úplný zdrojový kód skriptu, který vytvoří novou databázi a vloží do ní patnáct vektorů, může vypadat následovně:

"""Zápis vektorů s přidanými texty do databáze."""
 
from pymilvus import MilvusClient
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_3"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "L2"
 
# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)
 
# x-ové souřadnice bodů v rovině
x = [-5, -4, -3,    3,  4,  5,   3, 3, 3,  4, 4, 4,  5, 5, 5]
 
# y-ové souřadnice bodů v rovině
y = [ 5,  3,  5,   -5, -3, -5,   3, 4, 5,  3, 4, 5,  3, 4, 5]
 
# příprava datové struktury pro zápis do databáze
data = []
 
for i in range(len(x)):
    vec = [x[i], y[i]]
    print(i, vec)
    # další záznam
    data.append({"id": i, "vector": vec, "text": f"vector [{x[i]}, {y[i]}]"})
 
# strukturu před uložením do databáze zobrazíme
print(data)
 
# provedení zápisu
insert_res = milvus_client.insert(collection_name=COLLECTION_NAME, data=data)
print("Insertions: ", insert_res["insert_count"])

Struktura výsledné databáze

Skript popsaný v předchozí kapitole běžným způsobem spustíme:

$ uv run milvus_db_3.py

Jednotlivé operace jsou vypisovány – konstrukce vektorů, výsledný seznam slovníků i výsledek zápisu obsahu seznamu slovníku do databáze:

0 [-5, 5]
1 [-4, 3]
2 [-3, 5]
3 [3, -5]
4 [4, -3]
5 [5, -5]
6 [3, 3]
7 [3, 4]
8 [3, 5]
9 [4, 3]
10 [4, 4]
11 [4, 5]
12 [5, 3]
13 [5, 4]
14 [5, 5]
[{'id': 0, 'vector': [-5, 5], 'text': 'vector [-5, 5]'}, {'id': 1, 'vector': [-4, 3], 'text': 'vector [-4, 3]'}, {'id': 2, 'vector': [-3, 5], 'text': 'vector [-3, 5]'}, {'id': 3, 'vector': [3, -5], 'text': 'vector [3, -5]'}, {'id': 4, 'vector': [4, -3], 'text': 'vector [4, -3]'}, {'id': 5, 'vector': [5, -5], 'text': 'vector [5, -5]'}, {'id': 6, 'vector': [3, 3], 'text': 'vector [3, 3]'}, {'id': 7, 'vector': [3, 4], 'text': 'vector [3, 4]'}, {'id': 8, 'vector': [3, 5], 'text': 'vector [3, 5]'}, {'id': 9, 'vector': [4, 3], 'text': 'vector [4, 3]'}, {'id': 10, 'vector': [4, 4], 'text': 'vector [4, 4]'}, {'id': 11, 'vector': [4, 5], 'text': 'vector [4, 5]'}, {'id': 12, 'vector': [5, 3], 'text': 'vector [5, 3]'}, {'id': 13, 'vector': [5, 4], 'text': 'vector [5, 4]'}, {'id': 14, 'vector': [5, 5], 'text': 'vector [5, 5]'}]
Insertions:  15

Stromová struktura adresáře hf_milvus_demo.db se „rozkošatěla“ do následující podoby:

hf_milvus_demo.db/
├── collections
│   ├── milvus_db_1
│   │   ├── manifest.json
│   │   ├── schema.json
│   │   └── wal
│   ├── milvus_db_2
│   │   ├── manifest.json
│   │   ├── schema.json
│   │   └── wal
│   └── milvus_db_3
│       ├── manifest.json
│       ├── manifest.json.prev
│       ├── partitions
│       │   └── _default
│       │       └── data
│       │           └── data_000001_000015.parquet
│       ├── schema.json
│       └── wal
└── LOCK

První dvě databáze/kolekce jsou prázdné, to již víme. Poslední databáze milvus_db3 ovšem obsahuje patnáct uložených vektorů. Změnil se především manifest.json, který kromě dalších informací obsahuje i cestu k souboru s obsahem databáze:

{
  "active_wal_number": 2,
  "current_seq": 15,
  "index_specs": {
    "vector": {
      "build_params": {},
      "field_name": "vector",
      "index_type": "AUTOINDEX",
      "metric_type": "L2",
      "search_params": {}
    }
  },
  "manifest_format_version": 2,
  "partitions": {
    "_default": {
      "data_files": [
        "data/data_000001_000015.parquet"
      ],
      "delta_files": []
    }
  },
  "schema_version": 1,
  "version": 2
}

Schéma zůstalo zachováno:

{
  "collection_name": "milvus_db_3",
  "enable_dynamic_field": true,
  "fields": [
    {
      "auto_id": false,
      "default_value": null,
      "dim": null,
      "dtype": "int64",
      "element_type": null,
      "is_primary": true,
      "max_capacity": null,
      "max_length": null,
      "name": "id",
      "nullable": false
    },
    {
      "auto_id": false,
      "default_value": null,
      "dim": 2,
      "dtype": "float_vector",
      "element_type": null,
      "is_primary": false,
      "max_capacity": null,
      "max_length": null,
      "name": "vector",
      "nullable": false
    }
  ],
  "schema_format_version": 2,
  "version": 1
}

Samotná data jsou uložena v (prozatím jediném) souboru, který má jméno data_000001_000015.parquet. Jak již název koncovky napovídá, jedná se o soubor s formátem (resp. se strukturou) nazvanou Apache Parquet, který mohou čtenáři znát například z nástroje Hadoop. S tímto formátem jsme se seznámili například v článku Komunikace se sloupcovými databázemi z jazyka Go: Parquet soubory.

Vyhledávání vektorů na základě jejich podobnosti

Nejdůležitější vlastností vektorových databází je podpora pro efektivní vyhledávání vektorů na základě jejich podobnosti (vector similarity search). Tato operace je pochopitelně podporována i databází Milvus. K dispozici je několik metod výpočtů podobnosti vektorů. Každá z těchto metod je založena na určité metrice. Podporované metriky jsou vypsány pod tímto odstavcem:

Metrika
Eukleidovská vzdálenost (teoreticky nejdůležitější metrika, ovšem její výpočet nemusí být příliš rychlý)
Skalární součin (jedna z nejdůležitějších matematických operací vůbec)
Porovnání výsledků výpočtu kosinu úhlu mezi vektory (normalizovaná varianta předchozí operace)
Hammingova vzdálenost (určena pro binární vektory, popíšeme si ji příště)
Jaccardův index (taktéž určena pro binární vektory, popíšeme si ji příště)

Samotné vyhledávání vektorů na základě jejich podobnosti je realizováno metodou MilvusClient.search, jejíž hlavička sice vypadá poměrně složitě, ale o to jednodušší je její reálné použití. Mnohdy si vystačíme pouze s parametry collection, data a limit:

search(
    collection_name: str,
    data: Union[List[list], list, NoneType] = None,
    filter: str = '',
    limit: int = 10,
    output_fields: Optional[List[str]] = None,
    search_params: Optional[dict] = None,
    timeout: Optional[float] = None,
    partition_names: Optional[List[str]] = None,
    anns_field: Optional[str] = None,
    ranker: Union[pymilvus.orm.schema.Function, pymilvus.orm.schema.FunctionScore, NoneType] = None,
    highlighter: Union[pymilvus.orm.schema.LexicalHighlighter, pymilvus.orm.schema.SemanticHighlighter, NoneType] = None,
    ids: Union[List[int], List[str], str, int, NoneType] = None,
    **kwargs
) -> List[List[dict]] method of pymilvus.milvus_client.milvus_client.MilvusClient instance
    Search for a query vector/vectors.
 
    In order for the search to process, a collection needs to have been either provided
    at init or data needs to have been inserted.

Skript realizující vyhledávání vektorů na základě jejich podobnosti

Výše zmíněnou metodu MilvusClient.search použijeme pro vyhledání čtyř vektorů, které jsou nejpodobnější vektoru [3, 3]:

# vyhledávaný vektor
vector_to_search = [3, 3]

Povšimněte si, jakým způsobem se tento vektor předává do metody MilvusClient.search. Kromě parametru data specifikujeme i počet vektorů, které se mají nalézt (limit), pochopitelně jméno kolekce (collection_name) a taktéž specifikace sloupců, které se mají vrátit (output_fields):

# pokusíme se nalézt čtyři nejbližší vektory
search_res = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=[vector_to_search],
    limit=4,
    search_params={"metric_type": SIMILARITY_METRICS, "params": {}},
    output_fields=["text"],
)

Samotné zpracování nalezených vektorů je již snadné:

# výpis výsledků
for vector in search_res[0]:
    print(vector)

Úplný skript, který naplní databázi patnácti vektory a posléze v nich vyhledá čtyři nejbližší vektory k vektoru [3, 3], vypadá takto:

"""Vyhledávání vektorů na základě jejich podobnosti."""
 
from pymilvus import MilvusClient
from pprint import pprint
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_4"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "L2"
 
# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)
 
# x-ové souřadnice bodů v rovině
x = [-5, -4, -3,    3,  4,  5,   3, 3, 3,  4, 4, 4,  5, 5, 5]
 
# y-ové souřadnice bodů v rovině
y = [ 5,  3,  5,   -5, -3, -5,   3, 4, 5,  3, 4, 5,  3, 4, 5]
 
# příprava datové struktury pro zápis do databáze
data = []
 
for i in range(len(x)):
    vec = [x[i], y[i]]
    print(i, vec)
    # další záznam
    data.append({"id": i, "vector": vec, "text": f"vector [{x[i]}, {y[i]}]"})
 
# strukturu před uložením do databáze zobrazíme
print(data)
 
# provedení zápisu
insert_res = milvus_client.insert(collection_name=COLLECTION_NAME, data=data)
print("Insertions: ", insert_res["insert_count"])
 
print("-" * 50)
print("Searching:")
 
# vyhledávaný vektor
vector_to_search = [3, 3]
 
# pokusíme se nalézt čtyři nejbližší vektory
search_res = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=[vector_to_search],
    limit=4,
    search_params={"metric_type": SIMILARITY_METRICS, "params": {}},
    output_fields=["text"],
)
 
# výpis výsledků
for vector in search_res[0]:
    print(vector)

Vizualizace získaných výsledků

Pokud skript, jehož zdrojový kód byl uveden v předchozí kapitole, spustíme, měly by se vypsat tyto výsledky:

Searching:
{'id': 6, 'distance': 0.0, 'entity': {'id': 6, 'text': 'vector [3, 3]'}}
{'id': 7, 'distance': 1.0, 'entity': {'id': 7, 'text': 'vector [3, 4]'}}
{'id': 9, 'distance': 1.0, 'entity': {'id': 9, 'text': 'vector [4, 3]'}}
{'id': 10, 'distance': 1.4142135381698608, 'entity': {'id': 10, 'text': 'vector [4, 4]'}}

Nejprve se vypíše klíč, následně vypočtená vzdálenost (ta je nulová, nebo jde o krok na x-ové ose, krok na y-ové ose popř. krok po úhlopříčce) a další data (v našem případě text) zapsaný do databáze.

Výsledky si pochopitelně můžeme vizualizovat v rovině, ostatně proto používáme vektory s pouhými dvěma dimenzemi. Tečkami jsou naznačeny koncové body NEnalezených vektorů, nulou, jedničkou nebo √2 pak koncové body vektorů vrácených (a hodnota odpovídá vzdálenosti):

                                       │ y
                                       │
                                       │
                                       │
                                       │                [5,5]
                     .       .         │          .   .   .
                                       │          1   √2  .
                         .             │          0   1   .
                      [-4,3]           │        [3,3]   [5,3]
                                       │
─────────────────────────────────────[0,0]──────────────────────────────────────
                                       │                                       x
                                       │              .
                                       │
                                       │          .       .
                                       │                [5,-5]
                                       │
                                       │
                                       │
                                       │

Použití odlišné metriky pro vyhledávání vektorů na základě jejich podobnosti

V předchozím demonstračním příkladu byla při hledání nejbližších vektorů použita metrika nazvaná L2, což značí eukleidovskou normu:

# použitá metrika
SIMILARITY_METRICS = "L2"

Podobnost vektorů se v tomto případě vypočte zobecněnou Pythagorovou větou – jako vzdálenost koncových bodů obou vektorů. Samozřejmě platí, že čím bližší jsou tyto koncové body, tím podobnější jsou i celé vektory.

Metrika je použita jak při konstrukci databáze:

# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)

Tak i při vyhledávání:

search_res = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=[vector_to_search],
    limit=4,
    search_params={"metric_type": SIMILARITY_METRICS, "params": {}},
    output_fields=["text"],
)

Ovšem můžeme použít i odlišné metriky, například metriku IP založenou na skalárním součinu (inner product):

# použitá metrika
SIMILARITY_METRICS = "IP"

Mezi další podporované metriky patří: COSINE (kosinus úhlu mezi vektory), Jaccard a Hamming.

Úprava skriptu: vyhledávání vektorů s využitím metriky skalárního součinu

Úprava našeho skriptu takovým způsobem, aby se při konstrukci databáze i při vyhledávání podobných vektorů použila odlišná metrika, je snadné, protože ve skriptu striktně používáme konstantu SIMILARITY_METRICS. „Přepnutí“ z L2 na IP je tedy triviální:

"""Vyhledávání vektorů na základě jejich podobnosti, použití odlišné metriky."""
 
from pymilvus import MilvusClient
from pprint import pprint
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_5"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "IP"
 
# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)
 
# x-ové souřadnice bodů v rovině
x = [-5, -4, -3,    3,  4,  5,   3, 3, 3,  4, 4, 4,  5, 5, 5]
 
# y-ové souřadnice bodů v rovině
y = [ 5,  3,  5,   -5, -3, -5,   3, 4, 5,  3, 4, 5,  3, 4, 5]
 
# příprava datové struktury pro zápis do databáze
data = []
 
for i in range(len(x)):
    vec = [x[i], y[i]]
    print(i, vec)
    # další záznam
    data.append({"id": i, "vector": vec, "text": f"vector [{x[i]}, {y[i]}]"})
 
# strukturu před uložením do databáze zobrazíme
print(data)
 
# provedení zápisu
insert_res = milvus_client.insert(collection_name=COLLECTION_NAME, data=data)
print("Insertions: ", insert_res["insert_count"])
 
print("-" * 50)
print("Searching:")
 
# vyhledávaný vektor
vector_to_search = [3, 3]
 
# pokusíme se nalézt čtyři nejbližší vektory
search_res = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=[vector_to_search],
    limit=4,
    search_params={"metric_type": SIMILARITY_METRICS, "params": {}},
    output_fields=["text"],
)
 
# výpis výsledků
for vector in search_res[0]:
    print(vector)

Výsledky ovšem nebudou korektní:

--------------------------------------------------
Searching:
{'id': 14, 'distance': 30.0, 'entity': {'id': 14, 'text': 'vector [5, 5]'}}
{'id': 11, 'distance': 27.0, 'entity': {'id': 11, 'text': 'vector [4, 5]'}}
{'id': 13, 'distance': 27.0, 'entity': {'id': 13, 'text': 'vector [5, 4]'}}
{'id': 8, 'distance': 24.0, 'entity': {'id': 8, 'text': 'vector [3, 5]'}}

Proč tomu tak je, si řekneme v navazující kapitole.

Metrika založená na skalárním součinu a normalizace vektorů

Výpočet metriky založené na skalárním součinu předpokládá, že vektory jsou již dopředu normalizovány, tj. že jejich délka je buď rovna jedné nebo nule. V praxi je tedy nutné již při konstrukci indexů použít normalizované vektory. Normalizace se provede relativně snadno (a zejména – pouze jedenkrát při vkládání vektorů do databáze, což je operace, která se provádí s velmi malou frekvencí):

for i in range(len(x)):
    vec = [x[i], y[i]]
    normalized = vec / np.linalg.norm(vec)
    print(i, normalized)
    # další záznam
    data.append({"id": i, "vector": normalized, "text": f"vector [{x[i]}, {y[i]}]"})

I vektor, ke kterému se hledají nejpodobnější vektory z databáze, musí být pochopitelně normalizován:

# vyhledávaný vektor
vector_to_search = [3, 3]
normalized = vec / np.linalg.norm(vec)
 
# pokusíme se nalézt čtyři nejbližší vektory
search_res = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=[normalized],
    limit=4,
    search_params={"metric_type": SIMILARITY_METRICS, "params": {}},
    output_fields=["text"],
)

Upravený skript pro práci s normalizovaným vektory a vyhledávání podobnosti na základě skalárního součinu, vypadá takto:

"""Vyhledávání vektorů na základě jejich podobnosti, použití odlišné metriky."""
 
import numpy as np
from pymilvus import MilvusClient
from pprint import pprint
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_6"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "IP"
 
# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)
 
# x-ové souřadnice bodů v rovině
x = [-5, -4, -3,    3,  4,  5,   3, 3, 3,  4, 4, 4,  5, 5, 5]
 
# y-ové souřadnice bodů v rovině
y = [ 5,  3,  5,   -5, -3, -5,   3, 4, 5,  3, 4, 5,  3, 4, 5]
 
# příprava datové struktury pro zápis do databáze
data = []
 
for i in range(len(x)):
    vec = [x[i], y[i]]
    normalized = vec / np.linalg.norm(vec)
    print(i, normalized)
    # další záznam
    data.append({"id": i, "vector": normalized, "text": f"vector [{x[i]}, {y[i]}]"})
 
# strukturu před uložením do databáze zobrazíme
print(data)
 
# provedení zápisu
insert_res = milvus_client.insert(collection_name=COLLECTION_NAME, data=data)
print("Insertions: ", insert_res["insert_count"])
 
print("-" * 50)
print("Searching:")
 
# vyhledávaný vektor
vector_to_search = [3, 3]
normalized = vec / np.linalg.norm(vec)
 
# pokusíme se nalézt čtyři nejbližší vektory
search_res = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=[normalized],
    limit=4,
    search_params={"metric_type": SIMILARITY_METRICS, "params": {}},
    output_fields=["text"],
)
 
# výpis výsledků
for vector in search_res[0]:
    print(vector)

Vliv normalizace vektorů při vyhledávání s využitím metriky založené na skalárním součinu

V případě, že jsou vektory v databázi normalizovány, normalizován je i vektor předávaný do metody MilvusClient.search a použije se skalární součin, budou nalezeny následující čtyři vektory:

--------------------------------------------------
Searching:
{'id': 6, 'distance': 0.9999999403953552, 'entity': {'id': 6, 'text': 'vector [3, 3]'}}
{'id': 10, 'distance': 0.9999999403953552, 'entity': {'id': 10, 'text': 'vector [4, 4]'}}
{'id': 14, 'distance': 0.9999999403953552, 'entity': {'id': 14, 'text': 'vector [5, 5]'}}
{'id': 13, 'distance': 0.9938837289810181, 'entity': {'id': 13, 'text': 'vector [5, 4]'}}
Poznámka: to jsou ovšem výsledky, které se odlišují od výsledků získaných na základě vzdálenosti koncových bodů (Eukleidova vzdálenost). Je to ovšem logické, protože normalizací ztratíme informaci o délce vektorů a porovnáváme pouze jejich sklon. Z tohoto pohledu jsou původní vektory [3, 3], [4, 4] a [5, 5] totožné:
Searching:
{'id': 6, 'distance': 0.0, 'entity': {'id': 6, 'text': 'vector [3, 3]'}}
{'id': 7, 'distance': 1.0, 'entity': {'id': 7, 'text': 'vector [3, 4]'}}
{'id': 9, 'distance': 1.0, 'entity': {'id': 9, 'text': 'vector [4, 3]'}}
{'id': 10, 'distance': 1.4142135381698608, 'entity': {'id': 10, 'text': 'vector [4, 4]'}}

Specifikace schématu databáze

Prozatím jsme novou databázi (v Milvusu nazývanou kolekci) vytvářeli bez toho, abychom specifikovali schéma tabulky.

# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
)

Schéma takto vytvořené databáze, jejíž tabulka obsahuje dva sloupce id a vector, je možné popsat následovně (to již známe):

  "fields": [
    {
      "auto_id": false,
      "default_value": null,
      "dim": null,
      "dtype": "int64",
      "element_type": null,
      "is_primary": true,
      "max_capacity": null,
      "max_length": null,
      "name": "id",
      "nullable": false
    },
    {
      "auto_id": false,
      "default_value": null,
      "dim": 2,
      "dtype": "float_vector",
      "element_type": null,
      "is_primary": false,
      "max_capacity": null,
      "max_length": null,
      "name": "vector",
      "nullable": false
    }
  ],

Nic nám ovšem nebrání v tom, aby vytvářená tabulka obsahovala další sloupce, lze specifikovat formát prvků vektorů atd. Schéma je specifikováno objektem, jehož (prázdnou) instanci získáme metodou MilvusClient.create_schema:

# konstrukce schématu databáze
schema = milvus_client.create_schema(
    auto_id=True,
    enable_dynamic_fields=True,
)

Specifikace jednotlivých sloupců se do schématu přidává metodou nazvanou add_field. Zadat je nutné především jméno sloupce, jeho typ a popř. i další vlastnosti (zda se jedná o primární klíč, dimenze vektorů atd.). Podrobnosti si řekneme příště, ovšem základní způsob specifikace sloupců je poměrně zřejmý z uvedené ukázky:

# specifikace jednotlivých sloupců
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, max_length=100)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=2)
schema.add_field(field_name="text", datatype=DataType.VARCHAR)

Tento objekt (schema) se předává do metody MilvusClient.create_collection v nepovinném parametru nazvaném schema:

# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
    # nastavení schématu
    schema=schema,
)

Schéma je samozřejmě nutné dodržet i při vkládání vektorů do databáze:

for i in range(len(x)):
    vec = [x[i], y[i]]
    print(i, vec)
    # další záznam
    data.append({"id": i, "vector": vec, "text": f"vector [{x[i]}, {y[i]}]"})

Demonstrační příklad: specifikace schématu databáze

V dnešním sedmém a současně i posledním demonstračním příkladu je ukázáno, jakým způsobem se vytvoří databáze s explicitně zadaným schématem, jak se do takové databáze vloží nové vektory a jak vypadá výsledek vyhledávání vektorů na základě jejich podobnosti:

"""Specifikace schématu databáze."""
 
from pymilvus import MilvusClient, DataType
 
# inicializace klienta pro připojení k vektorové databázi
milvus_client = MilvusClient(uri="./hf_milvus_demo.db")
 
# jméno databáze
COLLECTION_NAME = "milvus_db_4"
 
# počet dimenzí uložených vektorů
EMDEDDING_DIM = 2
 
# použitá metrika
SIMILARITY_METRICS = "foo"
 
# pokud datáze existuje, odstraníme ji
if milvus_client.has_collection(COLLECTION_NAME):
    milvus_client.drop_collection(COLLECTION_NAME)
 
# konstrukce schématu databáze
schema = milvus_client.create_schema(
    auto_id=True,
    enable_dynamic_fields=True,
)
 
# specifikace jednotlivých sloupců
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, max_length=100)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=2)
schema.add_field(field_name="text", datatype=DataType.VARCHAR)
 
# vytvoření databáze
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=EMDEDDING_DIM,
    metric_type=SIMILARITY_METRICS,
    consistency_level="Strong",
    # nastavení schématu
    schema=schema,
)
 
# x-ové souřadnice bodů v rovině
x = [-5, -4, -3,    3,  4,  5,   3, 3, 3,  4, 4, 4,  5, 5, 5]
 
# y-ové souřadnice bodů v rovině
y = [ 5,  3,  5,   -5, -3, -5,   3, 4, 5,  3, 4, 5,  3, 4, 5]
 
# příprava datové struktury pro zápis do databáze
data = []
 
for i in range(len(x)):
    vec = [x[i], y[i]]
    print(i, vec)
    # další záznam
    data.append({"id": i, "vector": vec, "text": f"vector [{x[i]}, {y[i]}]"})
 
# strukturu před uložením do databáze zobrazíme
print(data)
 
# provedení zápisu
insert_res = milvus_client.insert(collection_name=COLLECTION_NAME, data=data)
print("Insertions: ", insert_res["insert_count"])

Průběh operací po spuštění tohoto skriptu:

0 [-5, 5]
1 [-4, 3]
2 [-3, 5]
3 [3, -5]
4 [4, -3]
5 [5, -5]
6 [3, 3]
7 [3, 4]
8 [3, 5]
9 [4, 3]
10 [4, 4]
11 [4, 5]
12 [5, 3]
13 [5, 4]
14 [5, 5]
[{'id': 0, 'vector': [-5, 5], 'text': 'vector [-5, 5]'}, {'id': 1, 'vector': [-4, 3], 'text': 'vector [-4, 3]'}, {'id': 2, 'vector': [-3, 5], 'text': 'vector [-3, 5]'}, {'id': 3, 'vector': [3, -5], 'text': 'vector [3, -5]'}, {'id': 4, 'vector': [4, -3], 'text': 'vector [4, -3]'}, {'id': 5, 'vector': [5, -5], 'text': 'vector [5, -5]'}, {'id': 6, 'vector': [3, 3], 'text': 'vector [3, 3]'}, {'id': 7, 'vector': [3, 4], 'text': 'vector [3, 4]'}, {'id': 8, 'vector': [3, 5], 'text': 'vector [3, 5]'}, {'id': 9, 'vector': [4, 3], 'text': 'vector [4, 3]'}, {'id': 10, 'vector': [4, 4], 'text': 'vector [4, 4]'}, {'id': 11, 'vector': [4, 5], 'text': 'vector [4, 5]'}, {'id': 12, 'vector': [5, 3], 'text': 'vector [5, 3]'}, {'id': 13, 'vector': [5, 4], 'text': 'vector [5, 4]'}, {'id': 14, 'vector': [5, 5], 'text': 'vector [5, 5]'}]
Insertions:  15
Poznámka: povšimněte si formátu získaných výsledků, tj. seznamu slovníků.

A nakonec se ještě podívejme na schéma vytvořené vektorové databáze:

Školení Zabbix

  "fields": [
    {
      "auto_id": true,
      "default_value": null,
      "dim": null,
      "dtype": "int64",
      "element_type": null,
      "is_primary": true,
      "max_capacity": null,
      "max_length": null,
      "name": "id",
      "nullable": false
    },
    {
      "auto_id": false,
      "default_value": null,
      "dim": 2,
      "dtype": "float_vector",
      "element_type": null,
      "is_primary": false,
      "max_capacity": null,
      "max_length": null,
      "name": "vector",
      "nullable": false
    },
    {
      "auto_id": false,
      "default_value": null,
      "dim": null,
      "dtype": "varchar",
      "element_type": null,
      "is_primary": false,
      "max_capacity": null,
      "max_length": null,
      "name": "text",
      "nullable": false
    }
  ],

Repositář s demonstračními příklady

Všechny demonstrační příklady, které byly popsané v tomto článku, naleznete i v repositáři https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady i na projektový soubor obsahující všechny závislosti:

# Příklad Stručný popis Adresa příkladu
1 pyproject.toml projektový soubor použitý všemi demonstračními příklady https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/pyproject.toml
       
2 milvus_db1.py skript realizující připojení k (nové) vektorové databázi https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db1.py
3 milvus_db2.py vytvoření nové databáze při každém spuštění aplikace https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db2.py
4 milvus_db3.py zápis vektorů s přidanými texty do databáze https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db3.py
5 milvus_db4.py vyhledávání vektorů na základě podobnosti https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db4.py
6 milvus_db5.py využití odlišné metriky při vyhledávání (skalární součin) https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db5.py
7 milvus_db6.py vliv normalizace vektorů na výsledky vyhledávání založeného na skalárním součinu https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db6.py
8 milvus_db7.py specifikace schématu databáze https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db7.py
9 milvus_db8.py specifikace schématu databáze https://github.com/tisnik/most-popular-python-libs/blob/master/milvus/mil­vus_db8.py
       
10 milvus_help1.py zobrazení dokumentace ke třídě MilvusClient https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p1.pymilvus/
11 milvus_help2.py zobrazení dokumentace k metodě MilvusClient.create_collection https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p2.pymilvus/
12 milvus_help3.py zobrazení dokumentace k metodě MilvusClient.has_collection https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p3.pymilvus/
13 milvus_help4.py zobrazení dokumentace k metodě MilvusClient.drop_collection https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p4.pymilvus/
14 milvus_help5.py zobrazení dokumentace k metodě MilvusClient.insert https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p5.pymilvus/
15 milvus_help6.py zobrazení dokumentace k metodě MilvusClient.search https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p6.pymilvus/
16 milvus_help7.py zobrazení dokumentace k metodě MilvusClient.create_schema https://github.com/tisnik/most-popular-python-libs/blob/master/milvus_hel­p7.pymilvus/

Články o vektorových databázích i jejich využití při realizaci RAGu

Na stránkách Rootu jsme se s konceptem vektorových databází, vyhledávání vektorů na základě jejich podobnosti i s konstrukcí RAG několikrát setkali. Konkrétně se jedná o následující články:

  1. pgvector: vektorová databáze postavená na Postgresu
    https://www.root.cz/clanky/pgvector-vektorova-databaze-postavena-na-postgresu/
  2. Rozšíření PostgreSQL jménem pgvector, embedding a sémantické vyhledávání (1. část)
    https://www.root.cz/clanky/rozsireni-postgresql-jmenem-pgvector-embedding-a-semanticke-vyhledavani-1-cast/
  3. pgvector, embedding a sémantické vyhledávání: binární vektory
    https://www.root.cz/clanky/pgvector-embedding-a-semanticke-vyhledavani-binarni-vektory/
  4. pgvector, embedding a sémantické vyhledávání: sofistikovanější indexy a různé typy vektorů
    https://www.root.cz/clanky/pgvector-embedding-a-semanticke-vyhledavani-sofistikovanejsi-indexy-a-ruzne-typy-vektoru/
  5. SQLite-vec: vektorové rozšíření databáze SQLite
    https://www.root.cz/clanky/sqlite-vec-vektorove-rozsireni-databaze-sqlite/
  6. FAISS: knihovna pro rychlé a efektivní vyhledávání podobných vektorů
    https://www.root.cz/clanky/faiss-knihovna-pro-rychle-a-efektivni-vyhledavani-podobnych-vektoru/
  7. FAISS: knihovna pro rychlé a efektivní vyhledávání podobných vektorů (2. část)
    https://www.root.cz/clanky/faiss-knihovna-pro-rychle-a-efektivni-vyhledavani-podobnych-vektoru-2-cast/
  8. Knihovna FAISS a embedding: základ jazykových modelů
    https://www.root.cz/clanky/knihovna-faiss-a-embedding-zaklad-jazykovych-modelu/
  9. Knihovna FAISS a embedding: základ jazykových modelů (2. část)
    https://www.root.cz/clanky/knihovna-faiss-a-embedding-zaklad-jazykovych-modelu-2-cast/
  10. Komunikace se sloupcovými databázemi z jazyka Go: Parquet soubory
    https://www.root.cz/clanky/komunikace-se-sloupcovymi-databazemi-z-jazyka-go-parquet-soubory/

Odkazy na Internetu

  1. FAISS (Facebook AI Similarity Search)
    https://en.wikipedia.org/wiki/FAISS
  2. FAISS documentation
    https://faiss.ai/
  3. Introduction to Facebook AI Similarity Search (Faiss)
    https://www.pinecone.io/le­arn/series/faiss/faiss-tutorial/
  4. Faiss: Efficient Similarity Search and Clustering of Dense Vectors
    https://medium.com/@pankaj_pan­dey/faiss-efficient-similarity-search-and-clustering-of-dense-vectors-dace1df1e235
  5. Cosine Distance vs Dot Product vs Euclidean in vector similarity search
    https://medium.com/data-science-collective/cosine-distance-vs-dot-product-vs-euclidean-in-vector-similarity-search-227a6db32edb
  6. F16C
    https://en.wikipedia.org/wiki/F16C
  7. FP16 (AVX-512)
    https://en.wikipedia.org/wiki/AVX-512#FP16
  8. Top 8 Vector Databases in 2025: Features, Use Cases, and Comparisons
    https://synapsefabric.com/top-8-vector-databases-in-2025-features-use-cases-and-comparisons/
  9. Is FAISS a Vector Database? Complete Guide
    https://mljourney.com/is-faiss-a-vector-database-complete-guide/
  10. Vector database
    https://en.wikipedia.org/wi­ki/Vector_database
  11. Similarity search
    https://en.wikipedia.org/wi­ki/Similarity_search
  12. Nearest neighbor search
    https://en.wikipedia.org/wi­ki/Nearest_neighbor_search#Ap­proximation_methods
  13. Decoding Similarity Search with FAISS: A Practical Approach
    https://www.luminis.eu/blog/decoding-similarity-search-with-faiss-a-practical-approach/
  14. MetricType and distances
    https://github.com/facebo­okresearch/faiss/wiki/Metric­Type-and-distances
  15. RAG – Retrieval-augmented generation
    https://en.wikipedia.org/wi­ki/Retrieval-augmented_generation
  16. pgvector na GitHubu
    https://github.com/pgvector/pgvector
  17. Why we replaced Pinecone with PGVector
    https://www.confident-ai.com/blog/why-we-replaced-pinecone-with-pgvector
  18. PostgreSQL as VectorDB – Beginner Tutorial
    https://www.youtube.com/wat­ch?v=Ff3tJ4pJEa4
  19. What is a Vector Database? (neobsahuje odpověď na otázku v titulku :-)
    https://www.youtube.com/wat­ch?v=t9IDoenf-lo
  20. PGVector: Turn PostgreSQL Into A Vector Database
    https://www.youtube.com/wat­ch?v=j1QcPSLj7u0
  21. Milvus
    https://milvus.io/
  22. Vector Databases simply explained! (Embeddings & Indexes)
    https://www.youtube.com/wat­ch?v=dN0lsF2cvm4
  23. Vector databases are so hot right now. WTF are they?
    https://www.youtube.com/wat­ch?v=klTvEwg3oJ4
  24. Step-by-Step Guide to Installing “pgvector” and Loading Data in PostgreSQL
    https://medium.com/@besttechreads/step-by-step-guide-to-installing-pgvector-and-loading-data-in-postgresql-f2cffb5dec43
  25. Best 17 Vector Databases for 2025
    https://lakefs.io/blog/12-vector-databases-2023/
  26. Top 15 Vector Databases that You Must Try in 2025
    https://www.geeksforgeeks.org/top-vector-databases/
  27. Picking a vector database: a comparison and guide for 2023
    https://benchmark.vectorvi­ew.ai/vectordbs.html
  28. Top 9 Vector Databases as of Feburary 2025
    https://www.shakudo.io/blog/top-9-vector-databases
  29. What is a vector database?
    https://www.ibm.com/think/to­pics/vector-database
  30. SQL injection
    https://en.wikipedia.org/wi­ki/SQL_injection
  31. Cosine similarity
    https://en.wikipedia.org/wi­ki/Cosine_similarity
  32. Euclidean distance
    https://en.wikipedia.org/wi­ki/Euclidean_distance
  33. Dot product
    https://en.wikipedia.org/wi­ki/Dot_product
  34. Hammingova vzdálenost
    https://cs.wikipedia.org/wi­ki/Hammingova_vzd%C3%A1le­nost
  35. Jaccard index
    https://en.wikipedia.org/wi­ki/Jaccard_index
  36. Manhattanská metrika
    https://cs.wikipedia.org/wi­ki/Manhattansk%C3%A1_metri­ka
  37. FAISS (Facebook AI Similarity Search)
    https://en.wikipedia.org/wiki/FAISS
  38. FAISS documentation
    https://faiss.ai/
  39. Introduction to Facebook AI Similarity Search (Faiss)
    https://www.pinecone.io/le­arn/series/faiss/faiss-tutorial/
  40. Faiss: Efficient Similarity Search and Clustering of Dense Vectors
    https://medium.com/@pankaj_pan­dey/faiss-efficient-similarity-search-and-clustering-of-dense-vectors-dace1df1e235
  41. Cosine Distance vs Dot Product vs Euclidean in vector similarity search
    https://medium.com/data-science-collective/cosine-distance-vs-dot-product-vs-euclidean-in-vector-similarity-search-227a6db32edb
  42. F16C
    https://en.wikipedia.org/wiki/F16C
  43. FP16 (AVX-512)
    https://en.wikipedia.org/wiki/AVX-512#FP16
  44. Top 8 Vector Databases in 2025: Features, Use Cases, and Comparisons
    https://synapsefabric.com/top-8-vector-databases-in-2025-features-use-cases-and-comparisons/
  45. Is FAISS a Vector Database? Complete Guide
    https://mljourney.com/is-faiss-a-vector-database-complete-guide/
  46. FAISS and sentence-transformers in 5 Minutes
    https://www.stephendiehl.com/pos­ts/faiss/
  47. Sentence Transformer: Quickstart
    https://sbert.net/docs/qu­ickstart.html#sentence-transformer
  48. Sentence Transformers: Embeddings, Retrieval, and Reranking
    https://pypi.org/project/sentence-transformers/
  49. uv
    https://docs.astral.sh/uv/
  50. A Gentle Introduction to Retrieval Augmented Generation (RAG)
    https://wandb.ai/cosmo3769/RAG/re­ports/A-Gentle-Introduction-to-Retrieval-Augmented-Generation-RAG---Vmlldzo1MjM4Mjk1
  51. The Beginner’s Guide to Text Embeddings
    https://www.deepset.ai/blog/the-beginners-guide-to-text-embeddings
  52. What are Word Embeddings?
    https://www.youtube.com/wat­ch?v=wgfSDrqYMJ4
  53. How to choose an embedding model
    https://www.youtube.com/wat­ch?v=djp4205tHGU
  54. What is a Vector Database? Powering Semantic Search & AI Applications
    https://www.youtube.com/wat­ch?v=gl1r1XV0SLw
  55. How do Sentence Transformers differ from traditional word embedding models like Word2Vec or GloVe?
    https://zilliz.com/ai-faq/how-do-sentence-transformers-differ-from-traditional-word-embedding-models-like-word2vec-or-glove
  56. BERT (language model)
    https://en.wikipedia.org/wi­ki/BERT_(language_model)
  57. Levenštejnova vzdálenost
    https://cs.wikipedia.org/wi­ki/Leven%C5%A1tejnova_vzd%C3%A1le­nost
  58. pgvector Tutorial: Integrate Vector Search into PostgreSQL
    https://www.datacamp.com/tu­torial/pgvector-tutorial
  59. pgvectorbench
    https://github.com/pgvector­Bench/pgvectorBench
  60. pgvector 0.4.0 performance
    https://supabase.com/blog/pgvector-performance
  61. IVFFlat (Inverted File Flat) Index
    https://skyzh.github.io/write-you-a-vector-db/cpp-05-ivfflat.html
  62. HNSW (Hierarchical Navigable Small Worlds) Index
    https://skyzh.github.io/write-you-a-vector-db/cpp-06–02-hnsw.html
  63. Vector Indexing: Your Guide to Understanding and Implementation
    https://www.teradata.com/insights/ai-and-machine-learning/what-is-vector-index
  64. Vector Indexing Explained: Everything You Need to Know
    https://www.datastax.com/guides/what-is-a-vector-index
  65. Voroného diagram
    https://cs.wikipedia.org/wi­ki/Voron%C3%A9ho_diagram
  66. Matplotlib Home Page
    http://matplotlib.org/
  67. matplotlib (Wikipedia)
    https://en.wikipedia.org/wi­ki/Matplotlib
  68. The Case Against pgvector
    https://alex-jacobs.com/posts/the-case-against-pgvector/
  69. Embedding Quantization
    https://github.com/huggin­gface/sentence-transformers/blob/main/exam­ples/sentence_transformer/ap­plications/embedding-quantization/README.md
  70. Binary and Scalar Embedding Quantization for Significantly Faster & Cheaper Retrieval
    https://huggingface.co/blog/embedding-quantization
  71. Embedding Quantization
    https://www.sbert.net/exam­ples/sentence_transformer/ap­plications/embedding-quantization/README.html
  72. Understanding Quantization in Embedding Models
    https://www.linkedin.com/pul­se/understanding-quantization-embedding-models-rob-murphy-v5gue/
  73. Optimization of embeddings storage for RAG systems using quantization and dimensionality reduction techniques
    https://arxiv.org/html/2505.00105v1
  74. Apache Parquet
    https://en.wikipedia.org/wi­ki/Apache_Parquet
  75. parquet-java
    https://github.com/apache/parquet-java
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.