Get Started

Build a semantic search engine that understands meaning

Keyword search looks for the words you typed. Ask it "how do I protect my laptop on public wifi" and it never finds the note about VPNs, because that note says "encrypted tunnel" and "untrusted network" instead. In this mission you build a search that matches on meaning, so it finds that note anyway. Every piece runs on your own laptop with a small model and no graphics card.

96 minIntermediateTools: FreeStep 1 free
Tested 12 Oct 2026 · sentence-transformers 6.1.0, PyTorch 2.14.1 (CPU, no GPU), numpy 2.5.4, rank-bm25 0.2.2, sqlite-vec 0.1.9, model all-MiniLM-L6-v2, Python 3.13.5, uv 0.11.9, Windows 11
A working semantic search over your own notestype a question in plain words and get back the passages that mean the same thing, ranked with a score, including ones that share none of your words
A real feel for embeddings, cosine similarity, chunking, top-k and hybrid search, so you can tune retrieval instead of guessing at it
One small engine (search.py) you can point at any folder of notes, plus a second version (scale_sqlite.py) that moves the same search into a real vector database for when it grows
Before you start
  • uv, the Python runner used across this site. It fetches Python for you. If you have not got it, Install anything from GitHub safely (Level 0) has the one-line install.
  • You can read a little Python. You do not write any from scratch: every file is complete and in the kit. Run a ChatGPT-style AI on your own laptop is a gentle warm-up if this is your first local-AI lesson.
  • A few GB of free disk space. Almost all of it is PyTorch, which the embedding model runs on; the model itself is about 90MB, and the project's other packages are small.
  • No graphics card, no accounts, no API keys, nothing to pay for. The model runs on your processor.
01/07Why meaning beats keywords, and see it in ten minutes0 done
STEP 01 of 07~12 min

Why meaning beats keywords, and see it in ten minutes

Keyword search matches letters. Meaning search matches sense. Get the whole thing running first, then take it apart.

  1. Every search box you have ever used, from a text editor to a wiki, works the same way: it looks for the words you typed. Type "wifi" and it finds pages with "wifi" on them. That breaks the moment the page uses different words for the same idea. A note explaining how a VPN keeps you safe on a cafe network might never contain the words "wifi", "laptop" or "protect", so a keyword search for "how do I protect my laptop on public wifi" walks straight past the one note that answers it.

  2. A semantic search fixes that. It turns each passage into a list of numbers that stands for its meaning, does the same to your question, and returns the passages whose meaning sits closest. This mission builds that, end to end, over a folder of plain notes. It is deliberately not a chatbot: there is no model writing answers, no made-up text, nothing to upload. It is the retrieval engine that sits underneath tools like Build your own "chat with my files" app, shown on its own so you can see exactly how it ranks things.

  3. Download the four kit files into a new folder. Save search.py, scale_sqlite.py and requirements.txt in the folder itself, and notes.md inside a sub-folder called corpus. Then set it up and run the headline comparison:

    Windows
    cd $HOME\Documents
    mkdir semantic-search; cd semantic-search
    # put search.py, scale_sqlite.py and requirements.txt here, and notes.md in a corpus\ sub-folder
    uv venv --python 3.13
    uv pip install -r requirements.txt
    uv run search.py build
    uv run search.py compare "how do I protect my laptop on public wifi"
    Mac / Linux
    cd ~/Documents
    mkdir semantic-search && cd semantic-search
    # put search.py, scale_sqlite.py and requirements.txt here, and notes.md in a corpus/ sub-folder
    uv venv --python 3.13
    uv pip install -r requirements.txt
    uv run search.py build
    uv run search.py compare "how do I protect my laptop on public wifi"
  4. build cuts the notes into chunks and turns each one into numbers (the first run downloads the 90MB model, so give it a minute). compare then runs the same question two ways, keyword first, meaning second:

    Output
    KEYWORD  "how do I protect my laptop on public wifi"
      1.   1.601  notes.md #7  ## Why a laptop feels slow Most of the time the disk is the bottleneck, not the processor....
      2.   0.000  notes.md #1  # Field notes: staying private and keeping your computer working FICTIONAL SAMPLE DOCUMENT...
      3.   0.000  notes.md #3  ## Password managers A password manager invents a long random secret for every account and...
    
    MEANING  "how do I protect my laptop on public wifi"
      1.   0.425  notes.md #2  ## Tunnelling your traffic on an untrusted network A virtual private network routes everyt...
      2.   0.139  notes.md #3  ## Password managers A password manager invents a long random secret for every account and...
      3.   0.097  notes.md #1  # Field notes: staying private and keeping your computer working FICTIONAL SAMPLE DOCUMENT...
  5. That is the whole point of the lesson in one screen. Keyword search put the note titled "Why a laptop feels slow" on top, because it contains the word "laptop", and then scored 0.000 for everything else: it could not see the VPN note at all. Meaning search put the VPN note ("Tunnelling your traffic on an untrusted network") first, even though that note never says wifi, laptop or protect. The rest of the lesson takes this apart so you can tune it and point it at your own notes.

    TipThe scores in the two blocks are not on the same scale and should not be compared with each other. Keyword scores (BM25) have no fixed ceiling; meaning scores (cosine) run from about -1 to 1. Each column ranks within itself. Step 5 reads both properly.
✓
CheckpointThe MEANING block puts notes.md #2 (the tunnelling note) first, and the KEYWORD block scores it nowhere.
If it breaks'uv' is not recognised + 2 more
'uv' is not recognised
Install it with winget install --id astral-sh.uv -e (Windows) or curl -LsSf https://astral.sh/uv/install.sh | sh (Mac or Linux), then open a new terminal. Full walkthrough in Install anything from GitHub.
'No .md or .txt files in ...corpus'
notes.md is in the wrong place. It must be inside a corpus sub-folder of the project, not next to search.py. Make the folder and move it there.
The first build sits still for a long time
It is downloading the model (about 90MB) and loading PyTorch, which is slow the first time on a processor. Later runs skip the download. Step 2 explains what is happening.
Still stuck? Ask the community
Next mission · AI engineeringAsk your database questions in plain English
→