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
- Instalace balíčku pymilvus a jeho závislostí
- Skript realizující připojení k (nové) vektorové databázi
- Struktura adresářů a souborů s prázdnou vektorovou databází
- Vytvoření nové databáze při každém spuštění aplikace
- Struktura adresářů a souborů s dvojicí vektorových databází
- Zápis vektorů s přidanými texty do databáze
- Struktura výsledné databáze
- Vyhledávání vektorů na základě jejich podobnosti
- Skript realizující vyhledávání vektorů na základě jejich podobnosti
- Vizualizace získaných výsledků
- Použití odlišné metriky pro vyhledávání vektorů na základě jejich podobnosti
- Úprava skriptu: vyhledávání vektorů s využitím metriky skalárního součinu
- Metrika založená na skalárním součinu a normalizace vektorů
- Vliv normalizace vektorů při vyhledávání s využitím metriky založené na skalárním součinu
- Specifikace schématu databáze
- Demonstrační příklad: specifikace schématu databáze
- Repositář s demonstračními příklady
- Články o vektorových databázích i jejich využití při realizaci RAGu
- 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).
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`
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
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]'}}
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
A nakonec se ještě podívejme na schéma vytvořené vektorové databáze:
"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:
Č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:
- pgvector: vektorová databáze postavená na Postgresu
https://www.root.cz/clanky/pgvector-vektorova-databaze-postavena-na-postgresu/ - 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/ - pgvector, embedding a sémantické vyhledávání: binární vektory
https://www.root.cz/clanky/pgvector-embedding-a-semanticke-vyhledavani-binarni-vektory/ - 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/ - SQLite-vec: vektorové rozšíření databáze SQLite
https://www.root.cz/clanky/sqlite-vec-vektorove-rozsireni-databaze-sqlite/ - 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/ - 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/ - Knihovna FAISS a embedding: základ jazykových modelů
https://www.root.cz/clanky/knihovna-faiss-a-embedding-zaklad-jazykovych-modelu/ - 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/ - 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
- FAISS (Facebook AI Similarity Search)
https://en.wikipedia.org/wiki/FAISS - FAISS documentation
https://faiss.ai/ - Introduction to Facebook AI Similarity Search (Faiss)
https://www.pinecone.io/learn/series/faiss/faiss-tutorial/ - Faiss: Efficient Similarity Search and Clustering of Dense Vectors
https://medium.com/@pankaj_pandey/faiss-efficient-similarity-search-and-clustering-of-dense-vectors-dace1df1e235 - 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 - F16C
https://en.wikipedia.org/wiki/F16C - FP16 (AVX-512)
https://en.wikipedia.org/wiki/AVX-512#FP16 - 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/ - Is FAISS a Vector Database? Complete Guide
https://mljourney.com/is-faiss-a-vector-database-complete-guide/ - Vector database
https://en.wikipedia.org/wiki/Vector_database - Similarity search
https://en.wikipedia.org/wiki/Similarity_search - Nearest neighbor search
https://en.wikipedia.org/wiki/Nearest_neighbor_search#Approximation_methods - Decoding Similarity Search with FAISS: A Practical Approach
https://www.luminis.eu/blog/decoding-similarity-search-with-faiss-a-practical-approach/ - MetricType and distances
https://github.com/facebookresearch/faiss/wiki/MetricType-and-distances - RAG – Retrieval-augmented generation
https://en.wikipedia.org/wiki/Retrieval-augmented_generation - pgvector na GitHubu
https://github.com/pgvector/pgvector - Why we replaced Pinecone with PGVector
https://www.confident-ai.com/blog/why-we-replaced-pinecone-with-pgvector - PostgreSQL as VectorDB – Beginner Tutorial
https://www.youtube.com/watch?v=Ff3tJ4pJEa4 - What is a Vector Database? (neobsahuje odpověď na otázku v titulku :-)
https://www.youtube.com/watch?v=t9IDoenf-lo - PGVector: Turn PostgreSQL Into A Vector Database
https://www.youtube.com/watch?v=j1QcPSLj7u0 - Milvus
https://milvus.io/ - Vector Databases simply explained! (Embeddings & Indexes)
https://www.youtube.com/watch?v=dN0lsF2cvm4 - Vector databases are so hot right now. WTF are they?
https://www.youtube.com/watch?v=klTvEwg3oJ4 - 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 - Best 17 Vector Databases for 2025
https://lakefs.io/blog/12-vector-databases-2023/ - Top 15 Vector Databases that You Must Try in 2025
https://www.geeksforgeeks.org/top-vector-databases/ - Picking a vector database: a comparison and guide for 2023
https://benchmark.vectorview.ai/vectordbs.html - Top 9 Vector Databases as of Feburary 2025
https://www.shakudo.io/blog/top-9-vector-databases - What is a vector database?
https://www.ibm.com/think/topics/vector-database - SQL injection
https://en.wikipedia.org/wiki/SQL_injection - Cosine similarity
https://en.wikipedia.org/wiki/Cosine_similarity - Euclidean distance
https://en.wikipedia.org/wiki/Euclidean_distance - Dot product
https://en.wikipedia.org/wiki/Dot_product - Hammingova vzdálenost
https://cs.wikipedia.org/wiki/Hammingova_vzd%C3%A1lenost - Jaccard index
https://en.wikipedia.org/wiki/Jaccard_index - Manhattanská metrika
https://cs.wikipedia.org/wiki/Manhattansk%C3%A1_metrika - FAISS (Facebook AI Similarity Search)
https://en.wikipedia.org/wiki/FAISS - FAISS documentation
https://faiss.ai/ - Introduction to Facebook AI Similarity Search (Faiss)
https://www.pinecone.io/learn/series/faiss/faiss-tutorial/ - Faiss: Efficient Similarity Search and Clustering of Dense Vectors
https://medium.com/@pankaj_pandey/faiss-efficient-similarity-search-and-clustering-of-dense-vectors-dace1df1e235 - 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 - F16C
https://en.wikipedia.org/wiki/F16C - FP16 (AVX-512)
https://en.wikipedia.org/wiki/AVX-512#FP16 - 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/ - Is FAISS a Vector Database? Complete Guide
https://mljourney.com/is-faiss-a-vector-database-complete-guide/ - FAISS and sentence-transformers in 5 Minutes
https://www.stephendiehl.com/posts/faiss/ - Sentence Transformer: Quickstart
https://sbert.net/docs/quickstart.html#sentence-transformer - Sentence Transformers: Embeddings, Retrieval, and Reranking
https://pypi.org/project/sentence-transformers/ - uv
https://docs.astral.sh/uv/ - A Gentle Introduction to Retrieval Augmented Generation (RAG)
https://wandb.ai/cosmo3769/RAG/reports/A-Gentle-Introduction-to-Retrieval-Augmented-Generation-RAG---Vmlldzo1MjM4Mjk1 - The Beginner’s Guide to Text Embeddings
https://www.deepset.ai/blog/the-beginners-guide-to-text-embeddings - What are Word Embeddings?
https://www.youtube.com/watch?v=wgfSDrqYMJ4 - How to choose an embedding model
https://www.youtube.com/watch?v=djp4205tHGU - What is a Vector Database? Powering Semantic Search & AI Applications
https://www.youtube.com/watch?v=gl1r1XV0SLw - 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 - BERT (language model)
https://en.wikipedia.org/wiki/BERT_(language_model) - Levenštejnova vzdálenost
https://cs.wikipedia.org/wiki/Leven%C5%A1tejnova_vzd%C3%A1lenost - pgvector Tutorial: Integrate Vector Search into PostgreSQL
https://www.datacamp.com/tutorial/pgvector-tutorial - pgvectorbench
https://github.com/pgvectorBench/pgvectorBench - pgvector 0.4.0 performance
https://supabase.com/blog/pgvector-performance - IVFFlat (Inverted File Flat) Index
https://skyzh.github.io/write-you-a-vector-db/cpp-05-ivfflat.html - HNSW (Hierarchical Navigable Small Worlds) Index
https://skyzh.github.io/write-you-a-vector-db/cpp-06–02-hnsw.html - Vector Indexing: Your Guide to Understanding and Implementation
https://www.teradata.com/insights/ai-and-machine-learning/what-is-vector-index - Vector Indexing Explained: Everything You Need to Know
https://www.datastax.com/guides/what-is-a-vector-index - Voroného diagram
https://cs.wikipedia.org/wiki/Voron%C3%A9ho_diagram - Matplotlib Home Page
http://matplotlib.org/ - matplotlib (Wikipedia)
https://en.wikipedia.org/wiki/Matplotlib - The Case Against pgvector
https://alex-jacobs.com/posts/the-case-against-pgvector/ - Embedding Quantization
https://github.com/huggingface/sentence-transformers/blob/main/examples/sentence_transformer/applications/embedding-quantization/README.md - Binary and Scalar Embedding Quantization for Significantly Faster & Cheaper Retrieval
https://huggingface.co/blog/embedding-quantization - Embedding Quantization
https://www.sbert.net/examples/sentence_transformer/applications/embedding-quantization/README.html - Understanding Quantization in Embedding Models
https://www.linkedin.com/pulse/understanding-quantization-embedding-models-rob-murphy-v5gue/ - Optimization of embeddings storage for RAG systems using quantization and dimensionality reduction techniques
https://arxiv.org/html/2505.00105v1 - Apache Parquet
https://en.wikipedia.org/wiki/Apache_Parquet - parquet-java
https://github.com/apache/parquet-java
