ЁЯПл The SchoolтА║ЁЯЧ║я╕П Vector DatabasesтА║ЁЯПГ рдзрдбрд╛ 04 тАФ Nearest neighbors: рд╕рдЧрд│реНрдпрд╛рдВрдирд╛ рд╡рд┐рдЪрд╛рд░рдгреЗ рд╡рд┐рд░реБрджреНрдз shortcut рдирдХрд╛рд╢рд╛
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯПГ рдзрдбрд╛ 04 тАФ Nearest neighbors: рд╕рдЧрд│реНрдпрд╛рдВрдирд╛ рд╡рд┐рдЪрд╛рд░рдгреЗ рд╡рд┐рд░реБрджреНрдз shortcut рдирдХрд╛рд╢рд╛

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 8 рдкреИрдХреА рдзрдбрд╛ 04 ┬╖ рдорд╛рдЧреЗ: lesson-03-similarity ┬╖ рдкреБрдвреЗ: lesson-05-build-a-vector-db


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ03, рдЖрдгрд┐ scaling рдЪреА рдЧреЛрд╖реНрдЯ: exact kNN, рддреНрдпрд╛рд▓рд╛ рдЖрдбрд╡реА рдпреЗрдгрд╛рд░реА рднрд┐рдВрдд, рдЖрдгрд┐ рджрд╣рд╛ рд▓рд╛рдЦ рдЬрд╛рдЧрд╛рдВрдЪреЗ halls milliseconds рдордзреНрдпреЗ рд╢реЛрдзрдгреНрдпрд╛рдЬреЛрдЧреЗ рдХрд░рдгрд╛рд░реЗ ANN indexes (HNSW, IVF).

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

"рдорд╛рдЭреНрдпрд╛рд╕рд╛рд░рдЦреА рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рдЕрд╕рд▓реЗрд▓реА 5 рдореБрд▓реЗ рд╢реЛрдзрд╛."

рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдкрджреНрдзрдд ЁЯЪ╢ (brute-force kNN, рдЖрдкрд▓рд╛ toy рд╣реЗрдЪ рдХрд░рддреЛ): hall рдордзрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдореБрд▓рд╛рдХрдбреЗ рдЬрд╛, рддреБрд▓рдирд╛ рдХрд░рд╛, рд╕рд░реНрд╡реЛрддреНрддрдо 5 рдареЗрд╡рд╛. рдкреВрд░реНрдгрдкрдгреЗ рдмрд░реЛрдмрд░ тАФ рдЖрдгрд┐ рдкреВрд░реНрдгрдкрдгреЗ linear: 7 рдореБрд▓реЗ, рдХреНрд╖рдгрд╛рдд; 7 million рдореБрд▓реЗ ├Ч рдкреНрд░рддреНрдпреЗрдХреА 1,000 рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХтАж рддреБрдордЪреА query рдореНрд╣рд╛рддрд╛рд░реА рд╣реЛрдКрди рдорд░рддреЗ. рд╣реАрдЪ рднрд┐рдВрдд.

Shortcut рдирдХрд╛рд╢рд╛ ЁЯЧ║я╕П (ANN тАФ approximate nearest neighbors): hall рдЧреБрдкрдЪреВрдк рд╕реНрд╡рддрдГрдЪреА рдорд╛рдВрдбрдгреА рдХрд░рддреЛ:

рд╡реЗрдЧрд╛рдЪреА рдХрд┐рдВрдордд: approximate. рдирдХрд╛рд╢рд╛рдХрдбреВрди рдПрдЦрд╛рджрд╛ рдЦрд░рд╛ рд╢реЗрдЬрд╛рд░реА рдЪреБрдХреВ рд╢рдХрддреЛ тАФ рд╣реЗ recall рдиреЗ рдореЛрдЬрд▓реЗ рдЬрд╛рддреЗ ("рдЦрд▒реНрдпрд╛ top-10 рдкреИрдХреА рдЖрдкрдг рдХрд┐рддреА рдкрд░рдд рджрд┐рд▓реЗ?"). рдЦрд░реЗ systems рдПрдХ рдиреЙрдм рдлрд┐рд░рд╡рддрд╛рдд: рдЬрд╛рд╕реНрдд рдореЗрд╣рдирдд тЖФ рдЬрд╛рд╕реНрдд recall. ANN рдереЛрдбрд╛ recall рджреЗрдКрди рдЦреВрдк рд╡реЗрдЧрд╡рд╛рди search рдорд┐рд│рд╡рддреЗ тАФ speed тЖФ recall рдЪрд╛ рдиреЙрдм рддреБрдордЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ data рд╡рд░ tune рдХрд░рд╛ тАФ рдЖрдгрд┐ RAG рд╕рд╛рдареА, рдЬрд╡рд│рдЬрд╡рд│ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рдмрд░реЛрдмрд░ рдпреЗрдгрд╛рд░рд╛ page-finder рдкрд░рд┐рдкреВрд░реНрдгрдкреЗрдХреНрд╖рд╛ рд╡реЗрдЧрд│рд╛ рдУрд│рдЦреВрд╣реА рдпреЗрдд рдирд╛рд╣реА.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart TB
    q["тЭУ query seat"]
    subgraph brute["ЁЯЪ╢ brute force - exact kNN"]
        b1["compare with ALL N seats<br/>N=7: instant ┬╖ N=7M: ЁЯТА"]
    end
    subgraph hnsw["ЁЯЧ║я╕П HNSW - the friendship map"]
        h1["hop: pen-pal jumps first,<br/>local hops last тЖТ log-ish steps"]
    end
    subgraph ivf["ЁЯПШя╕П IVF - the neighborhoods"]
        i1["search only the nearest<br/>few districts"]
    end
    r["ЁЯОп top-k ┬╖ recall dial:<br/>speed тЖФ % of true neighbors found"]
    q --> brute --> r
    q --> hnsw --> r
    q --> ivf --> r

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рд╣рд╛ рдзрдбрд╛ рдореНрд╣рдгрдЬреЗ "рд╣рд╛ database рдХрд╛ рдЖрд╣реЗ, for-loop рдХрд╛ рдирд╛рд╣реА" рдпрд╛ рдкреНрд░рд╢реНрдирд╛рдЪреЗ рд╕рдВрдкреВрд░реНрдг рдЙрддреНрддрд░ тАФ for-loop рдмрд░реЛрдмрд░рдЪ рдЖрд╣реЗ, рдлрдХреНрдд рддреЛ scale рд╣реЛрдд рдирд╛рд╣реА, рдЖрдгрд┐ index рд░рдЪрдирд╛ рд╣реЗрдЪ product рдЖрд╣реЗ. Vendor benchmarks рд╕рд╛рдареА рд╣рд╛ рддреБрдордЪрд╛ рдерд╛рдкрд╛-рдУрд│рдЦрдгрд╛рд░рд╛ рдпрдВрддреНрд░ рдкрдг рдЖрд╣реЗ: "рдХреЛрдгрддреНрдпрд╛ recall рд╡рд░?" рдЕрд╕реЗ рд╡рд┐рдЪрд╛рд░рд╛ рдЖрдгрд┐ рдЦреЛрд▓реА рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рд╣реЛрддрд╛рдирд╛ рдкрд╛рд╣рд╛.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛ тАФ рднрд┐рдВрдд рдЕрдиреБрднрд╡рд╛

python3 - <<'EOF'
import sys, time, random; sys.path.insert(0,'vectordb')
from vectordb import MiniVectorDB
words = ['robot','student','pizza','library','class','lunch','book','teacher']
db = MiniVectorDB()
for i in range(20000):
    db.add(f"d{i}", " ".join(random.choices(words, k=6)))
t = time.time()
db.search("robot library book", k=5)
print(f"brute-force over {len(db):,} chunks: {(time.time()-t)*1000:.0f} ms")
print("now imagine 7 million ├Ч 1536 dims тАФ THAT'S why HNSW exists ЁЯЧ║я╕П")
EOF

тПня╕П рдкреБрдвреЗ

рдпрдВрддреНрд░ рдЙрдШрдбрд╛: vectordb.py, рдкреНрд░рддреНрдпреЗрдХ рдУрд│ тАФ рдЖрдгрд┐ рддреНрдпрд╛рдд рддреБрдордЪреА рдкрд╣рд┐рд▓реА рднрд░.

git checkout lesson-05-build-a-vector-db

ЁЯПГ Lesson 04 тАФ Nearest neighbors: asking everyone vs the shortcut map

ЁЯУН You are here: Lesson 04 of 8 ┬╖ Previous: lesson-03-similarity ┬╖ Next: lesson-05-build-a-vector-db


ЁЯУж What's in this branch

Lessons 01тАУ03, plus the scaling story: exact kNN, the wall it hits, and the ANN indexes (HNSW, IVF) that make million-seat halls searchable in milliseconds.

ЁЯзТ Explain like I'm 5

"Find the 5 kids most similar to me."

The honest way ЁЯЪ╢ (brute-force kNN, what our toy does): walk up to EVERY kid in the hall, compare, keep the best 5. Perfectly correct тАФ and perfectly linear: 7 kids, instant; 7 million kids ├Ч 1,000 coordinates eachтАж your query dies of old age. That's the wall.

The shortcut map ЁЯЧ║я╕П (ANN тАФ approximate nearest neighbors): the hall secretly organizes itself:

The price of speed: approximate. The map might miss a true neighbor тАФ measured as recall ("of the true top-10, how many did we return?"). Real systems tune a dial: more effort тЖФ higher recall. ANN trades some recall for much faster search тАФ tune the speed тЖФ recall dial on your own data тАФ and for RAG, a page-finder that is right nearly every time is indistinguishable from perfect.

ЁЯЧ║я╕П Diagram

flowchart TB
    q["тЭУ query seat"]
    subgraph brute["ЁЯЪ╢ brute force - exact kNN"]
        b1["compare with ALL N seats<br/>N=7: instant ┬╖ N=7M: ЁЯТА"]
    end
    subgraph hnsw["ЁЯЧ║я╕П HNSW - the friendship map"]
        h1["hop: pen-pal jumps first,<br/>local hops last тЖТ log-ish steps"]
    end
    subgraph ivf["ЁЯПШя╕П IVF - the neighborhoods"]
        i1["search only the nearest<br/>few districts"]
    end
    r["ЁЯОп top-k ┬╖ recall dial:<br/>speed тЖФ % of true neighbors found"]
    q --> brute --> r
    q --> hnsw --> r
    q --> ivf --> r

тЭУ What

ЁЯдФ Why

This lesson is the entire "why is this a database and not a for-loop" answer тАФ the for-loop IS correct, it just doesn't scale, and the index structures are the product. It's also your BS-detector for vendor benchmarks: ask "at what recall?" and watch the room get honest.

ЁЯзк Try it тАФ feel the wall

python3 - <<'EOF'
import sys, time, random; sys.path.insert(0,'vectordb')
from vectordb import MiniVectorDB
words = ['robot','student','pizza','library','class','lunch','book','teacher']
db = MiniVectorDB()
for i in range(20000):
    db.add(f"d{i}", " ".join(random.choices(words, k=6)))
t = time.time()
db.search("robot library book", k=5)
print(f"brute-force over {len(db):,} chunks: {(time.time()-t)*1000:.0f} ms")
print("now imagine 7 million ├Ч 1536 dims тАФ THAT'S why HNSW exists ЁЯЧ║я╕П")
EOF

тПня╕П Next

Open the machine: vectordb.py, every line тАФ and your first extension to it.

git checkout lesson-05-build-a-vector-db
тЖР PrevioussimilarityNext тЖТbuild a vector db

This page is the lesson's README from the lesson-04-nearest-neighbors branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.