Obsah
1. Knihovna FAISS a embedding: základ jazykových modelů (2. část)
2. Úprava projektu – přidání nových závislostí
3. Datová sada s jedním milionem anglických vět
4. Získání vybrané datové sady polygraf-ai/human-sentences-1M-sample-v2
5. Slovník s datovými sadami vs. jedna datová sada
6. Konstrukce běžného Pythonovského seznamu s větami
7. Hledání nejpodobnějších vět v celé datové sadě
8. Krátké připomenutí: vyhledávání na základě výrazů s využitím sémantické podobnosti
9. Využití celé datové sady pro sémantické vyhledávání
10. Úplný zdrojový kód demonstračního příkladu
11. Refaktoring pro lepší čitelnost a další rozšiřování funkcionality
12. Výsledky získané demonstračním příkladem
13. Rychlost sémantického vyhledávání
14. Rychlost embeddingu i konstrukce indexu
16. Vektory s prvky typu float16 nebo bfloat16
18. Velikost sady vektorů i indexu při použití prvků typu float32, float16 a bfloat16
19. Repositář s demonstračními příklady
1. Knihovna FAISS a embedding: základ jazykových modelů (2. část)
V předchozím článku jsme si ukázali jeden dosti typický způsob využití knihovny FAISS. S využitím FAISSu a vhodným způsobem „vektorizovaného“ textu je totiž možné zajistit takzvané sémantické vyhledávání, které není založeno na (většinou dosti triviální) textové podobě či podobě tokenizovaného textu, ale na významu, které věty či delší texty obsahují. Základem je přitom převod původních textů s využitím vhodného modelu do podoby vektorů pevné délky (typicky se jedná o délky 256, 384, 512, 768), přičemž do hodnot konkrétních prvků je nějakým způsobem promítnuta sémantika (jak konkrétně či naopak obecně je to provedeno, do značné míry záleží na použitém modelu, kterých dnes existuje minimálně několik desítek, spíše však několik set).
Minule obsahovala naše „textová databáze“ pouze přibližně deset vět. Dnes si vyzkoušíme, jak se FAISS a taktéž knihovna Sentence-Transformers chová v situaci, když použijeme datovou sadu s mnohem větším počtem vět. Konkrétně využijeme sadu s přibližně milionem anglických vět. Při takovém rozsahu dat již bude zajímavé sledovat výkonnost obou zmíněných knihoven. A taktéž bude zajímavé zjistit, jak se vlastně změní velikost modelu v případě, že prvky vektorů (po vektorizaci textu) budou typu float16 nebo bfloat16 a nikoli float32 (což je výchozí typ).
2. Úprava projektu – přidání nových závislostí
Ještě před tím, než si ukážeme další vlastnosti knihoven Faiss i sentence-transformers, je nutné provést úpravu projektu. Přidáme do něj další závislosti, konkrétně knihovny nazvané datasets a matplotlib. To se provede snadno. Buď příkazy:
uv add datasets uv add matplotlib
Nebo lze alternativně použít správce balíčků PDM:
uv add datasets uv add matplotlib
Projektový soubor pyproject.toml by nyní měl vypadat následovně:
[project]
name = "sentence-transformer"
version = "0.1.0"
description = "Sentence transformer demos"
authors = [
{name = "Pavel Tisnovsky", email = "ptisnovs@redhat.com"},
]
dependencies = [
"datasets&=4.0.0",
"faiss-cpu&=1.11.0.post1",
"matplotlib&=3.10.5",
"sentence-transformers&=5.0.0",
]
requires-python = "==3.12.*"
readme = "README.md"
license = {text = "MIT"}
[tool.pdm]
distribution = false
3. Datová sada s jedním milionem anglických vět
V demonstračních příkladech, které jsme si ukázali v předchozím článku, se pracovalo pouze s minimalistickou „databází“ textů, která se skládala pouze z osmi vět, což skutečně při práci s reálným mluveným jazykem není mnoho:
sentences = [
"The rain in Spain falls mainly on the plain",
"The tesselated polygon is a special type of polygon",
"The quick brown fox jumps over the lazy dog",
"To be or not to be, that is the question",
"It is a truth universally acknowledged...",
"How old are you?",
"The goat ran down the hill"
]
Dnes již budeme pracovat s mnohem větší databází. Konkrétně se bude jednat o datovou sadu polygraf-ai/human-sentences-1M-sample-v2 obsahující jeden milion anglických vět. Na tomto místě je vhodné poznamenat, že se stále jedná o relativně malou datovou sadu (například pro trénink LLM je naprosto nedostačující), ovšem pro otestování základních vlastností knihoven Faiss a sentence-transformers bude její velikost dostačující. Navíc je práce s touto datovou sadou relativně rychlá.
4. Získání vybrané datové sady polygraf-ai/human-sentences-1M-sample-v2
Datovou sadu polygraf-ai/human-sentences-1M-sample-v2 není nutné stahovat ručně, protože tuto funkci zajišťuje přímo knihovna dataset. Postačuje pouze zavolat funkci load_dataset a předat jí jednoznačný identifikátor datové sady. Knihovna automaticky zjistí, zda je datová sada dostupná na lokálním úložišti a pokud tomu tak není, provede její stažení:
from datasets import load_dataset dataset_id = "polygraf-ai/human-sentences-1M-sample-v2" dataset = load_dataset(dataset_id) print(dataset)
Při prvním spuštění tohoto skriptu je patrné, že stažení opravdu proběhlo (cca 100 MB!):
README.md: 100%|███████████████████████████████████████████████████████████████████████████████████████| 317/317 [00:00<00:00, 1.31MB/s]
train-00000-of-00001.parquet: 100%|██████████████████████████████████████████████████████████████████| 100M/100M [00:09<00:00, 10.1MB/s]
Generating train split: 100%|████████████████████████████████████████████████████████| 997593/997593 [00:01<00:00, 926163.87 examples/s]
DatasetDict({
train: Dataset({
features: ['text', 'source'],
num_rows: 997593
})
})
Po každém dalším spuštění skriptu se pouze zobrazí informace o datové sadě:
DatasetDict({
train: Dataset({
features: ['text', 'source'],
num_rows: 997593
})
})
$ ls -lah human-sentences-1_m-sample-v2-train.arrow -rw-r--r--. 1 ptisnovs ptisnovs 145M Jul 31 18:46 human-sentences-1_m-sample-v2-train.arrow
5. Slovník s datovými sadami vs. jedna datová sada
Předchozí skript by měl po svém spuštění vypsat informaci o tom, že ve skutečnosti nenačetl a nevrátil pouze jedinou datovou sadu, ale celý slovník datových sad s jediným prvkem:
DatasetDict({
train: Dataset({
features: ['text', 'source'],
num_rows: 997593
})
})
Sadu nazvanou train získáme snadno – předáním pojmenovaného parametru split=„train“ funkci load_dataset:
from datasets import load_dataset dataset_id = "polygraf-ai/human-sentences-1M-sample-v2" dataset = load_dataset(dataset_id, split="train") print(dataset.features)
Po spuštění tohoto skriptu by se měly vypsat informace o sloupcích v tabulce, ve které je datová sada uložena:
{'text': Value('string'), 'source': Value('string')}
6. Konstrukce běžného Pythonovského seznamu s větami
Ukažme si ještě jeden mezikrok, který vlastně v praxi není nezbytně nutné provádět, protože je výpočetně i paměťově náročný. Nicméně je vhodné vědět, že stažená datová sada není nějakým „magickým objektem“, ale skutečným zdrojem dat. Konkrétně si necháme z datové sady vygenerovat běžný Pythonovský seznam se všemi větami (v čisté textové podobě):
from datasets import load_dataset
dataset_id = "polygraf-ai/human-sentences-1M-sample-v2"
dataset = load_dataset(dataset_id, split="train")
print("Building sentences")
sentences = [sentence for sentence in dataset["text"]]
print(f"{len(sentences)} sentences created")
Výsledek získaný po určité době (jednotky až desítky sekund):
Building sentences 997593 sentences created
Počet vět transformovaných do seznamu lze řídit s využitím operace řezu (slice), a to ještě před vytvořením seznamu:
from datasets import load_dataset
dataset_id = "polygraf-ai/human-sentences-1M-sample-v2"
dataset = load_dataset(dataset_id, split="train")
print("Building sentences")
sentences = [sentence for sentence in dataset["text"][0:100]]
print(f"{len(sentences)} sentences created")
Nyní získáme výsledky prakticky okamžitě:
Building sentences 100 sentences created
7. Hledání nejpodobnějších vět v celé datové sadě
V navazujících kapitolách si ukážeme, jakým způsobem je možné provádět vyhledávání vět na základě podobnosti v rámci celé datové sady s přibližně jedním milionem vět. Opět je však nutné zdůraznit, že 1000000 vět sice může vypadat jako velmi vysoká hodnota, ovšem v praxi se mnohdy pracuje i s (mnohem) většími datovými sadami. Typickým příkladem je trénink velkých jazykových modelů, což je však téma na samostatné články.
Na druhou stranu je ovšem tato hodnota již dostatečně vysoká na to, aby byly jednotlivé kroky zpracování časově náročné. Z tohoto důvodu si otestujeme rychlost (nebo spíše pomalost) vektorizace textů (embedding), rychlost konstrukce indexu knihovnou FAISS a samozřejmě i rychlost vyhledávání s využitím tohoto indexu.
8. Krátké připomenutí: vyhledávání na základě výrazů s využitím sémantické podobnosti
Jen pro připomenutí si ukažme demonstrační příklad z předchozího článku. V tomto příkladu jsme si nechali zvoleným embedding modelem „vektorizovat“ sedm vět, poté jsme knihovnou FAISS z těchto vektorů zkonstruovali index a následně jsme tento index použili při vyhledávání výrazů či celých vět na základě jejich sémantické podobnosti s původními větami:
from sentence_transformers import SentenceTransformer
import faiss
model = SentenceTransformer("paraphrase-MiniLM-L6-v2")
print(model)
sentences = [
"The rain in Spain falls mainly on the plain",
"The tesselated polygon is a special type of polygon",
"The quick brown fox jumps over the lazy dog",
"To be or not to be, that is the question",
"It is a truth universally acknowledged...",
"How old are you?",
"The goat ran down the hill"
]
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
similarities = model.similarity(embeddings, embeddings)
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
def find_similar_sentences(query_sentence, k):
query_embedding = model.encode([query_sentence])
distances, indices = index.search(query_embedding, k)
print("-"*40)
print(f"Query: {query_sentence}")
print(f"Most {k} similar sentences:")
for i, idx in enumerate(indices[0]):
print(f"{i + 1}: {sentences[idx]} (Distance: {distances[0][i]})")
find_similar_sentences("Shakespeare", 3)
find_similar_sentences("animal", 3)
find_similar_sentences("geometry", 3)
find_similar_sentences("weather", 3)
Příklad výsledků získaných po spuštění tohoto demonstračního příkladu:
SentenceTransformer(
(0): Transformer({'max_seq_length': 128, 'do_lower_case': False, 'architecture': 'BertModel'})
(1): Pooling({'word_embedding_dimension': 384, 'pooling_mode_cls_token': False, 'pooling_mode_mean_tokens': True, 'pooling_mode_max_tokens': False, 'pooling_mode_mean_sqrt_len_tokens': False, 'pooling_mode_weightedmean_tokens': False, 'pooling_mode_lasttoken': False, 'include_prompt': True})
)
Embeddings shape: (7, 384)
Index: 7
----------------------------------------
Query: Shakespeare
Most 3 similar sentences:
1: To be or not to be, that is the question (Distance: 83.53305053710938)
2: The tesselated polygon is a special type of polygon (Distance: 112.60221862792969)
3: The rain in Spain falls mainly on the plain (Distance: 114.61812591552734)
----------------------------------------
Query: animal
Most 3 similar sentences:
1: The goat ran down the hill (Distance: 67.3703384399414)
2: The quick brown fox jumps over the lazy dog (Distance: 68.25883483886719)
3: To be or not to be, that is the question (Distance: 82.82962036132812)
----------------------------------------
Query: geometry
Most 3 similar sentences:
1: The tesselated polygon is a special type of polygon (Distance: 51.57851791381836)
2: To be or not to be, that is the question (Distance: 91.08709716796875)
3: The goat ran down the hill (Distance: 109.95413208007812)
----------------------------------------
Query: weather
Most 3 similar sentences:
1: The rain in Spain falls mainly on the plain (Distance: 73.53900146484375)
2: To be or not to be, that is the question (Distance: 86.14794921875)
3: How old are you? (Distance: 101.28636169433594)
9. Využití celé datové sady pro sémantické vyhledávání
Podívejme se nyní, jak se datová sada polygraf-ai/human-sentences-1M-sample-v2 využije v praxi pro embedding i pro tvorbu indexu pro knihovnu FAISS. Celý skript je rozdělen do několika samostatných kroků.
V prvním kroku inicializujeme model, jenž bude využitý pro embedding, tedy pro vektorizaci celé datové sady:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("paraphrase-MiniLM-L6-v2")
print(model)
V dalším kroku načteme, stejně jako v předchozích kapitolách, datovou sadu s cca jedním milionem vět:
from datasets import load_dataset
dataset = load_dataset("polygraf-ai/human-sentences-1M-sample-v2", split="train")
print(dataset)
Převedeme věty do formy běžného seznamu (můžeme i odstranit řez a převést všechny věty):
sentences = [sentence for sentence in dataset["text"][0:1000]]
print(f"{len(sentences)} sentences created")
Dále si necháme knihovnou Sentence-transformers vytvořit vektorizovanou formu vět (embedding):
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
Zbývá předposlední krok – tvorba FAISS indexu:
import faiss
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
Ve chvíli, kdy je index vytvořen, již můžeme v celé databázi jednoho milionu vět provádět sémantické vyhledávání:
def find_similar_sentences(query_sentence, k):
query_embedding = model.encode([query_sentence])
distances, indices = index.search(query_embedding, k)
print("-"*40)
print(f"Query: {query_sentence}")
print(f"Most {k} similar sentences:")
for i, idx in enumerate(indices[0]):
print(f"{i + 1}: {sentences[idx]} (Distance: {distances[0][i]})")
find_similar_sentences("city", 3)
find_similar_sentences("animal", 3)
find_similar_sentences("geometry", 3)
find_similar_sentences("weather", 3)
find_similar_sentences("game", 3)
find_similar_sentences("school", 3)
10. Úplný zdrojový kód demonstračního příkladu
Úplný zdrojový kód demonstračního příkladu popsaného v předchozí kapitole vypadá následovně:
from sentence_transformers import SentenceTransformer
import faiss
from datasets import load_dataset
model = SentenceTransformer("paraphrase-MiniLM-L6-v2")
print(model)
dataset = load_dataset("polygraf-ai/human-sentences-1M-sample-v2", split="train")
print(dataset)
sentences = [sentence for sentence in dataset["text"][0:1000]]
print(f"{len(sentences)} sentences created")
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
def find_similar_sentences(query_sentence, k):
query_embedding = model.encode([query_sentence])
distances, indices = index.search(query_embedding, k)
print("-"*40)
print(f"Query: {query_sentence}")
print(f"Most {k} similar sentences:")
for i, idx in enumerate(indices[0]):
print(f"{i + 1}: {sentences[idx]} (Distance: {distances[0][i]})")
find_similar_sentences("city", 3)
find_similar_sentences("animal", 3)
find_similar_sentences("geometry", 3)
find_similar_sentences("weather", 3)
find_similar_sentences("game", 3)
find_similar_sentences("school", 3)
11. Refaktoring pro lepší čitelnost a další rozšiřování funkcionality
Demonstrační příklad z předchozí kapitoly je sice funkční, ale není příliš čitelný ani rozšiřitelný. Z těchto důvodů ho nepatrně přepíšeme takovým způsobem, že každý krok bude realizován ve zvláštní funkci. Takto upravený zdrojový kód bude použitelný i pro další účely – měření času, benchmarky, zjištění velikosti vektorizovaného textu i FAISS indexu atd.:
from sentence_transformers import SentenceTransformer
import faiss
from datasets import load_dataset
MODEL_NAME = "paraphrase-MiniLM-L6-v2"
DATASET_ID = "polygraf-ai/human-sentences-1M-sample-v2"
def initialize_model(model_name):
print("Model initialization started")
model = SentenceTransformer(model_name)
print(model)
print("Model initialization finished")
return model
def load_dataset_by_id(dataset_id):
print("Loading dataset started")
dataset = load_dataset(dataset_id, split="train")
print("Loading dataset finished")
return dataset
def build_sentences(dataset, from_, to_):
print("Building sentences")
sentences = [sentence for sentence in dataset["text"][from_:to_]]
print(f"{len(sentences)} sentences created")
return sentences
def create_embeddings(model, sentences):
print("Embedding started")
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
print("Embedding finished")
return embeddings
def create_faiss_index(embeddings):
print("FAISS index construction started")
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
print("FAISS index construction finished")
return index
def find_similar_sentences(model, index, query_sentence, k):
query_embedding = model.encode([query_sentence])
distances, indices = index.search(query_embedding, k)
print("-"*40)
print(f"Query: {query_sentence}")
print(f"Most {k} similar sentences:")
for i, idx in enumerate(indices[0]):
print(f"{i + 1}: {sentences[idx]} (Distance: {distances[0][i]})")
model = initialize_model(MODEL_NAME)
dataset = load_dataset_by_id(DATASET_ID)
sentences = build_sentences(dataset, 0, 1000)
embeddings = create_embeddings(model, sentences)
index = create_faiss_index(embeddings)
find_similar_sentences(model, index, "city", 3)
find_similar_sentences(model, index, "animal", 3)
find_similar_sentences(model, index, "geometry", 3)
find_similar_sentences(model, index, "weather", 3)
find_similar_sentences(model, index, "game", 3)
find_similar_sentences(model, index, "school", 3)
12. Výsledky získané demonstračním příkladem
Podívejme se nyní na výsledky, které byly získány demonstračním příkladem popsaným v předchozí kapitole. Nejprve jsou vypsány informace o tvorbě modelu, embeddingu, indexu atd:
Model initialization started
SentenceTransformer(
(0): Transformer({'max_seq_length': 128, 'do_lower_case': False, 'architecture': 'BertModel'})
(1): Pooling({'word_embedding_dimension': 384, 'pooling_mode_cls_token': False, 'pooling_mode_mean_tokens': True, 'pooling_mode_max_tokens': False, 'pooling_mode_mean_sqrt_len_tokens': False, 'pooling_mode_weightedmean_tokens': False, 'pooling_mode_lasttoken': False, 'include_prompt': True})
)
Model initialization finished
Loading dataset started
Loading dataset finished
Building sentences
1000 sentences created
Embedding started
Embeddings shape: (1000, 384)
Embedding finished
FAISS index construction started
Index: 1000
FAISS index construction finished
Následují výsledky sémantického vyhledávání v prvních tisících větách:
---------------------------------------- Query: city Most 3 similar sentences: 1: Do you gamble that the city will stay quiet for a few hours, or do you risk sending an undermanned team into a dangerous situation? (Distance: 59.321781158447266) 2: "Please respond" said: "Sam - do yourself a favor and contact Pleasanton city management and they will confirm that personnel costs have increased from the 65% range to 77% due to the significant increase of personnel costs in and of themselves." (Distance: 59.33335876464844) 3: Mayor of Hartford and subsequent career Upon the death of John A. Pilgard—who died only nine days after being elected and before he could take office—Spellacy was elected mayor of Hartford in 1935 by the Board of Aldermen. (Distance: 59.40525817871094) ---------------------------------------- Query: animal Most 3 similar sentences: 1: Prolific fly tyer Blane Chocklett of the TFO Advisory Staff, was integral in the design of the “Esox” rod and brings forth a wealth of knowledge from years of chasing toothy, carnivorous fish. (Distance: 55.286163330078125) 2: In contrast to tunicates and echinoderms, the MRCA of vertebrates is thought to have resembled a lancelet, which is pelagic and which has a more advanced nervous system than adult tunicates or echinoderms. (Distance: 56.6212158203125) 3: Rare Alnskan Bird’s Nest and Eggs Found Ornithologists have just succeeded in finding the nest and eggs of the rare surf bird of Alaska, though the bird itself has been known to science for a century and a half. (Distance: 58.14012145996094) ---------------------------------------- Query: geometry Most 3 similar sentences: 1: In the present work we show that this is indeed the case and that for spherically symmetric spacetimes there are several inequivalent representations possible. (Distance: 53.43998718261719) 2: Geometric intuition plays an important role in many aspects of Hilbert space theory. (Distance: 54.873863220214844) 3: To further confirm these projection pulses are able to correctly construct a robust density matrix, a tomographic Rabi Chevron map is performed in Figure 2c,d, combined with the calibration technique described above. (Distance: 56.672767639160156) ---------------------------------------- Query: weather Most 3 similar sentences: 1: In late fall and early winter, they’ve given that heat up, back into the atmosphere. (Distance: 48.415863037109375) 2: Traffic patterns are flown at one specific altitude, usually 800 or 1,000 ft (244 or 305 m) above ground level (AGL). (Distance: 58.13227081298828) 3: Considered an exploratory species Arabian oryx exhibit highly flexible home ranges with large distance migration being observed after rainfall (mostly during spring in Saudi Arabia) while it will contract again during hot and dry periods (e.g. (Distance: 65.33474731445312) ---------------------------------------- Query: game Most 3 similar sentences: 1: But also to give my players a chance to continue playing with the character they are invested in. (Distance: 45.21950912475586) 2: In contrast, Go is ancient board game that consists of simple elements (a line and circle, black and white colors, and stone and wood materials) combined with simple rules that generate subtleties that have enthralled players for millennia \[[@CR5]\]. (Distance: 49.22539138793945) 3: Differing skill levels of players made it work. (Distance: 51.900543212890625) ---------------------------------------- Query: school Most 3 similar sentences: 1: Three of my children have progressed through the PPS (soon my youngest will finish at Allderdice) and I was happy with their middle schools being separate from high school. (Distance: 44.28334045410156) 2: When afternoon school began Mr. Porson placed on the desk before him a packet done up in brown paper. (Distance: 54.15468978881836) 3: In response to these considerations, we propose to conduct an innovative multi-measure longitudinal study of a national sample of medical students in order to examine the impact of medical school factors, independent of individual medical student characteristics, on implicit and explicit racial bias in medical students' judgments and decisions. (Distance: 54.777183532714844)
13. Rychlost sémantického vyhledávání
V praxi je velmi často důležité zajistit, aby samotné sémantické vyhledávání bylo co nejrychlejší, k čemuž v knihovně FAISS slouží několik speciálních datových struktur a algoritmů (blíže se s nimi seznámíme příště). Nepatrnou úpravou demonstračního příkladu můžeme zjistit časy vyhledávání a ty následně vypsat:
from sentence_transformers import SentenceTransformer
import faiss
from datasets import load_dataset
from time import time
MODEL_NAME = "paraphrase-MiniLM-L6-v2"
DATASET_ID = "polygraf-ai/human-sentences-1M-sample-v2"
def initialize_model(model_name):
print("Model initialization started")
model = SentenceTransformer(model_name)
print(model)
print("Model initialization finished")
return model
def load_dataset_by_id(dataset_id):
print("Loading dataset started")
dataset = load_dataset(dataset_id, split="train")
print("Loading dataset finished")
return dataset
def build_sentences(dataset, from_, to_):
print("Building sentences")
sentences = [sentence for sentence in dataset["text"][from_:to_]]
print(f"{len(sentences)} sentences created")
return sentences
def create_embeddings(model, sentences):
print("Embedding started")
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
print("Embedding finished")
return embeddings
def create_faiss_index(embeddings):
print("FAISS index construction started")
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
print("FAISS index construction finished")
return index
def find_similar_sentences(model, index, query_sentence, k):
t1 = time()
query_embedding = model.encode([query_sentence])
distances, indices = index.search(query_embedding, k)
print("-"*40)
print(f"Query: {query_sentence}")
print(f"Most {k} similar sentences:")
for i, idx in enumerate(indices[0]):
print(f"{i + 1}: {sentences[idx]} (Distance: {distances[0][i]})")
t2 = time()
print(f"Finished in {t2-t1:3.2} seconds")
model = initialize_model(MODEL_NAME)
dataset = load_dataset_by_id(DATASET_ID)
sentences = build_sentences(dataset, 0, 100000)
embeddings = create_embeddings(model, sentences)
index = create_faiss_index(embeddings)
find_similar_sentences(model, index, "city", 3)
find_similar_sentences(model, index, "animal", 3)
find_similar_sentences(model, index, "geometry", 3)
find_similar_sentences(model, index, "weather", 3)
find_similar_sentences(model, index, "game", 3)
find_similar_sentences(model, index, "school", 3)
Výsledky:
Model initialization started
SentenceTransformer(
(0): Transformer({'max_seq_length': 128, 'do_lower_case': False, 'architecture': 'BertModel'})
(1): Pooling({'word_embedding_dimension': 384, 'pooling_mode_cls_token': False, 'pooling_mode_mean_tokens': True, 'pooling_mode_max_tokens': False, 'pooling_mode_mean_sqrt_len_tokens': False, 'pooling_mode_weightedmean_tokens': False, 'pooling_mode_lasttoken': False, 'include_prompt': True})
)
Model initialization finished
Loading dataset started
Loading dataset finished
Building sentences
100000 sentences created
Embedding started
Embeddings shape: (100000, 384)
Embedding finished
FAISS index construction started
Index: 100000
FAISS index construction finished
----------------------------------------
Query: city
Most 3 similar sentences:
1: Which is the best city in the world? (Distance: 34.68456268310547)
2: Which city do you come from? (Distance: 36.576637268066406)
3: That’s more than the population of the city. (Distance: 39.577919006347656)
Finished in 0.025 seconds
----------------------------------------
Query: animal
Most 3 similar sentences:
1: The animal comes from an early branch of the mammal family, and like mammals it is covered in fur and produces milk. (Distance: 36.88507843017578)
2: If an animal determines that you are indeed a human its game over. (Distance: 38.494911193847656)
3: State the animal mentioned in the sentence above." (Distance: 39.17326354980469)
Finished in 0.027 seconds
----------------------------------------
Query: geometry
Most 3 similar sentences:
1: One obtains a physical geometry as a deformation of some standard geometry, which is axiomatizable and physical simultaneously. (Distance: 36.97258377075195)
2: Later published in Discrete and Computational Geometry. (Distance: 40.11151123046875)
3: of Lagrange, Euler and collision points on a geometrically unfaithful depiction of the shape sphere S 2 . (Distance: 43.62152862548828)
Finished in 0.025 seconds
----------------------------------------
Query: weather
Most 3 similar sentences:
1: Daytime highs in the winter range between 64 and 75 °F (18 and 24 °C), with overnight lows between 30 and 44 °F (−1 and 7 °C). (Distance: 40.27581787109375)
2: Winters are cool and wet, with summers mild and also wet. (Distance: 40.89495086669922)
3: He sends rain in summer, snow in winter, and all the changes of weather in their season. (Distance: 42.138771057128906)
Finished in 0.031 seconds
----------------------------------------
Query: game
Most 3 similar sentences:
1: What would be the point of continuing the game? (Distance: 36.408992767333984)
2: The game has a lot of varieties that is either a curse or a blessing to the game. (Distance: 39.20246124267578)
3: Great games, but do not underestimate player frustrations. (Distance: 39.954978942871094)
Finished in 0.038 seconds
----------------------------------------
Query: school
Most 3 similar sentences:
1: But nonetheless, school is beginning or already under way for fully one in four American youngsters and adults enrolled in the nation’s more than 95,000 public elementary and secondary schools, 3,200 charter schools and nearly 4,300 degree-granting colleges, as well as for the 1.1 million who are home-schooled. (Distance: 36.799034118652344)
2: A great thing about this school is all of the clubs and activities available. (Distance: 37.57196044921875)
3: It now houses students in grades Year 1 to Year 11 and Kindergarten. (Distance: 38.36991500854492)
Finished in 0.029 seconds
14. Rychlost embeddingu i konstrukce indexu
Časy sémantického vyhledávání, které jsme zjišťovali v předchozím textu, jsou velmi důležité v praxi, ovšem při tvorbě modelů a indexů (což není tak častá operace) je důležité vědět i to, jak dlouho tyto dvě operace trvají. Opět si pro tyto účely vytvoříme jednoduchý benchmark. Tentokrát budeme zjišťovat, kolik času trvá vektorizace n vět i tvorba FAISS indexu z výsledné sady vektorů. Výsledky budou zobrazeny knihovnou Matplotlib pomocí dvojice grafů (každý totiž bude mít zcela odlišné časové měřítko na vertikální ose, proto nemá velký význam vše zobrazit v grafu jediném). Implementace benchmarku vypadá následovně:
from sentence_transformers import SentenceTransformer
import faiss
from datasets import load_dataset
from time import time
import numpy as np
import matplotlib.pyplot as plt
MODEL_NAME = "paraphrase-MiniLM-L6-v2"
DATASET_ID = "polygraf-ai/human-sentences-1M-sample-v2"
def initialize_model(model_name):
print("Model initialization started")
model = SentenceTransformer(model_name)
print(model)
print("Model initialization finished")
return model
def load_dataset_by_id(dataset_id):
print("Loading dataset started")
dataset = load_dataset(dataset_id, split="train")
print("Loading dataset finished")
return dataset
def build_sentences(dataset, from_, to_):
print("Building sentences")
sentences = [sentence for sentence in dataset["text"][from_:to_]]
print(f"{len(sentences)} sentences created")
return sentences
def create_embeddings(model, sentences):
t1 = time()
print("Embedding started")
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
print("Embedding finished")
t2 = time()
return embeddings, t2-t1
def create_faiss_index(embeddings):
t1 = time()
print("FAISS index construction started")
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
print("FAISS index construction finished")
t2 = time()
return index, t2-t1
model = initialize_model(MODEL_NAME)
dataset = load_dataset_by_id(DATASET_ID)
ns = []
ts_embeddings = []
ts_index = []
for n in np.linspace(1000, 10000, 20):
ns.append(n)
sentences = build_sentences(dataset, 0, int(n))
embeddings, t_embeddings = create_embeddings(model, sentences)
index, t_index = create_faiss_index(embeddings)
ts_embeddings.append(t_embeddings)
ts_index.append(t_index)
fig = plt.figure(figsize=(10, 10))
plt.subplot(2, 1, 1)
plt.plot(ns, ts_embeddings, "b-")
plt.title("Embeddings creation")
plt.subplot(2, 1, 2)
plt.plot(ns, ts_index, "m-", label="index creation")
plt.title("Index creation")
# povolení zobrazení mřížky
plt.grid(True)
fig.savefig("embeddings.png")
# zobrazení grafu
fig.show()
15. Výsledky benchmarku
Výsledky benchmarku z předchozí kapitoly (pro 1000 až 10000 vět, tedy pro relativně malé množství dat) jsou zobrazeny na následující dvojici grafů:
Obrázek 1: Výsledek benchmarku – tvorba vektorizovaného textu do podoby vektorů s prvky typu float32
16. Vektory s prvky typu float16 nebo bfloat16
Prozatím jsme při vektorizaci textů vůbec nespecifikovali, jakého typu budou prvky vektorů (na druhou stranu počet prvků určuje model, v našem případě to je 384 prvků). Při výchozím nastavení je pro reprezentaci prvků vektorů použit datový typ float32 neboli IEEE 754 single precision. Alternativně je ovšem možné namísto tohoto typu použít float16 (IEEE 754 half precision) nebo bfloat16 (brain floating point). Tyto datové typy využívají pro uložení numerické hodnoty pouze šestnáct bitů a vektorizovaný text by tak měl být teoreticky poloviční. Ovšem důležitější je, že výpočty s těmito datovými typy budou při použití GPU rychlejší (do jaké míry rychlejší – k tomu se ještě vrátíme). Na druhou stranu při SW výpočtech (Torch CPU) bude pravděpodobně naopak docházet ke zpomalení, zejména pokud nejsou k dispozici příslušná rozšíření instrukční sady (starší mikroprocesory).
Ostatně se o tom můžeme snadno přesvědčit specifikací datového typu float16:
model = SentenceTransformer(model_name, model_kwargs={"torch_dtype": "float16"})
Celý benchmark je upraven do této podoby:
from sentence_transformers import SentenceTransformer
import faiss
from datasets import load_dataset
from time import time
import numpy as np
import matplotlib.pyplot as plt
MODEL_NAME = "paraphrase-MiniLM-L6-v2"
DATASET_ID = "polygraf-ai/human-sentences-1M-sample-v2"
def initialize_model(model_name):
print("Model initialization started")
model = SentenceTransformer(model_name, model_kwargs={"torch_dtype": "float16"})
print(model)
print("Model initialization finished")
return model
def load_dataset_by_id(dataset_id):
print("Loading dataset started")
dataset = load_dataset(dataset_id, split="train")
print("Loading dataset finished")
return dataset
def build_sentences(dataset, from_, to_):
print("Building sentences")
sentences = [sentence for sentence in dataset["text"][from_:to_]]
print(f"{len(sentences)} sentences created")
return sentences
def create_embeddings(model, sentences):
t1 = time()
print("Embedding started")
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
print("Embedding finished")
t2 = time()
return embeddings, t2-t1
def create_faiss_index(embeddings):
t1 = time()
print("FAISS index construction started")
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
print("FAISS index construction finished")
t2 = time()
return index, t2-t1
model = initialize_model(MODEL_NAME)
dataset = load_dataset_by_id(DATASET_ID)
ns = []
ts_embeddings = []
ts_index = []
for n in np.linspace(1000, 10000, 20):
ns.append(n)
sentences = build_sentences(dataset, 0, int(n))
embeddings, t_embeddings = create_embeddings(model, sentences)
index, t_index = create_faiss_index(embeddings)
ts_embeddings.append(t_embeddings)
ts_index.append(t_index)
fig = plt.figure(figsize=(10, 10))
plt.subplot(2, 1, 1)
plt.plot(ns, ts_embeddings, "b-")
plt.title("Embeddings creation")
plt.subplot(2, 1, 2)
plt.plot(ns, ts_index, "m-", label="index creation")
plt.title("Index creation")
# povolení zobrazení mřížky
plt.grid(True)
fig.savefig("embeddings.png")
# zobrazení grafu
fig.show()
17. Výsledky benchmarku
Výsledky benchmarku z předchozí kapitoly jsou zobrazeny na následující dvojici grafů:
Obrázek 2: Výsledek benchmarku – tvorba vektorizovaného textu do podoby vektorů s prvky typu float16. Povšimněte si velkého zpomalení při implementaci na CPU.
18. Velikost sady vektorů i indexu při použití prvků typu float32, float16 a bfloat16
Pro zjištění velikostí vektorizovaného textu i indexu při použití prvků různých typů si upravíme původní skript do následující podoby, v níž se provádí uložení modelu i indexu do souboru, pochopitelně pro každý datový typ zvlášť (embeddings.dump vs. faiss.write_index):
for dtype in ["float32", "float16", "bfloat16"]:
model = initialize_model(MODEL_NAME, dtype)
dataset = load_dataset_by_id(DATASET_ID)
sentences = build_sentences(dataset, 0, 10)
embeddings = create_embeddings(model, sentences)
index = create_faiss_index(embeddings)
embeddings.dump(f"embeddings.{dtype}")
faiss.write_index(index, f"index.{dtype}")
Z výsledků je patrné, že vektorizovaná datová sada je (podle očekávání) zhruba poloviční při použití float16 namísto float32 (23225/11668=1.987080767, tedy přibližně 2.0). Zajímavé je, že pro typ bfloat16 dosahuje velikost 19454 bajtů, což si vyžádá hlubší prozkoumání. Ovšem FAISS indexy jsou stejně velké: 15405 bajtů. Proč tomu tak je? Při výpočtech podobnosti pomocí L2 metriky je vyžadováno 4×d×n bajtů, kde d je dimenze vektoru a n je počet vektorů. V našem konkrétním případě tedy 4×384×10=15360, což po doplnění hlavičky vychází na 15405 bajtů:
| Typ prvků vektorů | Embeggings | FAISS index |
|---|---|---|
| bfloat16 | 19454 | 15405 |
| float16 | 11668 | 15405 |
| float32 | 23225 | 15405 |
Celý skript vypadá následovně:
from sentence_transformers import SentenceTransformer
import faiss
from datasets import load_dataset
MODEL_NAME = "paraphrase-MiniLM-L6-v2"
DATASET_ID = "polygraf-ai/human-sentences-1M-sample-v2"
def initialize_model(model_name, dtype):
print("Model initialization started")
model = SentenceTransformer(model_name, model_kwargs={"torch_dtype": dtype})
print(model)
print("Model initialization finished")
return model
def load_dataset_by_id(dataset_id):
print("Loading dataset started")
dataset = load_dataset(dataset_id, split="train")
print("Loading dataset finished")
return dataset
def build_sentences(dataset, from_, to_):
print("Building sentences")
sentences = [sentence for sentence in dataset["text"][from_:to_]]
print(f"{len(sentences)} sentences created")
return sentences
def create_embeddings(model, sentences):
print("Embedding started")
embeddings = model.encode(sentences)
print(f"Embeddings shape: {embeddings.shape}")
print("Embedding finished")
return embeddings
def create_faiss_index(embeddings):
print("FAISS index construction started")
DIMENSIONS = embeddings.shape[1]
index = faiss.IndexFlatL2(DIMENSIONS)
index.add(embeddings)
print(f"Index: {index.ntotal}")
print("FAISS index construction finished")
return index
for dtype in ["float32", "float16", "bfloat16"]:
model = initialize_model(MODEL_NAME, dtype)
dataset = load_dataset_by_id(DATASET_ID)
sentences = build_sentences(dataset, 0, 1000)
embeddings = create_embeddings(model, sentences)
index = create_faiss_index(embeddings)
embeddings.dump(f"embeddings.{dtype}")
faiss.write_index(index, f"index.{dtype}")
19. Repositář s demonstračními příklady
Demonstrační příklady z předchozího i dnešního článku lze nalézt na následujících odkazech:
Demonstrační příklady vytvořené v Pythonu a popsané v předchozím i v článku FAISS: knihovna pro rychlé a efektivní vyhledávání podobných vektorů (2. část) https://github.com/tisnik/most-popular-python-libs/. Následují odkazy na jednotlivé příklady:
| # | Příklad | Stručný popis | Adresa |
|---|---|---|---|
| 1 | faiss-1.py | seznamy souřadnic bodů v rovině | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-1.py |
| 2 | faiss-2.py | konstrukce matice se souřadnicemi bodů | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-2.py |
| 3 | faiss-3.py | konstrukce indexu pro vyhledávání na základě vzdálenosti | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-3.py |
| 4 | faiss-4.py | nalezení nejbližších bodů k zadaným souřadnicím – výpis indexů nalezených bodů | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-4.py |
| 5 | faiss-5.py | nalezení nejbližších bodů k zadaným souřadnicím – výpis souřadnic nalezených bodů | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-5.py |
| 6 | faiss-6.py | vyhledávání bodů na základě skalárního součinu bez normalizace vektorů | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-6.py |
| 7 | faiss-7.py | vyhledávání bodů na základě skalárního součinu s normalizací vektorů | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-7.py |
| 8 | faiss-8.py | jednoduchý benchmark rychlosti vyhledávání knihovnou FAISS | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-8.py |
| 9 | faiss-9.py | vizualizace koncových bodů vektorů v rovině | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-9.py |
| 10 | faiss-A.py | vykreslení nejpodobnějších vektorů získaných na základě L2 metriky | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-A.py |
| 11 | faiss-B.py | nalezení nejpodobnějších vektorů získaných na základě skalárního součinu: varianta s nenormovanými vektory | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-B.py |
| 12 | faiss-C.py | nalezení nejpodobnějších vektorů získaných na základě skalárního součinu: varianta s normovanými vektory | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-C.py |
| 13 | faiss-D.py | vykreslení nejpodobnějších vektorů před jejich normalizací | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-D.py |
| 14 | faiss-E.py | vykreslení vektorů formou orientovaných šipek | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-E.py |
| 15 | faiss-F.py | vykreslení vektorů po jejich normalizaci formou orientovaných šipek | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-F.py |
| 16 | faiss-G.py | vyhledání a vykreslení nejvíce NEpodobných vektorů | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-G.py |
| 17 | faiss-H.py | vyhledání podobných vektorů se složkami typu float16 | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-H.py |
| 18 | faiss-I.py | jednoduchý benchmark rychlosti vyhledávání knihovnou FAISS: rozdíly mezi float16 a float32 | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/faiss-I.py |
| 19 | pyproject.toml | soubor s projektem a definicí závislostí | https://github.com/tisnik/most-popular-python-libs/blob/master/faiss/pyproject.toml |
20. Odkazy na Internetu
- 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/ - 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 - pgvector: vektorová databáze postavená na Postgresu
https://www.root.cz/clanky/pgvector-vektorova-databaze-postavena-na-postgresu/ - Matplotlib Home Page
http://matplotlib.org/ - matplotlib (Wikipedia)
https://en.wikipedia.org/wiki/Matplotlib - Dot Product
https://mathworld.wolfram.com/DotProduct.html - 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