Wyszukiwanie

Szukaj publikacji

Wpisz co najmniej 2 znaki, aby rozpocząć wyszukiwanie.

    Powrot do wpisow

    Pagefind na statycznym blogu: kiedy fuzzy search zaczyna przeszkadzać

    Felieton o lokalnym wyszukiwaniu Pagefind na statycznym blogu i o momencie, gdy zbyt pomocny fuzzy search zaczął podsuwać przypadkowe wyniki.

    Wyszukiwarka była już gotowa. Problem w tym, że działała aż za dobrze.

    Wpisałem llm. W indeksowanej treści nie było wtedy tej frazy, a mimo to dostałem trzy wpisy o Dockerze i firewallu. Każdy z tytułem, fragmentem i poprawnym linkiem. Wszystko wyglądało wiarygodnie, poza jedną drobną rzeczą: żaden wynik nie był zgodny z prawdą.

    To był moment, w którym przestałem patrzeć na wyszukiwarkę jak na gadżet strony. Pole wyszukiwania potrafi zwrócić coś dla niemal każdego tekstu. Trudniejsza część zaczyna się wtedy, gdy ma także umieć powiedzieć: „tu nic nie ma”.

    Blog jest statycznym projektem Astro na Cloudflare Pages. Nie chciałem do niego dokładać API, bazy, Workera ani usługi SaaS. Pagefind dobrze mieści się w takim układzie: po astro build przechodzi po katalogu dist, buduje indeks, a przeglądarka korzysta z niego lokalnie. Mały mechanizm, bez kolejnej rzeczy do utrzymania.

    Od początku pilnowałem też, by indeks dotyczył wpisów, a nie całej strony. Tytuł, lead, kategoria, tagi i tekst artykułu są przydatne. Header, stopka i nawigacja tylko udają treść, bo powtarzają się wszędzie. To banalne rozróżnienie, ale łatwo o nim zapomnieć, gdy skupia się wyłącznie na tym, czy wyszukiwanie już „działa”.

    Kiedy wynik nie jest odpowiedzią

    Surowe wyszukiwanie dla llm zwróciło wtedy trzy wyniki ze score 3.80, 2.19 i 2.02. Były to teksty o Dockerze, dynamicznym firewallu i publikacji portów. Cytowane zapytanie "llm" zwróciło natomiast zero.

    Nie próbowałem zgadywać, jakiego dokładnie algorytmu używa Pagefind. Nie było to potrzebne. Wystarczyło zobaczyć różnicę między wynikiem podobnym a rzeczywistym wystąpieniem frazy. Miałem wcześniej jeden globalny próg: score od 2 wzwyż przechodził. Brzmiało rozsądnie, dopóki nie zaczęło sugerować tekstów, których nie chciałem czytać.

    Krótkie terminy techniczne są pod tym względem niewygodne. git, api, sql, ssh czy ai zwykle mają znaczyć dokładnie to, co użytkownik wpisał. Nie potrzebują domysłu. Dłuższe, niedokładne zapytania mogą już skorzystać z odrobiny tolerancji.

    Dlatego wyszukiwanie ma dziś prostą politykę:

    < 2 znaki  → nie szukaj
    2–3 znaki → exact
    >= 4 znaki → exact, a potem ewentualny fuzzy fallback
    fuzzy score → minimum 4
    limit → 8 wyników

    Nie jest to rada dla każdego indeksu Pagefind. Ten próg dobrałem na podstawie obecnej zawartości bloga. Zostawia użyteczne skrócone zapytania, a odrzuca słabe dopasowania dla niepasujących haseł czy przestawionych liter. I dobrze. Nie próbuję budować Google’a; wolę nic nie znaleźć niż pokazać kilka przypadkowych wpisów z przekonującym snippetem.

    Dopiero build pokazuje prawdę

    Ta decyzja dostała test regresji, a nie test funkcji na wymyślonych danych testowych. npm run test:search korzysta z gotowego dist/, uruchamia rzeczywisty klient Pagefind i prawdziwy indeks. Celowo niepasujące zapytania dają zero, a llm znajduje już ten wpis dokładnie. Krótkie terminy mają dokładne trafienia, a dłuższe, niedokładne frazy nadal mogą działać sensownie.

    To jest dla mnie ważniejszy fragment całej historii niż sam próg. Indeks jest produktem buildu, więc właśnie jego trzeba sprawdzać. Po większej zmianie zawartości bloga wyniki mogą się przesunąć, a test ma to wychwycić, zanim wyszukiwarka znowu stanie się zbyt uprzejma.

    Przy okazji wyszedł drobiazg z Astro. Wyniki powstają w JavaScripcie, dlatego nie dostają atrybutów scoped CSS obecnych w HTML-u wygenerowanym przy kompilacji. Przez chwilę poprawiałem podkreślenia linków, choć mój selektor w ogóle nie trafiał w dynamiczny DOM. Dopiero podgląd gotowej strony zakończył tę małą, niepotrzebną wędrówkę. Wystarczyło świadomie użyć :global(...) pod kontenerem wyników.

    Wyszukiwarka nadal jest tylko dodatkiem do małego bloga. Ale ten przypadek uświadamia, że system, który zbyt chętnie zgaduje, bywa bardziej mylący od systemu, który uczciwie przyznaje, że nic nie znajduje. Czasem najbardziej wiarygodny wynik to zero.