Co je vektorová databáze a jak ji používají AI agenti
Klasická databáze najde řádek, který přesně odpovídá dotazu. Jenže AI aplikace potřebují něco jiného: najít dokumenty, které jsou dotazu významově podobné — i když nesdílejí jediné slovo. Přesně to umí vektorová databáze. V tomto článku si vysvětlíme, co jsou embeddingy a proč se význam dá měřit vzdáleností, jak funguje HNSW index, který to celé dělá rychlým, čím se liší Qdrant, pgvector a Pinecone — a hlavně: jak vektorové databáze slouží AI agentům jako znalostní báze a dlouhodobá paměť.
Nejkratší mentální model
Embedding převede text na bod v prostoru. Vektorová databáze pak neporovnává slova, ale vzdálenosti mezi body — a díky indexu typu HNSW to zvládne rychle i nad miliony dokumentů.
Proč klasické vyhledávání nestačí
Představte si firemní wiki a dotaz „jak dlouho trvá schválení dovolené“. Relevantní dokument se ale jmenuje „Směrnice o čerpání volna: lhůty pro vyjádření nadřízeného“ — nesdílí s dotazem prakticky žádné slovo. Fulltextové vyhledávání (SQL LIKE, ale i chytřejší BM25) stojí na shodě slov, takže tenhle dokument nenajde. Synonyma, parafráze, překlepy nebo dotaz v jiném jazyce jsou pro něj neviditelné.
Sémantické vyhledávání obchází slova úplně: porovnává významy. A aby se dal význam porovnávat strojově, potřebujeme ho převést na čísla. Tomu převodu se říká embedding.
Embeddingy: text jako bod v prostoru
Embedding model je neuronová síť, která vezme text (slovo, větu, odstavec, klidně i obrázek) a vrátí vektor — seznam stovek až tisíců čísel. Například text-embedding-3-small od OpenAI vrací 1536 čísel, open-source modely jako bge-m3 nebo nomic-embed-text typicky 768–1024. Ten vektor je souřadnice bodu ve vysokorozměrném prostoru a platí v něm jediné, zato zásadní pravidlo: texty s podobným významem leží blízko sebe.
Model se to naučil tréninkem na obrovském množství dvojic souvisejících textů (otázka–odpověď, titulek–článek, věta–parafráze): souvisejícím dvojicím vektory přibližoval, náhodným oddaloval. Výsledný prostor proto zachycuje sémantiku — „dovolená“ leží blízko „volna“, ačkoli jako řetězce nemají nic společného.

Podobnost dvou vektorů se nejčastěji měří kosinovou podobností — kosinem úhlu, který svírají. Hodnota 1 znamená stejný směr (stejný význam), 0 kolmost (nesouvisející texty). Celé sémantické vyhledávání je pak jedna věta: převeď dotaz na vektor a najdi k nejbližších sousedů (k-nearest neighbors, k-NN).
from openai import OpenAI
import numpy as np
client = OpenAI()
def embed(text: str) -> np.ndarray:
response = client.embeddings.create(model="text-embedding-3-small", input=text)
return np.array(response.data[0].embedding) # 1536 cisel
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
return float(a.dot(b) / (np.linalg.norm(a) * np.linalg.norm(b)))
dotaz = embed("jak dlouho trva schvaleni dovolene")
dokument = embed("Smernice o cerpani volna: lhuty pro vyjadreni nadrizeneho")
nesouvisejici = embed("recept na svickovou")
print(cosine_similarity(dotaz, dokument)) # ~0.72 - vysoka podobnost
print(cosine_similarity(dotaz, nesouvisejici)) # ~0.15 - nizka podobnost
Proč na to potřebujeme speciální databázi
Naivní k-NN znamená spočítat podobnost dotazu s každým uloženým vektorem. Při tisících dokumentů v pohodě (a numpy vám bohatě stačí), při milionech je to na každý dotaz miliarda násobení. Vektorové databáze proto používají přibližné hledání sousedů (ANN — approximate nearest neighbors): obětují zlomek přesnosti (recall 95–99 %) výměnou za odpovědi v jednotkách milisekund.
Dominantním algoritmem je dnes HNSW (Hierarchical Navigable Small World) — používají ho Qdrant, Weaviate, pgvector, Milvus i Chroma. Funguje jako vícepatrová mapa: horní patra obsahují jen hrstku bodů s dlouhými „dálničními“ spoji, spodní patro všechny body s krátkými spoji. Hledání startuje nahoře, pár skoky se dostane do správné oblasti prostoru a dole ji dohledá detailně — podobně jako skip-list nebo jako když na mapě nejdřív najdete kraj, pak město a nakonec ulici. Složitost je zhruba logaritmická, daní je index držený v paměti (typicky 2–3× velikost samotných vektorů) a pomalejší zápisy.
Samotný ANN index (třeba knihovna FAISS) ale ještě není databáze. Vektorová databáze k němu přidává to, co v produkci potřebujete:
- Filtrování podle metadat — „najdi podobné dokumenty, ale jen z oddělení HR a mladší než rok“. Zní triviálně, ale kombinace filtru s ANN indexem je algoritmicky zapeklitá a databáze se v ní výrazně liší.
- Hybridní vyhledávání — kombinace sémantického a klíčoslovného (BM25) skóre, typicky přes Reciprocal Rank Fusion. Zachrání vás u přesných termínů, kódů produktů nebo jmen, kde embeddingy selhávají.
- CRUD, perzistence, replikace, multi-tenancy — obyčejný provozní komfort: přidávat a mazat dokumenty za běhu, přežít restart, oddělit data zákazníků.
- Kvantizace — komprese vektorů (int8, binární) ušetří 4–32× paměti za cenu mírné ztráty přesnosti, často s přepočítáním kandidátů v plné přesnosti (rescoring).
Kdo je kdo: přehled hráčů
| Databáze | Charakter | Kdy sáhnout právě po ní |
|---|---|---|
| Chroma | embedded, open source | Prototyp na notebooku, RAG demo, jednotky milionů vektorů. Běží přímo v procesu jako SQLite. |
| pgvector | rozšíření PostgreSQL | Už máte Postgres a data do ~10–50 M vektorů. Žádná nová služba, vektory vedle relačních dat, joiny zadarmo. |
| Qdrant | samostatná DB, Rust, open source | Výkonnostně kritické nasazení, hodně filtrování podle metadat, kvantizace. Snadný self-hosting (jedna binárka/kontejner). |
| Weaviate | samostatná DB, Go, open source | Hybridní vyhledávání (BM25 + vektory) jako klíčový požadavek. |
| Milvus | distribuovaná DB, open source | Miliardy vektorů, oddělené škálování úložiště a výpočtu — za cenu provozu na Kubernetes s řadou závislostí. |
| Pinecone | plně spravovaná služba | Nulový provoz a rychlý start; platíte za dotazy, což při velkém objemu bolí. |
Praktické pravidlo z produkčních srovnání (BirJob 2026, Tensoria benchmark): máte-li Postgres a méně než desítky milionů vektorů, začněte s pgvector — ušetříte si celou jednu službu v architektuře. Dedikovanou vektorovou databázi nasaďte, až když narazíte na měřitelný limit (latence, škála, filtrování). A pro pokusy na notebooku je nejrychlejší cesta Chroma.
Praktická ukázka: Qdrant za pět minut
Následující minimum ukazuje celý cyklus: spustit databázi, vytvořit kolekci, uložit dokumenty s vektory a vyhledat podobné výsledky s filtrem podle metadat.
# lokalni Qdrant v Dockeru
$ docker run -p 6333:6333 -v qdrant_data:/qdrant/storage qdrant/qdrant
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="wiki",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)
# ulozeni dokumentu: vektor + puvodni text + metadata (payload)
client.upsert(
collection_name="wiki",
points=[
PointStruct(
id=1,
vector=embed("Smernice o cerpani volna: nadrizeny se vyjadri do 5 dnu.").tolist(),
payload={"text": "Smernice o cerpani volna...", "oddeleni": "HR", "rok": 2026},
),
# ... dalsi dokumenty
],
)
# semanticke hledani + filtr podle metadat
vysledky = client.query_points(
collection_name="wiki",
query=embed("jak dlouho trva schvaleni dovolene").tolist(),
query_filter=Filter(must=[FieldCondition(key="oddeleni", match=MatchValue(value="HR"))]),
limit=3,
)
for bod in vysledky.points:
print(bod.score, bod.payload["text"])
A pro srovnání totéž v pgvector — vektor je prostě další sloupec a podobnost se počítá SQL operátorem (<=> je kosinová vzdálenost):
CREATE EXTENSION vector;
CREATE TABLE wiki (
id bigserial PRIMARY KEY,
text text,
oddeleni text,
embedding vector(1536)
);
CREATE INDEX ON wiki USING hnsw (embedding vector_cosine_ops);
-- 3 nejpodobnejsi dokumenty z HR
SELECT text, 1 - (embedding <=> :dotaz) AS podobnost
FROM wiki
WHERE oddeleni = 'HR'
ORDER BY embedding <=> :dotaz
LIMIT 3;
Jak vektorovou databázi používají agenti
V článku o AI agentech jsme rozebrali agentní smyčku: model přemýšlí, volá nástroje a vyhodnocuje výsledky. Vektorová databáze v ní hraje dvě odlišné role — a vyplatí se je nezaměňovat.

Role 1: znalostní báze (RAG jako nástroj)
Retrieval-Augmented Generation znamená: než model odpoví, dostane do kontextu relevantní pasáže nalezené ve vektorové databázi. U agentů má RAG typicky podobu nástroje — agent se sám rozhodne, kdy a na co se zeptat, a klidně hledá opakovaně s přeformulovaným dotazem:
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_openai import OpenAIEmbeddings
from langchain_qdrant import QdrantVectorStore
vectorstore = QdrantVectorStore.from_existing_collection(
collection_name="wiki",
embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
url="http://localhost:6333",
)
@tool
def vyhledej_v_dokumentaci(dotaz: str) -> str:
"""Najde pasaze z firemni dokumentace relevantni k dotazu."""
dokumenty = vectorstore.similarity_search(dotaz, k=4)
return "\n\n".join(d.page_content for d in dokumenty)
# agent dostane nastroj a sam rozhoduje, kdy ho pouzit
agent = create_agent(model="openai:gpt-4.1", tools=[vyhledej_v_dokumentaci])
Tady se hodí připomenout U-křivku: nalezené pasáže nevkládejte do promptu v pořadí, v jakém přišly. Nejrelevantnější patří na začátek a konec kontextu, protože uprostřed je model přehlíží. A protože model odpovídá z dodaných pasáží místo z vlastní „paměti vah“, je RAG zároveň nejúčinnější prevencí halucinací.
Role 2: dlouhodobá paměť agenta
Kontextové okno je pracovní paměť: po skončení konverzace zmizí. Aby si agent pamatoval napříč sezeními („uživatel preferuje stručné odpovědi“, „deployment přes GitLab CI jsme už třikrát řešili takhle“), potřebuje vzpomínky někam ukládat — a při další konverzaci si vybavit ty relevantní. Přesné klíče předem neznáte, takže se vzpomínky hledají sémanticky: přesně úloha pro vektorovou databázi.
V praxi se ustálily tři druhy paměti (terminologie z kognitivní psychologie, používá ji LangChain i framework Letta, dříve MemGPT):
- Sémantická — fakta: „zákazník používá PostgreSQL 16 a Azure“.
- Epizodická — zkušenosti: „migrace přes pg_dump u něj minule selhala na rozšířeních“.
- Procedurální — naučené postupy a pravidla chování, často destilované do systémového promptu.
Zápis do paměti může být nástroj, který agent volá sám („tohle si zapamatuj“), nebo proces na pozadí, který po konverzaci extrahuje, co stojí za uložení. Takhle vypadá paměť agenta v LangGraphu — store se sémantickým indexem, nad kterým agent dostane nástroje pro zápis i vybavování:
from langgraph.store.postgres import PostgresStore
from langmem import create_manage_memory_tool, create_search_memory_tool
# store s vektorovym indexem - vzpominky se automaticky embeduji
store = PostgresStore.from_conn_string(
"postgresql://localhost/agent",
index={"dims": 1536, "embed": "openai:text-embedding-3-small"},
)
agent = create_agent(
model="openai:gpt-4.1",
tools=[
vyhledej_v_dokumentaci, # RAG nad znalostmi
create_manage_memory_tool(namespace=("vzpominky",)), # zapis/uprava pameti
create_search_memory_tool(namespace=("vzpominky",)), # semanticke vybaveni
],
store=store,
)
# pozdeji, klidne v jine konverzaci:
vzpominky = store.search(("vzpominky",), query="preference uzivatele ohledne odpovedi")
Za zmínku stojí, že tenhle příklad běží nad obyčejným Postgresem s pgvectorem — další ilustrace toho, že „vektorová databáze“ je dnes spíš schopnost než nutně samostatný produkt.
Úskalí, na která v praxi narazíte
- Chunking rozhoduje o všem. Dokumenty se před uložením dělí na kusy (chunky) — příliš malé ztratí kontext, příliš velké rozmělní význam a zaberou kontextové okno. Začněte na 500–1000 tokenech s překryvem a dělte podle struktury dokumentu (nadpisy, odstavce), ne po znacích.
- Embedding model nejde vyměnit za pochodu. Vektory z různých modelů žijí v nekompatibilních prostorech; změna modelu znamená přeindexovat všechno. Volbu ovlivňuje i podpora češtiny — sáhněte po vícejazyčném modelu (bge-m3, text-embedding-3) a ověřte si kvalitu na MTEB leaderboardu.
- Zastaralá paměť je horší než žádná. Vzpomínky a dokumenty stárnou: směrnice se změní, preference uživatele taky. Ukládejte časová razítka, mažte a konsolidujte — jinak si agent sebevědomě vybaví loňskou pravdu. (Rekapitulace: sebejistá nepravda je přesně mechanismus halucinace, jen tentokrát vlastnoručně vyrobená.) Systémové řešení tohoto problému nabízejí temporální grafové paměti, kterým se věnujeme v navazujícím článku.
- Sémantika není přesnost. Na čísla objednávek, SKU kódy a jména embeddingy nestačí — proto hybridní vyhledávání s BM25. A výsledky retrievalu pravidelně vyhodnocujte (recall na sadě testovacích otázek), ne jen „vypadá to dobře“.
Co s tím v praxi
- Prototyp: Chroma nebo numpy, žádná infrastruktura. Produkce s Postgresem: pgvector. Škála či těžké filtrování: Qdrant. Miliardy vektorů: Milvus. Nechcete provozovat nic: Pinecone.
- RAG dejte agentovi jako nástroj, ne jako natvrdo předřazený krok — agent se umí doptat a přeformulovat dotaz.
- Paměť strukturujte (namespace na uživatele/projekt, typ vzpomínky, timestamp) a od začátku počítejte s mazáním a konsolidací.
- Měřte retrieval zvlášť — většina „halucinací RAG systémů“ jsou ve skutečnosti chyby vyhledávání, ne generování.
Chcete si postavit agenta s pamětí?
Na kurzu Programátor AI agentů stavíme agenty s nástroji, RAG i dlouhodobou pamětí v praxi. Práci s daty, Pythonem a základy AI (včetně embeddings) pokrývá i Datová analýza a umělá inteligence. A pokud chcete embeddingy provozovat na vlastním železe, vyzkoušejte náš GPU Lab.
Zdroje a další čtení
- Malkov, Yashunin: Efficient and robust approximate nearest neighbor search using HNSW graphs — původní paper k HNSW
- LangChain: Long-term memory — paměť agentů nad LangGraph store
- LangMem — nástroje pro správu a vybavování vzpomínek
- Qdrant documentation a pgvector — oficiální dokumentace
- Vector Databases in Production 2026 a 100M Vector Benchmark — produkční srovnání
- MTEB leaderboard — srovnání kvality embedding modelů